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.async.impl.MockSink;
009: import com.tc.exception.TCLockUpgradeNotSupportedError;
010: import com.tc.management.L2LockStatsManager;
011: import com.tc.net.groups.ClientID;
012: import com.tc.net.groups.NodeID;
013: import com.tc.net.protocol.tcm.ChannelID;
014: import com.tc.object.lockmanager.api.LockID;
015: import com.tc.object.lockmanager.api.LockLevel;
016: import com.tc.object.lockmanager.api.ThreadID;
017: import com.tc.object.lockmanager.api.WaitTimer;
018: import com.tc.object.lockmanager.impl.WaitTimerImpl;
019: import com.tc.object.tx.WaitInvocation;
020: import com.tc.objectserver.lockmanager.api.LockAwardContext;
021: import com.tc.objectserver.lockmanager.api.LockEventListener;
022: import com.tc.objectserver.lockmanager.api.LockEventMonitor;
023: import com.tc.objectserver.lockmanager.api.NotifiedWaiters;
024: import com.tc.objectserver.lockmanager.api.NullChannelManager;
025: import com.tc.objectserver.lockmanager.api.TCIllegalMonitorStateException;
026: import com.tc.objectserver.lockmanager.api.LockEventMonitor.CallContext;
027: import com.tc.util.TCAssertionError;
028: import com.tc.util.concurrent.ThreadUtil;
029:
030: import java.util.Collection;
031: import java.util.Iterator;
032:
033: import junit.framework.TestCase;
034:
035: public class LockTest extends TestCase {
036:
037: private Sink sink;
038: private long uniqueId = 100000L;
039: private WaitTimer waitTimer;
040: private LockManagerImpl lockMgr = new LockManagerImpl(
041: new NullChannelManager(),
042: L2LockStatsManager.NULL_LOCK_STATS_MANAGER);
043: private NotifiedWaiters notifiedWaiters;
044:
045: protected void setUp() throws Exception {
046: super .setUp();
047: this .notifiedWaiters = new NotifiedWaiters();
048: this .sink = new MockSink();
049: this .waitTimer = new WaitTimerImpl();
050: }
051:
052: public void testLockClear() {
053: // XXX: test the return value of lock.nextPending()
054: // XXX: add this check into the other tests too
055:
056: // throw new ImplementMe();
057: }
058:
059: public void testUpgrade() throws Exception {
060: ClientID cid1 = new ClientID(new ChannelID(1));
061: ThreadID txnId1 = new ThreadID(1);
062: ThreadID txnId2 = new ThreadID(2);
063: ThreadID txnId3 = new ThreadID(3);
064:
065: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
066: ServerThreadContext thread2 = makeTxn(cid1, txnId2);
067: ServerThreadContext thread3 = makeTxn(cid1, txnId3);
068:
069: Lock lock = new Lock(new LockID("timmy"), 0,
070: new LockEventListener[] {});
071: lock.requestLock(thread1, LockLevel.READ, sink);
072: lock.requestLock(thread2, LockLevel.READ, sink);
073: lock.requestLock(thread3, LockLevel.READ, sink);
074: assertEquals(3, lock.getHoldersCount());
075: assertEquals(0, lock.getPendingCount());
076:
077: // try requesting the upgrade
078: try {
079: lock.requestLock(thread1, LockLevel.WRITE, sink);
080: throw new AssertionError(
081: "Should have thrown a TCLockUpgradeNotSupportedError.");
082: } catch (TCLockUpgradeNotSupportedError e) {
083: // expected
084: }
085: assertEquals(3, lock.getHoldersCount());
086: assertEquals(0, lock.getPendingCount());
087:
088: lock.removeCurrentHold(thread2);
089: assertEquals(2, lock.getHoldersCount());
090: assertEquals(0, lock.getPendingCount());
091:
092: // release 1 read lock
093: lock.removeCurrentHold(thread3);
094:
095: assertEquals(1, lock.getHoldersCount());
096: assertEquals(0, lock.getPendingCount());
097: Holder holder = (Holder) lock.getHoldersCollection().toArray()[0];
098: assertEquals(cid1, holder.getNodeID());
099: assertEquals(txnId1, holder.getThreadID());
100: //assertFalse(holder.isUpgrade());
101:
102: // add some other pending lock requests
103: lock.requestLock(thread2, LockLevel.READ, sink);
104: lock.requestLock(thread3, LockLevel.WRITE, sink);
105: assertEquals(1, lock.getPendingCount());
106: assertEquals(2, lock.getHoldersCount());
107:
108: // release all reads
109: lock.removeCurrentHold(thread1);
110: lock.removeCurrentHold(thread2);
111: assertEquals(0, lock.getHoldersCount());
112: assertEquals(1, lock.getPendingCount());
113: Holder[] holders = (Holder[]) lock.getHoldersCollection()
114: .toArray(new Holder[] {});
115: assertEquals(0, holders.length);
116:
117: // release one of the current read locks
118: lock.removeCurrentHold(thread1);
119: lock.nextPending();
120: assertEquals(0, lock.getPendingCount());
121: assertEquals(1, lock.getHoldersCount());
122: holder = (Holder) lock.getHoldersCollection().toArray()[0];
123: assertEquals(cid1, holder.getNodeID());
124: assertEquals(txnId3, holder.getThreadID());
125: assertEquals(LockLevel.WRITE, holder.getLockLevel());
126:
127: // release the write lock
128: lock.removeCurrentHold(thread3);
129: assertEquals(0, lock.getPendingCount());
130: assertEquals(0, lock.getHoldersCount());
131: }
132:
133: private static ServerThreadContext makeTxn(ClientID cid,
134: ThreadID threadID) {
135: return new ServerThreadContext(cid, threadID);
136: }
137:
138: public void testMonitorStateAssertions() throws Exception {
139: ClientID cid1 = new ClientID(new ChannelID(1));
140: ThreadID txnId1 = new ThreadID(1);
141:
142: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
143:
144: Lock lock = new Lock(new LockID("timmy"), 0,
145: new LockEventListener[] {});
146: lock.requestLock(thread1, LockLevel.WRITE, sink);
147: assertEquals(1, lock.getHoldersCount());
148: assertEquals(0, lock.getWaiterCount());
149: lock.wait(thread1, waitTimer, new WaitInvocation(), lockMgr,
150: sink); // indefinite
151: // wait()
152: assertEquals(0, lock.getHoldersCount());
153: assertEquals(1, lock.getWaiterCount());
154:
155: try {
156: lock.wait(thread1, waitTimer, new WaitInvocation(),
157: lockMgr, sink);
158: fail("able to join wait set twice");
159: } catch (TCAssertionError e) {
160: // exptected
161: }
162:
163: try {
164: lock.notify(thread1, false, notifiedWaiters);
165: fail("able to call notify whilst being in the wait set");
166: } catch (TCAssertionError e) {
167: // exptected
168: }
169: }
170:
171: public void testIllegalMonitorState() {
172: ClientID goodClientID = new ClientID(new ChannelID(1));
173: ThreadID goodTxnId = new ThreadID(1);
174:
175: ClientID badDClientID = new ClientID(new ChannelID(2));
176: ThreadID badTxnId = new ThreadID(2);
177:
178: ServerThreadContext good = makeTxn(goodClientID, goodTxnId);
179: ServerThreadContext bad = makeTxn(badDClientID, badTxnId);
180:
181: Lock lock = new Lock(new LockID("timmy"), 0,
182: new LockEventListener[] {});
183: lock.requestLock(good, LockLevel.WRITE, sink);
184: assertEquals(1, lock.getHoldersCount());
185: assertFalse(lock.hasPending());
186:
187: try {
188: // different lock owner should not be to do a wait()
189: lock.wait(bad, waitTimer, new WaitInvocation(), lockMgr,
190: sink);
191: fail("Not expected");
192: } catch (TCIllegalMonitorStateException e) {
193: try {
194: // different lock owner should not be to do a notify()
195: lock.notify(bad, false, notifiedWaiters);
196: fail("Not expected");
197: } catch (TCIllegalMonitorStateException e2) {
198: try {
199: // different lock owner should not be to do a notifyAll()
200: lock.notify(bad, true, notifiedWaiters);
201: fail("Not expected");
202: } catch (TCIllegalMonitorStateException e3) {
203: // expected
204: }
205: }
206: }
207:
208: // make it so no one is holding
209: lock.removeCurrentHold(good);
210: lock.nextPending();
211: assertEquals(0, lock.getHoldersCount());
212:
213: try {
214: // should not be able to wait() if no one holds a lock
215: lock.wait(good, waitTimer, new WaitInvocation(), lockMgr,
216: sink);
217: fail("Not expected");
218: } catch (TCIllegalMonitorStateException e) {
219: try {
220: // should not be able to notify() if no one holds a lock
221: lock.notify(good, false, notifiedWaiters);
222: fail("Not expected");
223: } catch (TCIllegalMonitorStateException e2) {
224: try {
225: // should not be able to notifyAll() if no one holds a lock
226: lock.notify(good, true, notifiedWaiters);
227: fail("Not expected");
228: } catch (TCIllegalMonitorStateException e3) {
229: // expected
230: }
231: }
232: }
233:
234: // award a read lock
235: assertEquals(0, lock.getHoldersCount());
236: lock.requestLock(good, LockLevel.READ, sink);
237: assertEquals(1, lock.getHoldersCount());
238:
239: try {
240: // should not be able to wait() if not holding a write lock
241: lock.wait(good, waitTimer, new WaitInvocation(), lockMgr,
242: sink);
243: fail("Not expected");
244: } catch (TCIllegalMonitorStateException e) {
245: try {
246: // should not be able to notify() if not holding a write lock
247: lock.notify(good, false, notifiedWaiters);
248: fail("Not expected");
249: } catch (TCIllegalMonitorStateException e2) {
250: try {
251: // should not be able to notifyAll() if not holding a write lock
252: lock.notify(good, true, notifiedWaiters);
253: fail("Not expected");
254: } catch (TCIllegalMonitorStateException e3) {
255: // expected
256: }
257: }
258: }
259: }
260:
261: public void testTimedWaitWithNotify() throws Exception {
262: ClientID cid1 = new ClientID(new ChannelID(1));
263: ThreadID txnId1 = new ThreadID(1);
264: ThreadID txnId2 = new ThreadID(2);
265:
266: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
267: ServerThreadContext thread2 = makeTxn(cid1, txnId2);
268:
269: Lock lock = new Lock(new LockID("timmy"), 0,
270: new LockEventListener[] {});
271: lock.requestLock(thread1, LockLevel.WRITE, sink);
272:
273: assertEquals(1, lock.getHoldersCount());
274: assertEquals(0, lock.getWaiterCount());
275: assertFalse(lock.hasPending());
276:
277: lock.wait(thread1, waitTimer, new WaitInvocation(200), lockMgr,
278: sink);
279: assertEquals(0, lock.getHoldersCount());
280: assertEquals(1, lock.getWaiterCount());
281: assertFalse(lock.hasPending());
282:
283: lock.requestLock(thread2, LockLevel.WRITE, sink);
284: lock.notify(thread2, false, notifiedWaiters);
285: assertEquals(1, lock.getHoldersCount());
286: assertEquals(0, lock.getWaiterCount());
287: assertEquals(1, lock.getPendingCount());
288:
289: // give the timer a chance to run (even though it should be cancelled)
290: ThreadUtil.reallySleep(2000);
291: assertEquals(1, lock.getHoldersCount());
292: assertEquals(0, lock.getWaiterCount());
293: assertEquals(1, lock.getPendingCount());
294: }
295:
296: public void testTimedWait2() throws Exception {
297: // excercise the 2 arg version of wait
298: ClientID cid1 = new ClientID(new ChannelID(1));
299: ThreadID txnId1 = new ThreadID(1);
300: lockMgr.start();
301:
302: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
303:
304: Lock lock = new Lock(new LockID("timmy"), 0,
305: new LockEventListener[] {});
306: lock.requestLock(thread1, LockLevel.WRITE, sink);
307: assertEquals(1, lock.getHoldersCount());
308: assertEquals(0, lock.getWaiterCount());
309: assertFalse(lock.hasPending());
310:
311: long t1 = System.currentTimeMillis();
312: lock.wait(thread1, waitTimer, new WaitInvocation(2000, 500),
313: lockMgr, sink);
314: // This is still not perfect - This can only raise false negatives
315: // assertEquals(0, lock.getHoldersCount());
316: // assertEquals(1, lock.getWaiterCount());
317: // assertFalse(lock.hasPending());
318:
319: while (lock.getHoldersCount() != 1) {
320: ThreadUtil.reallySleep(100);
321: }
322: long t2 = System.currentTimeMillis();
323: assertTrue(t2 - t1 >= 2000);
324:
325: assertEquals(1, lock.getHoldersCount());
326: assertEquals(0, lock.getWaiterCount());
327: assertFalse(lock.hasPending());
328: }
329:
330: public void testTimedWaitsDontFireWhenLockManagerIsStopped()
331: throws Exception {
332: ClientID cid1 = new ClientID(new ChannelID(1));
333: ThreadID txnId1 = new ThreadID(1);
334: lockMgr.start();
335:
336: // Test that a wait() timeout will obtain an uncontended lock
337: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
338:
339: Lock lock = new Lock(new LockID("timmy"), 0,
340: new LockEventListener[] {});
341: lock.requestLock(thread1, LockLevel.WRITE, sink);
342: assertEquals(1, lock.getHoldersCount());
343: assertEquals(0, lock.getWaiterCount());
344: assertFalse(lock.hasPending());
345:
346: lock.wait(thread1, waitTimer, new WaitInvocation(1000),
347: lockMgr, sink);
348: assertEquals(0, lock.getHoldersCount());
349: assertEquals(1, lock.getWaiterCount());
350: assertFalse(lock.hasPending());
351:
352: ThreadUtil.reallySleep(250);
353: assertEquals(0, lock.getHoldersCount());
354: assertEquals(1, lock.getWaiterCount());
355: assertFalse(lock.hasPending());
356:
357: // stop the lock manager
358: lockMgr.stop();
359:
360: ThreadUtil.reallySleep(250);
361: assertEquals(0, lock.getHoldersCount());
362: assertEquals(1, lock.getWaiterCount());
363: assertFalse(lock.hasPending());
364:
365: ThreadUtil.reallySleep(2000);
366: assertEquals(0, lock.getHoldersCount());
367: assertEquals(1, lock.getWaiterCount());
368: assertFalse(lock.hasPending());
369: }
370:
371: public void testTimedWaits() throws Exception {
372: ClientID cid1 = new ClientID(new ChannelID(1));
373: ThreadID txnId1 = new ThreadID(1);
374: ThreadID txnId2 = new ThreadID(2);
375: lockMgr.start();
376: {
377: // Test that a wait() timeout will obtain an uncontended lock
378: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
379:
380: Lock lock = new Lock(new LockID("timmy"), 0,
381: new LockEventListener[] {});
382: lock.requestLock(thread1, LockLevel.WRITE, sink);
383: assertEquals(1, lock.getHoldersCount());
384: assertEquals(0, lock.getWaiterCount());
385: assertFalse(lock.hasPending());
386:
387: long t1 = System.currentTimeMillis();
388: lock.wait(thread1, waitTimer, new WaitInvocation(1000),
389: lockMgr, sink);
390: // This is still not perfect - This can only raise false negatives
391: // assertEquals(0, lock.getHoldersCount());
392: // assertEquals(1, lock.getWaiterCount());
393: // assertFalse(lock.hasPending());
394:
395: while (lock.getHoldersCount() != 1) {
396: ThreadUtil.reallySleep(100);
397: }
398: long t2 = System.currentTimeMillis();
399: assertTrue(t2 - t1 >= 1000);
400:
401: assertEquals(1, lock.getHoldersCount());
402: assertEquals(0, lock.getWaiterCount());
403: assertFalse(lock.hasPending());
404:
405: }
406:
407: {
408: // this time the wait timeout will cause the waiter to be put in the
409: // pending
410: // list (instead of instantly getting the lock)
411: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
412: ServerThreadContext thread2 = makeTxn(cid1, txnId2);
413: Lock lock = new Lock(new LockID("timmy"), 0,
414: new LockEventListener[] {});
415: lock.requestLock(thread1, LockLevel.WRITE, sink);
416: assertEquals(1, lock.getHoldersCount());
417: assertEquals(0, lock.getWaiterCount());
418: assertFalse(lock.hasPending());
419:
420: lock.wait(thread1, waitTimer, new WaitInvocation(500),
421: lockMgr, sink);
422: assertEquals(0, lock.getHoldersCount());
423: assertEquals(1, lock.getWaiterCount());
424: assertFalse(lock.hasPending());
425:
426: lock.requestLock(thread2, LockLevel.WRITE, sink);
427: assertEquals(1, lock.getHoldersCount());
428: assertEquals(1, lock.getWaiterCount());
429: assertFalse(lock.hasPending());
430:
431: ThreadUtil.reallySleep(1000);
432: assertEquals(1, lock.getHoldersCount());
433: assertEquals(0, lock.getWaiterCount());
434: assertEquals(1, lock.getPendingCount());
435:
436: lock.removeCurrentHold(thread2);
437: lock.nextPending();
438: assertEquals(1, lock.getHoldersCount());
439: assertEquals(0, lock.getWaiterCount());
440: assertEquals(0, lock.getPendingCount());
441:
442: lock.removeCurrentHold(thread1);
443: lock.nextPending();
444: assertEquals(0, lock.getHoldersCount());
445: assertEquals(0, lock.getWaiterCount());
446: assertEquals(0, lock.getPendingCount());
447: }
448: }
449:
450: public void testWait() throws Exception {
451: ClientID cid1 = new ClientID(new ChannelID(1));
452: ThreadID txnId1 = new ThreadID(1);
453:
454: ServerThreadContext thread1 = makeTxn(cid1, txnId1);
455:
456: Lock lock = new Lock(new LockID("timmy"), 0,
457: new LockEventListener[] {});
458: lock.requestLock(thread1, LockLevel.WRITE, sink);
459: assertEquals(1, lock.getHoldersCount());
460: assertEquals(0, lock.getWaiterCount());
461: assertFalse(lock.hasPending());
462:
463: lock.wait(thread1, waitTimer, new WaitInvocation(), lockMgr,
464: sink);
465:
466: assertEquals(0, lock.getHoldersCount());
467: assertEquals(1, lock.getWaiterCount());
468: assertFalse(lock.hasPending());
469: }
470:
471: public void testWaitOnAndNotify() throws Exception {
472: ClientID cid1 = new ClientID(new ChannelID(1));
473:
474: ServerThreadContext thread1 = makeTxn(cid1, new ThreadID(1));
475: ServerThreadContext thread2 = makeTxn(cid1, new ThreadID(2));
476:
477: Lock lock = new Lock(new LockID("timmy"), 0,
478: new LockEventListener[] {});
479: lock.requestLock(thread1, LockLevel.WRITE, sink);
480: assertEquals(1, lock.getHoldersCount());
481: assertEquals(0, lock.getWaiterCount());
482: assertFalse(lock.hasPending());
483:
484: lock.wait(thread1, waitTimer, new WaitInvocation(), lockMgr,
485: sink);
486: assertEquals(0, lock.getHoldersCount());
487: assertEquals(1, lock.getWaiterCount());
488: assertFalse(lock.hasPending());
489:
490: // make sure another thread can notify()
491: boolean granted = lock.requestLock(thread2, LockLevel.WRITE,
492: sink);
493: assertTrue(granted);
494: assertEquals(1, lock.getHoldersCount());
495: assertEquals(1, lock.getWaiterCount());
496: assertFalse(lock.hasPending());
497:
498: lock.notify(thread2, false, notifiedWaiters);
499: assertEquals(1, lock.getHoldersCount());
500: assertEquals(0, lock.getWaiterCount());
501: assertEquals(1, lock.getPendingCount());
502:
503: lock.removeCurrentHold(thread2);
504: lock.nextPending();
505: assertEquals(1, lock.getHoldersCount());
506: assertEquals(0, lock.getWaiterCount());
507: assertEquals(0, lock.getPendingCount());
508:
509: // make sure the wait()'er gets an write lock back
510: Collection holders = lock.getHoldersCollection();
511: assertEquals(1, holders.size());
512: Holder holder = null;
513: for (Iterator iter = holders.iterator(); iter.hasNext();) {
514: assertNull(holder); // should only be one holder
515: holder = (Holder) iter.next();
516: }
517:
518: assertEquals(thread1, holder.getThreadContext());
519: //assertFalse(holder.isUpgrade());
520: assertEquals(LockLevel.WRITE, holder.getLockLevel());
521: }
522:
523: public void testNotifyAll() throws Exception {
524: Lock lock = createLockWithIndefiniteWaits(100);
525:
526: assertEquals(0, lock.getHoldersCount());
527: assertEquals(100, lock.getWaiterCount());
528: assertEquals(0, lock.getPendingCount());
529:
530: ServerThreadContext notifier = makeTxn(getUniqueClientID(),
531: getUniqueTransactionID());
532: lock.requestLock(notifier, LockLevel.WRITE, sink);
533: lock.notify(notifier, true, notifiedWaiters);
534: assertEquals(1, lock.getHoldersCount());
535: assertEquals(0, lock.getWaiterCount());
536: assertEquals(100, lock.getPendingCount());
537:
538: lock.removeCurrentHold(notifier);
539: lock.nextPending();
540: assertEquals(1, lock.getHoldersCount());
541: assertEquals(0, lock.getWaiterCount());
542: assertEquals(99, lock.getPendingCount());
543: }
544:
545: public void testNotify() throws Exception {
546: Lock lock = createLockWithIndefiniteWaits(3);
547:
548: assertEquals(0, lock.getHoldersCount());
549: assertEquals(3, lock.getWaiterCount());
550: assertEquals(0, lock.getPendingCount());
551:
552: ServerThreadContext notifier = makeTxn(getUniqueClientID(),
553: getUniqueTransactionID());
554: lock.requestLock(notifier, LockLevel.WRITE, sink);
555: lock.notify(notifier, false, notifiedWaiters);
556: assertEquals(1, lock.getHoldersCount());
557: assertEquals(2, lock.getWaiterCount());
558: assertEquals(1, lock.getPendingCount());
559:
560: lock.notify(notifier, false, notifiedWaiters);
561: assertEquals(1, lock.getHoldersCount());
562: assertEquals(1, lock.getWaiterCount());
563: assertEquals(2, lock.getPendingCount());
564:
565: lock.notify(notifier, false, notifiedWaiters);
566: assertEquals(1, lock.getHoldersCount());
567: assertEquals(0, lock.getWaiterCount());
568: assertEquals(3, lock.getPendingCount());
569:
570: // one more time, should have no effect
571: lock.notify(notifier, false, notifiedWaiters);
572: assertEquals(1, lock.getHoldersCount());
573: assertEquals(0, lock.getWaiterCount());
574: assertEquals(3, lock.getPendingCount());
575:
576: lock.removeCurrentHold(notifier);
577: lock.nextPending();
578: assertEquals(1, lock.getHoldersCount());
579: assertEquals(0, lock.getWaiterCount());
580: assertEquals(2, lock.getPendingCount());
581: }
582:
583: private ClientID getUniqueClientID() {
584: return new ClientID(new ChannelID(uniqueId++));
585: }
586:
587: private ThreadID getUniqueTransactionID() {
588: return new ThreadID(uniqueId++);
589: }
590:
591: private Lock createLockWithIndefiniteWaits(int numWaits)
592: throws TCIllegalMonitorStateException {
593: Lock lock = new Lock(new LockID("timmy"), 0,
594: new LockEventListener[] {});
595:
596: for (int i = 0; i < numWaits; i++) {
597: int before = lock.getWaiterCount();
598:
599: ServerThreadContext me = makeTxn(getUniqueClientID(),
600: getUniqueTransactionID());
601: lock.requestLock(me, LockLevel.WRITE, sink);
602: lock.wait(me, waitTimer, new WaitInvocation(), lockMgr,
603: sink);
604: assertEquals(before + 1, lock.getWaiterCount());
605: }
606:
607: assertEquals(numWaits, lock.getWaiterCount());
608: assertEquals(0, lock.getHoldersCount());
609: assertEquals(0, lock.getPendingCount());
610:
611: return lock;
612: }
613:
614: public void testAddPending() throws Exception {
615: LockEventMonitor monitor = new LockEventMonitor();
616: Lock lock = new Lock(new LockID("yo"), 0,
617: new LockEventListener[] { monitor });
618:
619: ServerThreadContext thread1 = makeTxn(getUniqueClientID(),
620: getUniqueTransactionID());
621: ServerThreadContext thread2 = makeTxn(getUniqueClientID(),
622: getUniqueTransactionID());
623:
624: lock.requestLock(thread1, LockLevel.WRITE, sink);
625: lock.requestLock(thread2, LockLevel.WRITE, sink);
626:
627: // make sure that addPending(...) causes notifyAddPending to be called with
628: // the correct pending count and
629: // for each holder's lock award context.
630: //
631: // The pending count should now be 1.
632: int pendingCount = 1;
633:
634: Collection holders = lock.getHoldersCollection();
635: assertEquals(1, holders.size());
636: checkNotifyAddPendingCallContextForAllHolders(lock, monitor,
637: pendingCount, holders);
638: }
639:
640: private void checkNotifyAddPendingCallContextForAllHolders(
641: Lock lock, LockEventMonitor monitor, int waiterCount,
642: Collection holders) throws Exception {
643: for (Iterator iter = holders.iterator(); iter.hasNext();) {
644: Holder holder = (Holder) iter.next();
645: checkCallContext(monitor.waitForNotifyAddPending(0), lock
646: .getLockID(), holder.getNodeID(), waiterCount);
647: }
648: }
649:
650: private void checkCallContext(CallContext cc, LockID theLockId,
651: NodeID nodeID, int waiterCount) {
652: assertNotNull(cc);
653: LockAwardContext ac = cc.ctxt;
654: assertEquals(theLockId, ac.getLockID());
655: assertEquals(nodeID, ac.getNodeID());
656: assertEquals(waiterCount, cc.waiterCount);
657: }
658:
659: }
|