001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: LockManagerTest.java,v 1.45.2.7 2008/01/10 03:05:04 cwl Exp $
007: */
008:
009: package com.sleepycat.je.txn;
010:
011: import java.io.File;
012:
013: import junit.framework.TestCase;
014:
015: import com.sleepycat.je.DatabaseException;
016: import com.sleepycat.je.DeadlockException;
017: import com.sleepycat.je.EnvironmentConfig;
018: import com.sleepycat.je.TransactionConfig;
019: import com.sleepycat.je.config.EnvironmentParams;
020: import com.sleepycat.je.dbi.EnvironmentImpl;
021: import com.sleepycat.je.junit.JUnitThread;
022: import com.sleepycat.je.util.TestUtils;
023:
024: public class LockManagerTest extends TestCase {
025:
026: private LockManager lockManager = null;
027: private Locker txn1;
028: private Locker txn2;
029: private Locker txn3;
030: private Locker txn4;
031: private Long nid;
032: private volatile int sequence;
033:
034: private EnvironmentImpl env;
035: private File envHome;
036:
037: public LockManagerTest() {
038: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
039: }
040:
041: public void setUp() throws DatabaseException {
042:
043: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
044: envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(),
045: "6");
046: envConfig.setConfigParam(EnvironmentParams.N_LOCK_TABLES
047: .getName(), "11");
048: envConfig.setAllowCreate(true);
049: envConfig.setTransactional(true);
050: env = new EnvironmentImpl(envHome, envConfig);
051:
052: TxnManager txnManager = env.getTxnManager();
053: lockManager = txnManager.getLockManager();
054: txn1 = new BasicLocker(env);
055: txn2 = new BasicLocker(env);
056: txn3 = new BasicLocker(env);
057: txn4 = new BasicLocker(env);
058: nid = new Long(1);
059: sequence = 0;
060: }
061:
062: public void tearDown() throws DatabaseException {
063:
064: txn1.operationEnd();
065: txn2.operationEnd();
066: txn3.operationEnd();
067: txn4.operationEnd();
068: env.close();
069: }
070:
071: /*
072: * SR15926 showed a bug where nodeIds that are > 0x80000000 produce
073: * negative lock table indexes becuase of the modulo arithmetic in
074: * LockManager.getLockTableIndex().
075: */
076: public void testSR15926LargeNodeIds() throws Exception {
077:
078: try {
079: lockManager.lock(0x80000000L, txn1, LockType.WRITE, 0,
080: false, null);
081: } catch (Exception e) {
082: fail("shouldn't get exception " + e);
083: }
084: }
085:
086: public void testNegatives() throws Exception {
087:
088: try {
089: assertFalse(lockManager.isOwner(nid, txn1, LockType.READ));
090: assertFalse(lockManager.isOwner(nid, txn1, LockType.WRITE));
091: assertFalse(lockManager.isLocked(nid));
092: assertFalse(lockManager.isWaiter(nid, txn1));
093: lockManager.lock(1, txn1, LockType.READ, 0, false, null);
094:
095: /* already holds this lock */
096: assertEquals(LockGrantType.EXISTING, lockManager.lock(1,
097: txn1, LockType.READ, 0, false, null));
098: assertFalse(lockManager.isOwner(nid, txn2, LockType.READ));
099: assertFalse(lockManager.isOwner(nid, txn2, LockType.WRITE));
100: assertTrue(lockManager.isLocked(nid));
101: assertTrue(lockManager.nOwners(new Long(2)) == -1);
102: assertTrue(lockManager.nWaiters(new Long(2)) == -1);
103:
104: /* lock 2 doesn't exist, shouldn't affect any the existing lock */
105: lockManager.release(2L, txn1);
106: txn1.removeLock(2L);
107: assertTrue(lockManager.isLocked(nid));
108:
109: /* txn2 is not the owner, shouldn't release lock 1. */
110: lockManager.release(1L, txn2);
111: txn2.removeLock(1L);
112: assertTrue(lockManager.isLocked(nid));
113: assertTrue(lockManager.isOwner(nid, txn1, LockType.READ));
114: assertTrue(lockManager.nOwners(nid) == 1);
115:
116: /* Now really release. */
117: lockManager.release(1L, txn1);
118: txn1.removeLock(1L);
119: assertFalse(lockManager.isLocked(nid));
120: assertFalse(lockManager.isOwner(nid, txn1, LockType.READ));
121: assertFalse(lockManager.nOwners(nid) == 1);
122:
123: lockManager.lock(1, txn1, LockType.WRITE, 0, false, null);
124: /* holds write and subsequent request for READ is ok */
125: lockManager.lock(1, txn1, LockType.READ, 0, false, null);
126: /* already holds this lock */
127: assertTrue(lockManager.lock(1, txn1, LockType.WRITE, 0,
128: false, null) == LockGrantType.EXISTING);
129: assertFalse(lockManager.isWaiter(nid, txn1));
130: } catch (Exception e) {
131: e.printStackTrace();
132: throw e;
133: }
134: }
135:
136: /**
137: * Acquire three read locks and make sure that they share nicely.
138: */
139: public void testMultipleReaders() throws Throwable {
140:
141: JUnitThread tester1 = new JUnitThread("testMultipleReaders1") {
142: public void testBody() {
143: try {
144: lockManager.lock(1, txn1, LockType.READ, 0, false,
145: null);
146: assertTrue(lockManager.isOwner(nid, txn1,
147: LockType.READ));
148: sequence++;
149: while (sequence < 3) {
150: Thread.yield();
151: }
152: lockManager.release(1L, txn1);
153: txn1.removeLock(1L);
154: } catch (DatabaseException DBE) {
155: DBE.printStackTrace();
156: fail("caught DatabaseException " + DBE);
157: }
158: }
159: };
160:
161: JUnitThread tester2 = new JUnitThread("testMultipleReaders2") {
162: public void testBody() {
163: try {
164: lockManager.lock(1, txn2, LockType.READ, 0, false,
165: null);
166: assertTrue(lockManager.isOwner(nid, txn2,
167: LockType.READ));
168: sequence++;
169: while (sequence < 3) {
170: Thread.yield();
171: }
172: lockManager.release(1L, txn2);
173: txn2.removeLock(1L);
174: } catch (DatabaseException DBE) {
175: DBE.printStackTrace();
176: fail("caught DatabaseException " + DBE);
177: }
178: }
179: };
180:
181: JUnitThread tester3 = new JUnitThread("testMultipleReaders3") {
182: public void testBody() {
183: try {
184: lockManager.lock(1, txn3, LockType.READ, 0, false,
185: null);
186: assertTrue(lockManager.isOwner(nid, txn3,
187: LockType.READ));
188: sequence++;
189: while (sequence < 3) {
190: Thread.yield();
191: }
192: lockManager.release(1L, txn3);
193: txn3.removeLock(1L);
194: } catch (DatabaseException DBE) {
195: DBE.printStackTrace();
196: fail("caught DatabaseException " + DBE);
197: }
198: }
199: };
200:
201: tester1.start();
202: tester2.start();
203: tester3.start();
204: tester1.finishTest();
205: tester2.finishTest();
206: tester3.finishTest();
207: }
208:
209: /**
210: * Grab two read locks, hold them, and make sure that a write lock
211: * waits for them to be released.
212: */
213: public void testMultipleReadersSingleWrite1() throws Throwable {
214:
215: JUnitThread tester1 = new JUnitThread("testMultipleReaders1") {
216: public void testBody() {
217: try {
218: lockManager.lock(1, txn1, LockType.READ, 0, false,
219: null);
220: assertTrue(lockManager.isOwner(nid, txn1,
221: LockType.READ));
222: while (lockManager.nWaiters(nid) < 1) {
223: Thread.yield();
224: }
225: assertTrue(lockManager.isWaiter(nid, txn3));
226: assertFalse(lockManager.isWaiter(nid, txn1));
227: lockManager.release(1L, txn1);
228: txn1.removeLock(1L);
229: assertFalse(lockManager.isOwner(nid, txn1,
230: LockType.READ));
231: } catch (DatabaseException DBE) {
232: DBE.printStackTrace();
233: fail("caught DatabaseException " + DBE);
234: }
235: }
236: };
237:
238: JUnitThread tester2 = new JUnitThread("testMultipleReaders2") {
239: public void testBody() {
240: try {
241: lockManager.lock(1, txn2, LockType.READ, 0, false,
242: null);
243: assertTrue(lockManager.isOwner(nid, txn2,
244: LockType.READ));
245: while (lockManager.nWaiters(nid) < 1) {
246: Thread.yield();
247: }
248: assertTrue(lockManager.isWaiter(nid, txn3));
249: lockManager.release(1L, txn2);
250: txn2.removeLock(1L);
251: assertFalse(lockManager.isOwner(nid, txn2,
252: LockType.READ));
253: } catch (DatabaseException DBE) {
254: DBE.printStackTrace();
255: fail("caught DatabaseException " + DBE);
256: }
257: }
258: };
259:
260: JUnitThread tester3 = new JUnitThread("testMultipleReaders3") {
261: public void testBody() {
262: try {
263: while (lockManager.nOwners(nid) < 2) {
264: Thread.yield();
265: }
266: lockManager.lock(1, txn3, LockType.WRITE, 0, false,
267: null);
268: assertTrue(lockManager.isOwner(nid, txn3,
269: LockType.WRITE));
270: } catch (DatabaseException DBE) {
271: DBE.printStackTrace();
272: fail("caught DatabaseException " + DBE);
273: }
274: }
275: };
276:
277: tester1.start();
278: tester2.start();
279: tester3.start();
280: tester1.finishTest();
281: tester2.finishTest();
282: tester3.finishTest();
283: }
284:
285: /**
286: * Acquire two read locks, put a write locker behind the two
287: * read lockers, and then queue a read locker behind the writer.
288: * Ensure that the third reader is not granted until the writer
289: * releases the lock.
290: */
291: public void testMultipleReadersSingleWrite2() throws Throwable {
292:
293: JUnitThread tester1 = new JUnitThread("testMultipleReaders1") {
294: public void testBody() {
295: try {
296: lockManager.lock(1, txn1, LockType.READ, 0, false,
297: null);
298: assertTrue(lockManager.isOwner(nid, txn1,
299: LockType.READ));
300: while (lockManager.nWaiters(nid) < 2) {
301: Thread.yield();
302: }
303: lockManager.release(1L, txn1);
304: txn1.removeLock(1L);
305: } catch (DatabaseException DBE) {
306: DBE.printStackTrace();
307: fail("caught DatabaseException " + DBE);
308: }
309: }
310: };
311:
312: JUnitThread tester2 = new JUnitThread("testMultipleReaders2") {
313: public void testBody() {
314: try {
315: lockManager.lock(1, txn2, LockType.READ, 0, false,
316: null);
317: assertTrue(lockManager.isOwner(nid, txn2,
318: LockType.READ));
319: while (lockManager.nWaiters(nid) < 2) {
320: Thread.yield();
321: }
322: lockManager.release(1L, txn2);
323: txn2.removeLock(1L);
324: } catch (DatabaseException DBE) {
325: DBE.printStackTrace();
326: fail("caught DatabaseException " + DBE);
327: }
328: }
329: };
330:
331: JUnitThread tester3 = new JUnitThread("testMultipleReaders3") {
332: public void testBody() {
333: try {
334: while (lockManager.nOwners(nid) < 2) {
335: Thread.yield();
336: }
337: lockManager.lock(1, txn3, LockType.WRITE, 0, false,
338: null);
339: while (lockManager.nWaiters(nid) < 1) {
340: Thread.yield();
341: }
342: assertTrue(lockManager.isOwner(nid, txn3,
343: LockType.WRITE));
344: lockManager.release(1L, txn3);
345: txn3.removeLock(1L);
346: } catch (DatabaseException DBE) {
347: DBE.printStackTrace();
348: fail("caught DatabaseException " + DBE);
349: }
350: }
351: };
352:
353: JUnitThread tester4 = new JUnitThread("testMultipleReaders4") {
354: public void testBody() {
355: try {
356: while (lockManager.nWaiters(nid) < 1) {
357: Thread.yield();
358: }
359: lockManager.lock(1, txn4, LockType.READ, 0, false,
360: null);
361: assertTrue(lockManager.isOwner(nid, txn4,
362: LockType.READ));
363: lockManager.release(1L, txn4);
364: txn4.removeLock(1L);
365: } catch (DatabaseException DBE) {
366: DBE.printStackTrace();
367: fail("caught DatabaseException " + DBE);
368: }
369: }
370: };
371:
372: tester1.start();
373: tester2.start();
374: tester3.start();
375: tester4.start();
376: tester1.finishTest();
377: tester2.finishTest();
378: tester3.finishTest();
379: tester4.finishTest();
380: }
381:
382: /**
383: * Acquire two read locks for two transactions, then request a write
384: * lock for a third transaction. Then request a write lock for one
385: * of the first transactions that already has a read lock (i.e.
386: * request an upgrade lock). Make sure it butts in front of the
387: * existing wait lock.
388: */
389: public void testUpgradeLock() throws Throwable {
390:
391: JUnitThread tester1 = new JUnitThread("testUpgradeLock1") {
392: public void testBody() {
393: try {
394: lockManager.lock(1, txn1, LockType.READ, 0, false,
395: null);
396: assertTrue(lockManager.isOwner(nid, txn1,
397: LockType.READ));
398: while (lockManager.nWaiters(nid) < 2) {
399: Thread.yield();
400: }
401: lockManager.release(1L, txn1);
402: txn1.removeLock(1L);
403: } catch (DatabaseException DBE) {
404: DBE.printStackTrace();
405: fail("caught DatabaseException " + DBE);
406: }
407: }
408: };
409:
410: JUnitThread tester2 = new JUnitThread("testUpgradeLock2") {
411: public void testBody() {
412: try {
413: lockManager.lock(1, txn2, LockType.READ, 0, false,
414: null);
415: assertTrue(lockManager.isOwner(nid, txn2,
416: LockType.READ));
417: while (lockManager.nWaiters(nid) < 1) {
418: Thread.yield();
419: }
420: lockManager.lock(1, txn2, LockType.WRITE, 0, false,
421: null);
422: assertTrue(lockManager.nWaiters(nid) == 1);
423: lockManager.release(1L, txn2);
424: txn2.removeLock(1L);
425: } catch (DatabaseException DBE) {
426: DBE.printStackTrace();
427: fail("caught DatabaseException " + DBE);
428: }
429: }
430: };
431:
432: JUnitThread tester3 = new JUnitThread("testUpgradeLock3") {
433: public void testBody() {
434: try {
435: while (lockManager.nOwners(nid) < 2) {
436: Thread.yield();
437: }
438: lockManager.lock(1, txn3, LockType.WRITE, 0, false,
439: null);
440: assertTrue(lockManager.isOwner(nid, txn3,
441: LockType.WRITE));
442: lockManager.release(1L, txn3);
443: txn3.removeLock(1L);
444: } catch (DatabaseException DBE) {
445: DBE.printStackTrace();
446: fail("caught DatabaseException " + DBE);
447: }
448: }
449: };
450:
451: tester1.start();
452: tester2.start();
453: tester3.start();
454: tester1.finishTest();
455: tester2.finishTest();
456: tester3.finishTest();
457: }
458:
459: /**
460: * Acquire a read lock, then request a write lock for a second
461: * transaction in non-blocking mode. Make sure it fails.
462: */
463: public void testNonBlockingLock1() throws Throwable {
464:
465: JUnitThread tester1 = new JUnitThread("testNonBlocking1") {
466: public void testBody() {
467: try {
468: lockManager.lock(1, txn1, LockType.READ, 0, false,
469: null);
470: assertTrue(lockManager.isOwner(nid, txn1,
471: LockType.READ));
472: while (sequence < 1) {
473: Thread.yield();
474: }
475: lockManager.release(1L, txn1);
476: txn1.removeLock(1L);
477: } catch (DatabaseException DBE) {
478: DBE.printStackTrace();
479: fail("caught DatabaseException " + DBE);
480: }
481: }
482: };
483:
484: JUnitThread tester2 = new JUnitThread("testNonBlocking2") {
485: public void testBody() {
486: try {
487: /* wait for tester1 */
488: while (lockManager.nOwners(nid) < 1) {
489: Thread.yield();
490: }
491: LockGrantType grant = lockManager.lock(1, txn2,
492: LockType.WRITE, 0, true, null);
493: assertSame(LockGrantType.DENIED, grant);
494: assertFalse(lockManager.isOwner(nid, txn2,
495: LockType.WRITE));
496: assertFalse(lockManager.isOwner(nid, txn2,
497: LockType.READ));
498: assertTrue(lockManager.nWaiters(nid) == 0);
499: assertTrue(lockManager.nOwners(nid) == 1);
500: sequence++;
501: /* wait for tester1 to release the lock */
502: while (lockManager.nOwners(nid) > 0) {
503: Thread.yield();
504: }
505: assertTrue(lockManager.lock(1, txn2,
506: LockType.WRITE, 0, false, null) == LockGrantType.NEW);
507: assertTrue(lockManager.isOwner(nid, txn2,
508: LockType.WRITE));
509: assertTrue(lockManager.isOwner(nid, txn2,
510: LockType.READ));
511: assertTrue(lockManager.nWaiters(nid) == 0);
512: assertTrue(lockManager.nOwners(nid) == 1);
513: lockManager.release(1L, txn2);
514: txn2.removeLock(1L);
515: } catch (DatabaseException DBE) {
516: DBE.printStackTrace();
517: fail("caught DatabaseException " + DBE);
518: }
519: }
520: };
521:
522: tester1.start();
523: tester2.start();
524: tester1.finishTest();
525: tester2.finishTest();
526: }
527:
528: /**
529: * Acquire a write lock, then request a read lock for a second
530: * transaction in non-blocking mode. Make sure it fails.
531: */
532: public void testNonBlockingLock2() throws Throwable {
533:
534: JUnitThread tester1 = new JUnitThread("testNonBlocking1") {
535: public void testBody() {
536: try {
537: lockManager.lock(1, txn1, LockType.WRITE, 0, false,
538: null);
539: assertTrue(lockManager.isOwner(nid, txn1,
540: LockType.WRITE));
541: sequence++;
542: while (sequence < 2) {
543: Thread.yield();
544: }
545: lockManager.release(1L, txn1);
546: txn1.removeLock(1L);
547: } catch (DatabaseException DBE) {
548: DBE.printStackTrace();
549: fail("caught DatabaseException " + DBE);
550: }
551: }
552: };
553:
554: JUnitThread tester2 = new JUnitThread("testNonBlocking2") {
555: public void testBody() {
556: try {
557: /* wait for tester1 */
558: while (sequence < 1) {
559: Thread.yield();
560: }
561: LockGrantType grant = lockManager.lock(1, txn2,
562: LockType.READ, 0, true, null);
563: assertSame(LockGrantType.DENIED, grant);
564: assertFalse(lockManager.isOwner(nid, txn2,
565: LockType.READ));
566: assertFalse(lockManager.isOwner(nid, txn2,
567: LockType.WRITE));
568: assertTrue(lockManager.nWaiters(nid) == 0);
569: assertTrue(lockManager.nOwners(nid) == 1);
570: sequence++;
571: /* wait for tester1 to release the lock */
572: while (lockManager.nOwners(nid) > 0) {
573: Thread.yield();
574: }
575: assertTrue(lockManager.lock(1, txn2, LockType.READ,
576: 0, false, null) == LockGrantType.NEW);
577: assertTrue(lockManager.isOwner(nid, txn2,
578: LockType.READ));
579: assertFalse(lockManager.isOwner(nid, txn2,
580: LockType.WRITE));
581: assertTrue(lockManager.nWaiters(nid) == 0);
582: assertTrue(lockManager.nOwners(nid) == 1);
583: lockManager.release(1L, txn2);
584: txn2.removeLock(1L);
585: } catch (DatabaseException DBE) {
586: DBE.printStackTrace();
587: fail("caught DatabaseException " + DBE);
588: }
589: }
590: };
591:
592: tester1.start();
593: tester2.start();
594: tester1.finishTest();
595: tester2.finishTest();
596: }
597:
598: /**
599: * Acquire a write lock, then request a read lock for a second
600: * transaction in blocking mode. Make sure it waits.
601: */
602: public void testWaitingLock() throws Throwable {
603:
604: JUnitThread tester1 = new JUnitThread("testBlocking1") {
605: public void testBody() {
606: try {
607: lockManager.lock(1, txn1, LockType.WRITE, 0, false,
608: null);
609: assertTrue(lockManager.isOwner(nid, txn1,
610: LockType.WRITE));
611: sequence++;
612: while (sequence < 2) {
613: Thread.yield();
614: }
615: lockManager.release(1L, txn1);
616: txn1.removeLock(1L);
617: } catch (DatabaseException DBE) {
618: DBE.printStackTrace();
619: fail("caught DatabaseException " + DBE);
620: }
621: }
622: };
623:
624: JUnitThread tester2 = new JUnitThread("testBlocking2") {
625: public void testBody() {
626: try {
627: /* wait for tester1 */
628: while (sequence < 1) {
629: Thread.yield();
630: }
631: try {
632: lockManager.lock(1, txn2, LockType.READ, 500,
633: false, null);
634: fail("didn't time out");
635: } catch (DeadlockException e) {
636: assertTrue(TestUtils.skipVersion(e).startsWith(
637: "Lock "));
638: }
639: assertFalse(lockManager.isOwner(nid, txn2,
640: LockType.READ));
641: assertFalse(lockManager.isOwner(nid, txn2,
642: LockType.WRITE));
643: assertTrue(lockManager.nWaiters(nid) == 0);
644: assertTrue(lockManager.nOwners(nid) == 1);
645: sequence++;
646: /* wait for tester1 to release the lock */
647: while (lockManager.nOwners(nid) > 0) {
648: Thread.yield();
649: }
650: assertTrue(lockManager.lock(1, txn2, LockType.READ,
651: 0, false, null) == LockGrantType.NEW);
652: assertTrue(lockManager.isOwner(nid, txn2,
653: LockType.READ));
654: assertFalse(lockManager.isOwner(nid, txn2,
655: LockType.WRITE));
656: assertTrue(lockManager.nWaiters(nid) == 0);
657: assertTrue(lockManager.nOwners(nid) == 1);
658: lockManager.release(1L, txn2);
659: txn2.removeLock(1L);
660: } catch (DatabaseException DBE) {
661: DBE.printStackTrace();
662: fail("caught DatabaseException " + DBE);
663: }
664: }
665: };
666:
667: tester1.start();
668: tester2.start();
669: tester1.finishTest();
670: tester2.finishTest();
671: }
672:
673: /**
674: * Test that DeadlockException has the correct owners and waiters when
675: * it is thrown due to a timeout.
676: *
677: * Create five threads, the first two of which take a readlock and the
678: * second two of which try for a write lock backed up behind the two
679: * read locks. Then have a fifth thread try for a read lock which backs
680: * up behind all of them. The first two threads (read lockers) are owners
681: * and the second two threads are waiters. When the fifth thread catches
682: * the DeadlockException make sure that it contains the txn ids for the
683: * two readers in the owners array and the txn ids for the two writers
684: * in the waiters array.
685: */
686: public void testDeadlock() throws Throwable {
687:
688: /* Get rid of these inferior BasicLockers -- we want real Txns. */
689: txn1.operationEnd();
690: txn2.operationEnd();
691: txn3.operationEnd();
692: txn4.operationEnd();
693:
694: TransactionConfig config = new TransactionConfig();
695: txn1 = new Txn(env, config);
696: txn2 = new Txn(env, config);
697: txn3 = new Txn(env, config);
698: txn4 = new Txn(env, config);
699: final Txn txn5 = new Txn(env, config);
700:
701: sequence = 0;
702: JUnitThread tester1 = new JUnitThread("testMultipleReaders1") {
703: public void testBody() {
704: try {
705: lockManager.lock(1, txn1, LockType.READ, 0, false,
706: null);
707: assertTrue(lockManager.isOwner(nid, txn1,
708: LockType.READ));
709: while (sequence < 1) {
710: Thread.yield();
711: }
712: lockManager.release(1L, txn1);
713: txn1.removeLock(1L);
714: } catch (DatabaseException DBE) {
715: DBE.printStackTrace();
716: fail("caught DatabaseException " + DBE);
717: }
718: }
719: };
720:
721: JUnitThread tester2 = new JUnitThread("testMultipleReaders2") {
722: public void testBody() {
723: try {
724: lockManager.lock(1, txn2, LockType.READ, 0, false,
725: null);
726: assertTrue(lockManager.isOwner(nid, txn2,
727: LockType.READ));
728: while (sequence < 1) {
729: Thread.yield();
730: }
731: lockManager.release(1L, txn2);
732: txn2.removeLock(1L);
733: } catch (DatabaseException DBE) {
734: DBE.printStackTrace();
735: fail("caught DatabaseException " + DBE);
736: }
737: }
738: };
739:
740: JUnitThread tester3 = new JUnitThread("testMultipleReaders3") {
741: public void testBody() {
742: try {
743: while (lockManager.nOwners(nid) < 2) {
744: Thread.yield();
745: }
746: lockManager.lock(1, txn3, LockType.WRITE, 0, false,
747: null);
748: while (sequence < 1) {
749: Thread.yield();
750: }
751: assertTrue(lockManager.isOwner(nid, txn3,
752: LockType.WRITE));
753: lockManager.release(1L, txn3);
754: txn3.removeLock(1L);
755: } catch (DatabaseException DBE) {
756: DBE.printStackTrace();
757: fail("caught DatabaseException " + DBE);
758: }
759: }
760: };
761:
762: JUnitThread tester4 = new JUnitThread("testMultipleReaders4") {
763: public void testBody() {
764: try {
765: while (lockManager.nOwners(nid) < 2) {
766: Thread.yield();
767: }
768: lockManager.lock(1, txn4, LockType.WRITE, 0, false,
769: null);
770: while (sequence < 1) {
771: Thread.yield();
772: }
773: assertTrue(lockManager.isOwner(nid, txn4,
774: LockType.WRITE));
775: lockManager.release(1L, txn4);
776: txn4.removeLock(1L);
777: } catch (DatabaseException DBE) {
778: DBE.printStackTrace();
779: fail("caught DatabaseException " + DBE);
780: }
781: }
782: };
783:
784: JUnitThread tester5 = new JUnitThread("testMultipleReaders5") {
785: public void testBody() {
786: try {
787: while (lockManager.nWaiters(nid) < 1) {
788: Thread.yield();
789: }
790: lockManager.lock(1, txn5, LockType.READ, 900,
791: false, null);
792: fail("expected DeadlockException");
793: } catch (DeadlockException DLE) {
794:
795: long[] owners = DLE.getOwnerTxnIds();
796: long[] waiters = DLE.getWaiterTxnIds();
797:
798: assertTrue((owners[0] == txn1.getId() && owners[1] == txn2
799: .getId())
800: || (owners[1] == txn1.getId() && owners[0] == txn2
801: .getId()));
802:
803: assertTrue((waiters[0] == txn3.getId() && waiters[1] == txn4
804: .getId())
805: || (waiters[1] == txn3.getId() && waiters[0] == txn4
806: .getId()));
807:
808: } catch (DatabaseException DBE) {
809: fail("expected DeadlockException");
810: DBE.printStackTrace(System.out);
811: }
812: System.out.println("setting sequence to 1");
813: sequence = 1;
814: }
815: };
816:
817: tester1.start();
818: tester2.start();
819: tester3.start();
820: tester4.start();
821: tester5.start();
822: tester1.finishTest();
823: tester2.finishTest();
824: tester3.finishTest();
825: tester4.finishTest();
826: tester5.finishTest();
827: ((Txn) txn1).abort(false);
828: ((Txn) txn2).abort(false);
829: ((Txn) txn3).abort(false);
830: ((Txn) txn4).abort(false);
831: txn5.abort(false);
832: }
833: }
|