001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)LockManager.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: /**
030: * LockManager.java
031: *
032: * SUN PROPRIETARY/CONFIDENTIAL.
033: * This software is the proprietary information of Sun Microsystems, Inc.
034: * Use is subject to license terms.
035: *
036: * Created on January 2, 2006, 4:49 PM
037: */package com.sun.jbi.management.util;
038:
039: import com.sun.jbi.StringTranslator;
040: import com.sun.jbi.management.registry.RegistryException;
041: import com.sun.jbi.management.LocalStringKeys;
042: import com.sun.jbi.management.system.ManagementContext;
043:
044: import java.util.concurrent.locks.ReentrantReadWriteLock;
045: import java.util.concurrent.TimeUnit;
046: import java.util.logging.Logger;
047: import java.util.logging.Level;
048:
049: /**
050: * Utility class to manage the acquition and release of a ReentrantReadWrite Lock.
051: *
052: * @author Sun Microsystems, Inc
053: */
054: public class LockManager {
055:
056: /**
057: * The ReentrantReadWriteLock
058: */
059: private ReentrantReadWriteLock mLock;
060:
061: /**
062: * The Logger
063: */
064: private Logger mLogger;
065:
066: /**
067: * Lock Name.
068: */
069: private String mLockName;
070:
071: /**
072: * The Waiting Time to acquire a Lock, 60 seconds
073: */
074: private static long DEFAULT_LOCK_WAIT_INTERVAL = 60;
075:
076: /**
077: * String Translator
078: */
079: private StringTranslator mTranslator;
080:
081: /**
082: * Actual Lock Interval
083: */
084: private long mLockWaitInterval;
085:
086: /**
087: *
088: */
089: static final String STRING_TRANSLATOR_NAME = "com.sun.jbi.management";
090:
091: /**
092: * Creates a new instance of LockManager
093: *
094: * @param lock - the ReentrantReadWriteLock to be managed
095: * @param lockName - user friendly name for the lock
096: * @param ctx - management context
097: * @param lockInterval - secons to wait for acquiring a registry read/write lock.
098: */
099: public LockManager(ReentrantReadWriteLock lock, String lockName,
100: ManagementContext ctx, String lockInterval) {
101: mLock = lock;
102: mLockName = lockName;
103: mLogger = ctx.getLogger();
104:
105: mTranslator = ctx.getEnvironmentContext().getStringTranslator(
106: STRING_TRANSLATOR_NAME);
107:
108: if (lockInterval == null) {
109: mLockWaitInterval = DEFAULT_LOCK_WAIT_INTERVAL;
110: } else {
111: try {
112: mLockWaitInterval = Long.parseLong(lockInterval);
113: } catch (NumberFormatException nex) {
114: mLockWaitInterval = DEFAULT_LOCK_WAIT_INTERVAL;
115: }
116: }
117: mLogger.fine("Lock wait interval for lock " + lockName + " is "
118: + mLockWaitInterval + " seconds.");
119: }
120:
121: /**
122: * Acquire Read Lock
123: *
124: * @throws a RegistryException if a Read Lock cannot be obtained after waiting
125: * for the lock interval
126: */
127: public void acquireReadLock() throws RegistryException {
128: if (mLogger.getLevel() == Level.FINEST) {
129: mLogger.finest(mTranslator.getString(
130: LocalStringKeys.JBI_ADMIN_ATTEMPT_READ_LOCK, Thread
131: .currentThread().getName(),
132: getCallerInformation(), mLockName));
133: }
134:
135: boolean acquired = false;
136:
137: try {
138: acquired = mLock.readLock().tryLock(mLockWaitInterval,
139: TimeUnit.SECONDS);
140: } catch (InterruptedException iex) {
141: acquired = false;
142: }
143:
144: if (!acquired) {
145:
146: if (mLogger.getLevel() == Level.FINEST) {
147: mLogger
148: .finest(mTranslator
149: .getString(
150: LocalStringKeys.JBI_ADMIN_THREAD_FAILED_ACQUIRE_READ_LOCK,
151: Thread.currentThread()
152: .getName(),
153: getCallerInformation(),
154: mLockName, new Long(
155: mLockWaitInterval)
156: .toString()));
157: }
158:
159: throw new RegistryException(mTranslator.getString(
160: LocalStringKeys.JBI_ADMIN_FAILED_ACQUIRE_READ_LOCK,
161: Thread.currentThread().getName(),
162: getCallerInformation(), mLockName));
163:
164: } else {
165: if (mLogger.getLevel() == Level.FINEST) {
166: mLogger.finest(mTranslator.getString(
167: LocalStringKeys.JBI_ADMIN_ACQUIRED_READ_LOCK,
168: Thread.currentThread().getName(),
169: getCallerInformation(), mLockName));
170: }
171: }
172:
173: }
174:
175: /**
176: * Acquire write lock to the in-memory registry lock.
177: *
178: * @throws a RegistryException if a Write Lock cannot be obtained after waiting
179: * for the lock wait interval
180: */
181: public void acquireWriteLock() throws RegistryException {
182: if (mLogger.getLevel() == Level.FINEST) {
183: mLogger.finest(mTranslator.getString(
184: LocalStringKeys.JBI_ADMIN_ATTEMPT_WRITE_LOCK,
185: Thread.currentThread().getName(),
186: getCallerInformation(), mLockName));
187:
188: }
189:
190: boolean acquired = false;
191:
192: try {
193: acquired = mLock.writeLock().tryLock(mLockWaitInterval,
194: TimeUnit.SECONDS);
195: } catch (InterruptedException iex) {
196: acquired = false;
197: }
198:
199: if (!acquired) {
200:
201: if (mLogger.getLevel() == Level.FINEST) {
202: mLogger
203: .finest(mTranslator
204: .getString(
205: LocalStringKeys.JBI_ADMIN_THREAD_FAILED_ACQUIRE_WRITE_LOCK,
206: Thread.currentThread()
207: .getName(),
208: getCallerInformation(),
209: mLockName, new Long(
210: mLockWaitInterval)
211: .toString()));
212: }
213:
214: throw new RegistryException(
215: mTranslator
216: .getString(
217: LocalStringKeys.JBI_ADMIN_FAILED_ACQUIRE_WRITE_LOCK,
218: Thread.currentThread().getName(),
219: getCallerInformation(), mLockName));
220: } else {
221: if (mLogger.getLevel() == Level.FINEST) {
222: mLogger.finest(mTranslator.getString(
223: LocalStringKeys.JBI_ADMIN_ACQUIRED_WRITE_LOCK,
224: Thread.currentThread().getName(),
225: getCallerInformation(), mLockName));
226: }
227: }
228: }
229:
230: /**
231: * Release Read Lock
232: */
233: public void releaseReadLock() {
234:
235: mLock.readLock().unlock();
236: if (mLogger.getLevel() == Level.FINEST) {
237: mLogger.finest(mTranslator.getString(
238: LocalStringKeys.JBI_ADMIN_RELEASED_READ_LOCK,
239: Thread.currentThread().getName(),
240: getCallerInformation(), mLockName));
241: }
242:
243: }
244:
245: /**
246: * Release write lock
247: */
248: public void releaseWriteLock() {
249: if (mLock.isWriteLockedByCurrentThread()) {
250: mLock.writeLock().unlock();
251:
252: if (mLogger.getLevel() == Level.FINEST) {
253: mLogger.finest(mTranslator.getString(
254: LocalStringKeys.JBI_ADMIN_RELEASED_WRITE_LOCK,
255: Thread.currentThread().getName(),
256: getCallerInformation(), mLockName));
257: }
258: }
259:
260: }
261:
262: /**
263: * Downgrade Write Lock
264: *
265: * @throws RegistryException if the Read Lock cannot be acquired.
266: */
267: public void downgradeWriteLock() throws RegistryException {
268:
269: if (mLogger.getLevel() == Level.FINEST) {
270: mLogger.finest(mTranslator.getString(
271: LocalStringKeys.JBI_ADMIN_ATTEMPT_DOWNGRADE_LOCK,
272: Thread.currentThread().getName(),
273: getCallerInformation(), mLockName));
274: }
275: acquireReadLock();
276: releaseWriteLock();
277:
278: if (mLogger.getLevel() == Level.FINEST) {
279: mLogger.finest(mTranslator.getString(
280: LocalStringKeys.JBI_ADMIN_DOWNGRADED_LOCK, Thread
281: .currentThread().getName(),
282: getCallerInformation(), mLockName));
283: }
284: }
285:
286: /**
287: * @return a String with information on the caller Class, Method and LineNumber
288: */
289: private String getCallerInformation() {
290: StackTraceElement[] callStack = Thread.currentThread()
291: .getStackTrace();
292: StringBuffer strBuf = new StringBuffer();
293: if (callStack.length >= 5) {
294: StackTraceElement top = callStack[4];
295: strBuf.append("[ Class: ");
296: strBuf.append(top.getClassName());
297: strBuf.append(", Method: ");
298: strBuf.append(top.getMethodName());
299: strBuf.append(", Line: ");
300: strBuf.append(top.getLineNumber());
301: strBuf.append("]");
302: }
303: return strBuf.toString();
304: }
305:
306: }
|