001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.objectserver.lockmanager.impl;
006:
007: import com.tc.async.api.Sink;
008: import com.tc.exception.ImplementMe;
009: import com.tc.logging.CustomerLogging;
010: import com.tc.logging.TCLogger;
011: import com.tc.logging.TCLogging;
012: import com.tc.management.L2LockStatsManager;
013: import com.tc.net.groups.NodeID;
014: import com.tc.object.lockmanager.api.LockContext;
015: import com.tc.object.lockmanager.api.LockID;
016: import com.tc.object.lockmanager.api.LockLevel;
017: import com.tc.object.lockmanager.api.ThreadID;
018: import com.tc.object.lockmanager.api.TryLockContext;
019: import com.tc.object.lockmanager.api.WaitContext;
020: import com.tc.object.lockmanager.api.WaitTimer;
021: import com.tc.object.lockmanager.api.WaitTimerCallback;
022: import com.tc.object.lockmanager.impl.WaitTimerImpl;
023: import com.tc.object.net.DSOChannelManager;
024: import com.tc.object.tx.WaitInvocation;
025: import com.tc.objectserver.lockmanager.api.DeadlockChain;
026: import com.tc.objectserver.lockmanager.api.DeadlockResults;
027: import com.tc.objectserver.lockmanager.api.LockEventListener;
028: import com.tc.objectserver.lockmanager.api.LockMBean;
029: import com.tc.objectserver.lockmanager.api.LockManager;
030: import com.tc.objectserver.lockmanager.api.LockManagerMBean;
031: import com.tc.objectserver.lockmanager.api.LockWaitContext;
032: import com.tc.objectserver.lockmanager.api.NotifiedWaiters;
033: import com.tc.objectserver.lockmanager.api.TCIllegalMonitorStateException;
034: import com.tc.util.Assert;
035:
036: import java.util.ArrayList;
037: import java.util.Collection;
038: import java.util.HashMap;
039: import java.util.HashSet;
040: import java.util.Iterator;
041: import java.util.List;
042: import java.util.Map;
043: import java.util.Set;
044:
045: /**
046: * Server representation of lock management. We will need to keep track of what locks are checkedout, who has the lock
047: * and who wants the lock
048: *
049: * @author steve
050: */
051: public class LockManagerImpl implements LockManager, LockManagerMBean,
052: WaitTimerCallback {
053: private static final TCLogger logger = TCLogging
054: .getLogger(LockManagerImpl.class);
055: private static final TCLogger clogger = CustomerLogging
056: .getDSOGenericLogger();
057:
058: public static final LockManagerErrorDescription NOT_STARTING_ERROR = new LockManagerErrorDescription(
059: "NOT STARTING");
060: public static final LockManagerErrorDescription NOT_STARTED_ERROR = new LockManagerErrorDescription(
061: "NOT STARTED");
062: public static final LockManagerErrorDescription IS_STARTING_ERROR = new LockManagerErrorDescription(
063: "IS STARTING");
064: public static final LockManagerErrorDescription IS_STOPPED_ERROR = new LockManagerErrorDescription(
065: "IS STOPPED");
066:
067: public static final LockManagerErrorDescription LOCK_ALREADY_GRANTED_ERROR = new LockManagerErrorDescription(
068: "LOCK ALREADY GRANTED");
069:
070: public static final int UNINITIALIZED_LOCK_POLICY = 0x00;
071: public static final int GREEDY_LOCK_POLICY = 0x01;
072: public static final int ALTRUISTIC_LOCK_POLICY = 0x02;
073:
074: private static final State STARTING = new State("STARTING");
075: private static final State STARTED = new State("STARTED");
076: private static final State STOPPING = new State("STOPPING");
077: private static final State STOPPED = new State("STOPPED");
078:
079: private State status = STARTING;
080: private final Map locks = new HashMap();
081: private final LockEventListener lockTimer;
082: private final DSOChannelManager channelManager;
083: private final LockEventListener[] lockListeners;
084: private final WaitTimer waitTimer;
085:
086: // XXX: These lock timeout/policy needs to be configurable-- probably per lock...
087: private final long lockTimeout = 1000 * 60 * 2;
088: private int lockPolicy = UNINITIALIZED_LOCK_POLICY;
089: // private int lockPolicy = ALTRUISTIC_LOCK_POLICY;
090:
091: private final List lockRequestQueue = new ArrayList();
092: private final ServerThreadContextFactory threadContextFactory = new ServerThreadContextFactory();
093: private final L2LockStatsManager lockStatsManager;
094:
095: public LockManagerImpl(DSOChannelManager channelManager,
096: L2LockStatsManager lockStatsManager) {
097: this .channelManager = channelManager;
098:
099: // Replacing real lock timer with a null lock timer until the OOP stuff is
100: // put in for real --Orion 2/24/2005
101: // this.lockTimer = new LockTimer(this.channelManager);
102: this .lockTimer = new NullLockTimer();
103: this .lockListeners = new LockEventListener[] { this .lockTimer };
104:
105: // This could maybe be combined with the lock timeout stuff, but for now
106: // just use a dedicated Timer instance
107: this .waitTimer = new WaitTimerImpl();
108: this .lockStatsManager = lockStatsManager;
109: }
110:
111: public synchronized void dump() {
112: StringBuffer buf = new StringBuffer("LockManager");
113: buf.append("locks=" + locks).append("\n");
114: buf.append("/LockManager").append("\n");
115: System.err.println(buf.toString());
116: }
117:
118: public synchronized int getLockCount() {
119: return this .locks.size();
120: }
121:
122: public synchronized int getThreadContextCount() {
123: return this .threadContextFactory.getCount();
124: }
125:
126: public synchronized void enableClientStat(LockID lockID, Sink sink,
127: int stackTraceDepth, int statCollectFrequency) {
128: assertNotStarting();
129: assertNotStopped();
130:
131: Lock lock = getLockFor(lockID);
132: if (lock != Lock.NULL_LOCK) {
133: lock.enableClientStat(sink, stackTraceDepth,
134: statCollectFrequency);
135: }
136: }
137:
138: public synchronized void disableClientStat(LockID lockID,
139: Set statEnabledClients, Sink sink) {
140: assertNotStarting();
141: assertNotStopped();
142:
143: Lock lock = getLockFor(lockID);
144: if (lock != Lock.NULL_LOCK) {
145: lock.disableClientStat(statEnabledClients, sink);
146: }
147: }
148:
149: public synchronized void verify(NodeID nodeID, LockID[] lockIDs) {
150: if (!isStarted()) {
151: return;
152: }
153: for (int i = 0; i < lockIDs.length; i++) {
154: Lock lock = (Lock) locks.get(lockIDs[i]);
155: if (lock == null) {
156: String errorMsg = " Lock is not held for " + lockIDs[i]
157: + ". Not by " + nodeID
158: + ". Not by anyone. uhm... Nada";
159: logger.warn(errorMsg);
160: throw new AssertionError(errorMsg);
161: }
162: if (!lock.holdsSomeLock(nodeID)) {
163: throw new AssertionError(" Lock " + lockIDs[i]
164: + " is not held by anyone in " + nodeID);
165: }
166: }
167: }
168:
169: public synchronized void reestablishLock(LockID lockID, NodeID nid,
170: ThreadID sourceID, int requestedLevel, Sink lockResponseSink) {
171: assertStarting();
172: ServerThreadContext threadContext = threadContextFactory
173: .getOrCreate(nid, sourceID);
174: Lock lock = (Lock) this .locks.get(lockID);
175:
176: if (lock == null) {
177: lock = new Lock(lockID, threadContext, this .lockTimeout,
178: this .lockListeners, this .lockPolicy,
179: threadContextFactory, lockStatsManager);
180: locks.put(lockID, lock);
181: }
182: lock.reestablishLock(threadContext, requestedLevel,
183: lockResponseSink);
184: }
185:
186: public synchronized boolean tryRequestLock(LockID lockID,
187: NodeID nodeID, ThreadID sourceID, int requestedLevel,
188: WaitInvocation timeout, Sink lockResponseSink) {
189: return requestLock(lockID, nodeID, sourceID, requestedLevel,
190: timeout, lockResponseSink, true);
191: }
192:
193: private synchronized boolean requestLock(LockID lockID,
194: NodeID nodeID, ThreadID threadID, int requestedLevel,
195: WaitInvocation timeout, Sink lockResponseSink,
196: boolean noBlock) {
197: if (!channelManager.isActiveID(nodeID))
198: return false;
199: if (isStarting()) {
200: queueRequestLock(lockID, nodeID, threadID, requestedLevel,
201: timeout, lockResponseSink, noBlock);
202: return false;
203: }
204: if (!isStarted())
205: return false;
206: return basicRequestLock(lockID, nodeID, threadID,
207: requestedLevel, timeout, lockResponseSink, noBlock);
208: }
209:
210: public synchronized boolean requestLock(LockID lockID,
211: NodeID nodeID, ThreadID sourceID, int requestedLevel,
212: Sink lockResponseSink) {
213: return requestLock(lockID, nodeID, sourceID, requestedLevel,
214: null, lockResponseSink, false);
215: }
216:
217: private boolean basicRequestLock(LockID lockID, NodeID nodeID,
218: ThreadID threadID, int requestedLevel,
219: WaitInvocation timeout, Sink lockResponseSink,
220: boolean noBlock) {
221: ServerThreadContext threadContext = threadContextFactory
222: .getOrCreate(nodeID, threadID);
223: Lock lock = (Lock) this .locks.get(lockID);
224:
225: boolean lockAwarded = false;
226: if (lock != null) {
227: if (noBlock) {
228: lockAwarded = lock.tryRequestLock(threadContext,
229: requestedLevel, timeout, waitTimer, this ,
230: lockResponseSink);
231: } else {
232: lockAwarded = lock.requestLock(threadContext,
233: requestedLevel, lockResponseSink);
234: }
235: } else {
236: lock = new Lock(lockID, threadContext, requestedLevel,
237: lockResponseSink, this .lockTimeout,
238: this .lockListeners, this .lockPolicy,
239: threadContextFactory, lockStatsManager);
240: locks.put(lockID, lock);
241: lockAwarded = true;
242: }
243:
244: return lockAwarded;
245: }
246:
247: private void queueRequestLock(LockID lockID, NodeID nodeID,
248: ThreadID threadID, int requestedLevel,
249: WaitInvocation timeout, Sink lockResponseSink,
250: boolean noBlock) {
251: if (timeout == null) {
252: lockRequestQueue
253: .add(new RequestLockContext(lockID, nodeID,
254: threadID, requestedLevel, lockResponseSink,
255: noBlock));
256: } else {
257: lockRequestQueue.add(new RequestLockContext(lockID, nodeID,
258: threadID, requestedLevel, timeout,
259: lockResponseSink, noBlock));
260: }
261: }
262:
263: public synchronized void queryLock(LockID lockID, NodeID cid,
264: ThreadID threadID, Sink lockResponseSink) {
265: assertNotStarting();
266: if (!isStarted())
267: return;
268:
269: Lock lock = getLockFor(lockID);
270: ServerThreadContext threadContext = threadContextFactory
271: .getOrCreate(cid, threadID);
272: lock.queryLock(threadContext, lockResponseSink);
273: }
274:
275: public synchronized void interrupt(LockID lockID, NodeID cid,
276: ThreadID threadID) {
277: assertNotStarting();
278: if (!isStarted())
279: return;
280:
281: Lock lock = getLockFor(lockID);
282: ServerThreadContext threadContext = threadContextFactory
283: .getOrCreate(cid, threadID);
284: lock.interrupt(threadContext);
285: }
286:
287: public synchronized void unlock(LockID id, NodeID channelID,
288: ThreadID threadID) {
289: assertNotStarting();
290: if (!isStarted())
291: return;
292:
293: Lock l = getLockFor(id);
294: if (l.isNull()) {
295: logger
296: .warn("An attempt was made to unlock:"
297: + id
298: + " for channelID:"
299: + channelID
300: + " This lock was not held. This could be do to that node being down so it may not be an error.");
301: return;
302: }
303: basicUnlock(l, threadContextFactory.getOrCreate(channelID,
304: threadID));
305: }
306:
307: public synchronized void wait(LockID lid, NodeID cid, ThreadID tid,
308: WaitInvocation call, Sink lockResponseSink) {
309: assertNotStopped();
310: Lock lock = (Lock) this .locks.get(lid);
311: if (lock != null) {
312: ServerThreadContext threadContext = threadContextFactory
313: .getOrCreate(cid, tid);
314: try {
315: lock.wait(threadContext, waitTimer, call, this ,
316: lockResponseSink);
317: notifyAll();
318: } catch (TCIllegalMonitorStateException e) {
319: e.printStackTrace();
320: // XXX: send error response back to client
321: throw new ImplementMe();
322: }
323: } else {
324: // XXX: lock doesn't exist...this is bad ;-)
325: throw new ImplementMe();
326: }
327: }
328:
329: public synchronized void reestablishWait(LockID lid, NodeID cid,
330: ThreadID tid, int lockLevel, WaitInvocation call,
331: Sink lockResponseSink) {
332: assertStarting();
333: Lock lock = (Lock) this .locks.get(lid);
334: ServerThreadContext threadContext = threadContextFactory
335: .getOrCreate(cid, tid);
336: if (lock == null) {
337: lock = new Lock(lid, threadContext, this .lockTimeout,
338: this .lockListeners, this .lockPolicy,
339: threadContextFactory, lockStatsManager);
340: locks.put(lid, lock);
341: }
342: lock.reestablishWait(threadContext, call, lockLevel,
343: lockResponseSink);
344: }
345:
346: public synchronized void recallCommit(LockID lid, NodeID cid,
347: Collection lockContexts, Collection waitContexts,
348: Collection pendingLockContexts,
349: Collection pendingTryLockContexts, Sink lockResponseSink) {
350: assertNotStarting();
351: if (!channelManager.isActiveID(cid)) {
352: logger
353: .warn("Ignoring Recall Commit message from disconnected client : "
354: + cid + " : Lock ID : " + lid);
355: return;
356: }
357: Lock lock = (Lock) this .locks.get(lid);
358: Assert.assertNotNull(lock);
359:
360: synchronized (lock) {
361: for (Iterator i = lockContexts.iterator(); i.hasNext();) {
362: LockContext ctxt = (LockContext) i.next();
363: ServerThreadContext threadContext = threadContextFactory
364: .getOrCreate(cid, ctxt.getThreadID());
365: lock.addRecalledHolder(threadContext, ctxt
366: .getLockLevel());
367: }
368:
369: for (Iterator i = waitContexts.iterator(); i.hasNext();) {
370: WaitContext ctxt = (WaitContext) i.next();
371: ServerThreadContext threadContext = threadContextFactory
372: .getOrCreate(cid, ctxt.getThreadID());
373: lock.addRecalledWaiter(threadContext, ctxt
374: .getWaitInvocation(), ctxt.getLockLevel(),
375: lockResponseSink, waitTimer, this );
376: }
377:
378: for (Iterator i = pendingLockContexts.iterator(); i
379: .hasNext();) {
380: LockContext ctxt = (LockContext) i.next();
381: ServerThreadContext threadContext = threadContextFactory
382: .getOrCreate(cid, ctxt.getThreadID());
383: lock.addRecalledPendingRequest(threadContext, ctxt
384: .getLockLevel(), lockResponseSink);
385: }
386:
387: for (Iterator i = pendingTryLockContexts.iterator(); i
388: .hasNext();) {
389: TryLockContext ctxt = (TryLockContext) i.next();
390: ServerThreadContext threadContext = threadContextFactory
391: .getOrCreate(cid, ctxt.getThreadID());
392: lock.addRecalledTryLockPendingRequest(threadContext,
393: ctxt.getLockLevel(), ((WaitContext) ctxt)
394: .getWaitInvocation(), lockResponseSink,
395: waitTimer, this );
396: }
397:
398: ServerThreadContext threadContext = threadContextFactory
399: .getOrCreate(cid, ThreadID.VM_ID);
400: if (lock.recallCommit(threadContext)) {
401: locks.remove(lid);
402: threadContextFactory.removeIfClear(threadContext);
403: }
404: }
405: }
406:
407: public void waitTimeout(Object callbackObject) {
408: synchronized (this ) {
409: if (isStarted()
410: && callbackObject instanceof LockWaitContext) {
411: LockWaitContext context = (LockWaitContext) callbackObject;
412: context.waitTimeout();
413: } else {
414: logger.warn("Ignoring wait timeout for : "
415: + callbackObject);
416: }
417: }
418: }
419:
420: public synchronized void notify(LockID lid, NodeID cid,
421: ThreadID tid, boolean all,
422: NotifiedWaiters addNotifiedWaitersTo) {
423: // assertStarted();
424: if (!isStarted()) {
425: if (isStarting()) {
426: throw new AssertionError(
427: "Notify was called before the LockManager was started.");
428: } else {
429: logger
430: .warn("Notify was called after shutdown sequence commenced.");
431: }
432: }
433: Lock lock = (Lock) this .locks.get(lid);
434: if (lock != null) {
435: ServerThreadContext threadContext = threadContextFactory
436: .getOrCreate(cid, tid);
437: try {
438: lock.notify(threadContext, all, addNotifiedWaitersTo);
439: if (false)
440: System.err.println("LockManager.notify(" + lid
441: + ", " + cid + ", " + tid + ", all=" + all
442: + ", notifiedWaiters="
443: + addNotifiedWaitersTo);
444: } catch (TCIllegalMonitorStateException e) {
445: e.printStackTrace();
446: throw new AssertionError(e);
447: }
448: } else {
449: throw new AssertionError("Lock :" + lid
450: + " is not present !");
451: }
452: }
453:
454: private void basicUnlock(Lock lock,
455: ServerThreadContext threadContext) {
456: lock.removeCurrentHold(threadContext);
457: if (isStarted()) {
458: boolean clear = lock.nextPending();
459: if (clear) {
460: locks.remove(lock.getLockID());
461: }
462: }
463: threadContextFactory.removeIfClear(threadContext);
464: notifyAll();
465: }
466:
467: public synchronized boolean hasPending(LockID id) {
468: return getLockFor(id).hasPending();
469: }
470:
471: public synchronized void clearAllLocksFor(NodeID nid) {
472: HashSet allLocks = new HashSet(locks.keySet());
473:
474: // NOTE: These loops might be too expensive as lock and threadContext sets grow large
475: // We could keep indexes based on channel to speed things up
476:
477: for (Iterator i = allLocks.iterator(); i.hasNext();) {
478: LockID lid = (LockID) i.next();
479: Lock lock = getLockFor(lid);
480:
481: if (!lock.isNull()) {
482: lock.clearStateForNode(nid);
483:
484: // This gets the next pending lock (if any) awarded
485: basicUnlock(lock, ServerThreadContext.NULL_CONTEXT);
486: }
487: }
488: threadContextFactory.clear(nid);
489: lockStatsManager.clearAllStatsFor(nid);
490: }
491:
492: private Lock getLockFor(LockID id) {
493: Lock lock = (Lock) locks.get(id);
494: if (lock == null)
495: return Lock.NULL_LOCK;
496: return lock;
497: }
498:
499: public synchronized void scanForDeadlocks(DeadlockResults output) {
500: new DeadlockDetector(output).detect(threadContextFactory
501: .getView().iterator());
502: }
503:
504: public DeadlockChain[] scanForDeadlocks() {
505: final List chains = new ArrayList();
506: DeadlockResults results = new DeadlockResults() {
507: public void foundDeadlock(DeadlockChain chain) {
508: chains.add(chain);
509: }
510: };
511:
512: scanForDeadlocks(results);
513:
514: return (DeadlockChain[]) chains
515: .toArray(new DeadlockChain[chains.size()]);
516: }
517:
518: public LockMBean[] getAllLocks() {
519: final List copy;
520: synchronized (this ) {
521: copy = new ArrayList(locks.size());
522: copy.addAll(locks.values());
523: }
524:
525: int count = 0;
526: LockMBean[] rv = new LockMBean[copy.size()];
527: for (Iterator i = copy.iterator(); i.hasNext();) {
528: Lock lock = (Lock) i.next();
529: rv[count++] = lock.getMBean(channelManager);
530: }
531:
532: return rv;
533: }
534:
535: public void start() {
536: synchronized (this ) {
537: assertStarting();
538: changeState(STARTED);
539: if (lockPolicy == UNINITIALIZED_LOCK_POLICY) {
540: this .lockPolicy = GREEDY_LOCK_POLICY;
541: }
542:
543: logger.debug("START Locks re-established -- "
544: + locks.size());
545: for (Iterator i = locks.values().iterator(); i.hasNext();) {
546: Lock lock = (Lock) i.next();
547: lock.setLockPolicy(lockPolicy);
548: lock.notifyStarted(this , waitTimer);
549: }
550:
551: for (Iterator i = lockRequestQueue.iterator(); i.hasNext();) {
552: RequestLockContext ctxt = (RequestLockContext) i.next();
553: requestLock(ctxt.lockID, ctxt.nodeID, ctxt.threadID,
554: ctxt.requestedLockLevel, ctxt.timeout,
555: ctxt.lockResponseSink, ctxt.noBlock);
556: }
557: lockRequestQueue.clear();
558: }
559: }
560:
561: public synchronized void stop() throws InterruptedException {
562: while (isStarting())
563: wait();
564: assertStarted();
565: cinfo("Stopping...");
566: changeState(STOPPING);
567:
568: locks.clear();
569: threadContextFactory.clear();
570:
571: if (waitTimer != null) {
572: waitTimer.shutdown();
573: }
574: setLockPolicy(ALTRUISTIC_LOCK_POLICY);
575:
576: changeState(STOPPED);
577: cinfo("Stopped.");
578:
579: }
580:
581: public int getLockPolicy() {
582: return lockPolicy;
583: }
584:
585: public void setLockPolicy(int lockPolicy) {
586: Assert.assertTrue(lockPolicy == GREEDY_LOCK_POLICY
587: || lockPolicy == ALTRUISTIC_LOCK_POLICY);
588: this .lockPolicy = lockPolicy;
589: for (Iterator i = locks.values().iterator(); i.hasNext();) {
590: Lock lock = (Lock) i.next();
591: lock.setLockPolicy(this .lockPolicy);
592: }
593: }
594:
595: private void cinfo(Object message) {
596: clogger.debug("Lock Manager: " + message);
597: }
598:
599: private void changeState(State s) {
600: this .status = s;
601: notifyAll();
602: }
603:
604: private boolean isStopped() {
605: return status == STOPPED;
606: }
607:
608: private boolean isStarted() {
609: return status == STARTED;
610: }
611:
612: private boolean isStarting() {
613: return status == STARTING;
614: }
615:
616: private void assertStarting() {
617: if (!isStarting())
618: throw new LockManagerError(NOT_STARTING_ERROR,
619: "LockManager is not starting ("
620: + this .status.getName() + ")");
621: }
622:
623: private void assertStarted() {
624: if (!isStarted())
625: throw new LockManagerError(NOT_STARTED_ERROR,
626: "LockManager is not started ("
627: + this .status.getName() + ")");
628: }
629:
630: private void assertNotStarting() {
631: if (isStarting())
632: throw new LockManagerError(IS_STARTING_ERROR,
633: "LockManager is starting");
634: }
635:
636: private void assertNotStopped() {
637: if (isStopped())
638: throw new LockManagerError(IS_STOPPED_ERROR,
639: "LockManager is stopped");
640: }
641:
642: public static class LockManagerError extends Error {
643:
644: private final LockManagerErrorDescription desc;
645:
646: private LockManagerError(LockManagerErrorDescription desc,
647: String msg) {
648: super (msg);
649: this .desc = desc;
650: }
651:
652: public LockManagerErrorDescription getDescription() {
653: return this .desc;
654: }
655: }
656:
657: public static class LockManagerErrorDescription {
658: private final String name;
659:
660: private LockManagerErrorDescription(String name) {
661: this .name = name;
662: }
663:
664: public String toString() {
665: return getClass().getName() + "[" + this .name + "]";
666: }
667: }
668:
669: private static class RequestLockContext {
670: final LockID lockID;
671: final NodeID nodeID;
672: final ThreadID threadID;
673: final int requestedLockLevel;
674: final boolean noBlock;
675: final Sink lockResponseSink;
676: final WaitInvocation timeout;
677:
678: private RequestLockContext(LockID lockID, NodeID nodeID,
679: ThreadID threadID, int requestedLockLevel,
680: Sink lockResponseSink, boolean noBlock) {
681: this .lockID = lockID;
682: this .nodeID = nodeID;
683: this .threadID = threadID;
684: this .requestedLockLevel = requestedLockLevel;
685: this .lockResponseSink = lockResponseSink;
686: this .noBlock = noBlock;
687: this .timeout = null;
688: }
689:
690: private RequestLockContext(LockID lockID, NodeID nodeID,
691: ThreadID threadID, int requestedLockLevel,
692: WaitInvocation timeout, Sink lockResponseSink,
693: boolean noBlock) {
694: this .lockID = lockID;
695: this .nodeID = nodeID;
696: this .threadID = threadID;
697: this .requestedLockLevel = requestedLockLevel;
698: this .lockResponseSink = lockResponseSink;
699: this .noBlock = noBlock;
700: this .timeout = timeout;
701: }
702:
703: public String toString() {
704: return "RequestLockContext [ " + lockID + "," + nodeID
705: + "," + threadID + ","
706: + LockLevel.toString(requestedLockLevel) + ", "
707: + noBlock + ", " + timeout + " ]";
708: }
709: }
710:
711: private static class State {
712: private final String name;
713:
714: private State(String name) {
715: this .name = name;
716: }
717:
718: public String getName() {
719: return this .name;
720: }
721:
722: public String toString() {
723: return getClass().getName() + "[" + this .name + "]";
724: }
725: }
726: }
|