View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.transaction.locking;
18  
19  import java.io.PrintWriter;
20  
21  import junit.framework.Test;
22  import junit.framework.TestCase;
23  import junit.framework.TestSuite;
24  
25  import org.apache.commons.transaction.util.LoggerFacade;
26  import org.apache.commons.transaction.util.PrintWriterLogger;
27  import org.apache.commons.transaction.util.RendezvousBarrier;
28  import org.apache.commons.transaction.util.TurnBarrier;
29  
30  /**
31   * Tests for generic locks. 
32   *
33   * @version $Id: GenericLockTest.java 493628 2007-01-07 01:42:48Z joerg $
34   */
35  public class GenericLockTest extends TestCase {
36  
37      private static final LoggerFacade sLogger = new PrintWriterLogger(new PrintWriter(System.out),
38              GenericLockTest.class.getName(), false);
39  
40      protected static final int READ_LOCK = 1;
41      protected static final int WRITE_LOCK = 2;
42      
43      private static final int CONCURRENT_TESTS = 25;
44      
45      protected static final long TIMEOUT = 1000000;
46      
47      private static int deadlockCnt = 0;
48      private static String first = null;
49  
50      public static Test suite() {
51          TestSuite suite = new TestSuite(GenericLockTest.class);
52          return suite;
53      }
54  
55      public static void main(java.lang.String[] args) {
56          junit.textui.TestRunner.run(suite());
57      }
58  
59      public GenericLockTest(String testName) {
60          super(testName);
61      }
62  
63      // we do not wait, as we only want the check the results and do not want real locking
64      protected boolean acquireNoWait(GenericLock lock, String owner, int targetLockLevel)  {
65          try {
66              return lock.acquire(owner, targetLockLevel, false, true, -1);
67          } catch (InterruptedException e) {
68              return false;
69          }
70      }
71  
72      public void testBasic() throws Throwable {
73  
74          sLogger.logInfo("\n\nChecking basic map features\n\n");
75  
76          String owner1 = "owner1";
77          String owner2 = "owner2";
78          String owner3 = "owner3";
79          
80          // a read / write lock
81          GenericLock lock = new GenericLock("Test read write lock", WRITE_LOCK, sLogger);
82          
83          // of course more than one can read
84          boolean canRead1 = acquireNoWait(lock, owner1, READ_LOCK);
85          assertTrue(canRead1);
86          boolean canRead2 = acquireNoWait(lock, owner2, READ_LOCK);
87          assertTrue(canRead2);
88          
89          // as there already are read locks, this write should not be possible
90          boolean canWrite3 = acquireNoWait(lock, owner3, WRITE_LOCK);
91          assertFalse(canWrite3);
92          
93          // release one read lock
94          lock.release(owner2);
95          // this should not change anything with the write as there is still one read lock left
96          canWrite3 = acquireNoWait(lock, owner3, WRITE_LOCK);
97          assertFalse(canWrite3);
98  
99          // release the other and final read lock as well
100         lock.release(owner1);
101         // no we should be able to get write access
102         canWrite3 = acquireNoWait(lock, owner3, WRITE_LOCK);
103         assertTrue(canWrite3);
104         // but of course no more read access
105         canRead2 = acquireNoWait(lock, owner2, READ_LOCK);
106         assertFalse(canRead2);
107         
108         // relase the write lock and make sure we can read again
109         lock.release(owner3);
110         canRead2 = acquireNoWait(lock, owner2, READ_LOCK);
111         assertTrue(canRead2);
112         
113         // now we do something weired, we try to block all locks lower than write...
114         boolean canBlock3 = lock.acquire(owner3, WRITE_LOCK, false, GenericLock.COMPATIBILITY_SUPPORT, -1);
115         // which of course does not work, as there already is an incompatible read lock
116         assertFalse(canBlock3);
117         
118         // ok, release read lock (no we have no more locks) and try again
119         lock.release(owner2);
120         canBlock3 = lock.acquire(owner3, WRITE_LOCK, false, GenericLock.COMPATIBILITY_SUPPORT, -1);
121         // which now should work creating an ordinary lock
122         assertTrue(canBlock3);
123         
124         // as this just an ordinary lock, we should not get a read lock:
125         canRead1 = acquireNoWait(lock, owner1, READ_LOCK);
126         assertFalse(canRead1);
127         
128         // this is the trick now, we *can* get an addtional write lock with this request as it has
129         // the same level as the write lock already set. This works, as we do not care for the
130         // write lock level, but only want to inhibit the read lock:
131         boolean canBlock2 = lock.acquire(owner2, WRITE_LOCK, false, GenericLock.COMPATIBILITY_SUPPORT, -1);
132         assertTrue(canBlock2);
133         
134         // now if we release one of the blocks supporting each other we still should not get a
135         // read lock
136         lock.release(owner3);
137         canRead1 = acquireNoWait(lock, owner1, READ_LOCK);
138         assertFalse(canRead1);
139 
140         // but of course after we release the second as well
141         lock.release(owner2);
142         canRead1 = acquireNoWait(lock, owner1, READ_LOCK);
143         assertTrue(canRead1);
144     }
145 
146     public void testTimeout() {
147         
148         sLogger.logInfo("\n\nChecking timeouts\n\n");
149 
150         ReadWriteLockManager lockManager = new ReadWriteLockManager(sLogger, 1000);
151         boolean timedOut = false;
152         try {
153             lockManager.readLock("owner1", "resource");
154             lockManager.writeLock("owner2", "resource");
155         } catch (LockException le) {
156             assertEquals(le.getCode(), LockException.CODE_TIMED_OUT);
157             timedOut = true;
158         }
159         assertTrue(timedOut);
160         lockManager = new ReadWriteLockManager(sLogger, 100);
161         timedOut = false;
162         try {
163             lockManager.readLock("owner1", "resource");
164             lockManager.writeLock("owner2", "resource");
165         } catch (LockException le) {
166             assertEquals(le.getCode(), LockException.CODE_TIMED_OUT);
167             timedOut = true;
168         }
169         assertTrue(timedOut);
170         lockManager = new ReadWriteLockManager(sLogger, 0);
171         timedOut = false;
172         try {
173             lockManager.readLock("owner1", "resource");
174             lockManager.writeLock("owner2", "resource");
175         } catch (LockException le) {
176             assertEquals(le.getCode(), LockException.CODE_TIMED_OUT);
177             timedOut = true;
178         }
179         assertTrue(timedOut);
180     }
181     
182 
183     public void testDeadlock() throws Throwable {
184 
185         sLogger.logInfo("\n\nChecking deadlock detection\n\n");
186 
187         final String owner1 = "owner1";
188         final String owner2 = "owner2";
189 
190         final String res1 = "res1";
191         final String res2 = "res2";
192 
193         // a read / write lock
194         final ReadWriteLockManager manager = new ReadWriteLockManager(sLogger, TIMEOUT);
195         
196         final RendezvousBarrier restart = new RendezvousBarrier("restart",
197                 TIMEOUT, sLogger);
198 
199         for (int i = 0; i < CONCURRENT_TESTS; i++) {
200 
201            System.out.print(".");
202             
203             final RendezvousBarrier deadlockBarrier1 = new RendezvousBarrier("deadlock1" + i,
204                     TIMEOUT, sLogger);
205 
206             Thread deadlock = new Thread(new Runnable() {
207                 public void run() {
208                     try {
209                         // first both threads get a lock, this one on res2
210                         manager.writeLock(owner2, res2);
211                         synchronized (deadlockBarrier1) {
212                             deadlockBarrier1.meet();
213                             deadlockBarrier1.reset();
214                         }
215                         // if I am first, the other thread will be dead, i.e.
216                         // exactly one
217                         manager.writeLock(owner2, res1);
218                     } catch (LockException le) {
219                         assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
220                         deadlockCnt++;
221                     } catch (InterruptedException ie) {
222                     } finally {
223                         manager.releaseAll(owner2);
224                         try {
225                             synchronized (restart) {
226                                 restart.meet();
227                                 restart.reset();
228                             }
229                             } catch (InterruptedException ie) {}
230                     }
231                 }
232             }, "Deadlock Thread");
233 
234             deadlock.start();
235 
236             try {
237                 // first both threads get a lock, this one on res2
238                 manager.readLock(owner1, res1);
239                 synchronized (deadlockBarrier1) {
240                     deadlockBarrier1.meet();
241                     deadlockBarrier1.reset();
242                 }
243                 //          if I am first, the other thread will be dead, i.e. exactly
244                 // one
245                 manager.readLock(owner1, res2);
246             } catch (LockException le) {
247                 assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
248                 deadlockCnt++;
249             } finally {
250                 manager.releaseAll(owner1);
251                 synchronized (restart) {
252                     restart.meet();
253                     restart.reset();
254                 }
255             }
256 
257             // XXX in special scenarios the current implementation might cause both
258             // owners to be deadlock victims
259             if (deadlockCnt != 1) {
260                 sLogger.logWarning("More than one thread was deadlock victim!");
261             }
262             assertTrue(deadlockCnt >= 1);
263             deadlockCnt = 0;
264         }
265     }
266 
267     /*
268      * 
269      * Test detection of an indirect deadlock:
270      * 
271      *                  Owner           Owner           Owner
272      * Step             #1              #2              #3
273      * 1                read res1 (ok)
274      * 2                                read res2 (ok)
275      * 3                                                read res3 (ok)
276      * 4                                                write res2 (blocked because of #2)
277      * 5                                write res1
278      *                                  (blocked 
279      *                                  because of #1)
280      * 6                write res3
281      *                  (blocked 
282      *                   because #3)
283      * 
284      * - Thread#1 waits for Thread#3 on res3
285      * - Thread#2 waits for Thread#1 on res1
286      * - Thread#3 waits for Thread#2 on res2
287      *
288      * This needs recursion of the deadlock detection algorithm
289      *  
290      */
291     public void testIndirectDeadlock() throws Throwable {
292 
293         sLogger.logInfo("\n\nChecking detection of indirect deadlock \n\n");
294 
295         final String jamowner1 = "jamowner1";
296         final String jamowner2 = "jamowner2";
297 
298         final String owner1 = "owner1";
299         final String owner2 = "owner2";
300         final String owner3 = "owner3";
301 
302         final String res1 = "res1";
303         final String res2 = "res2";
304         final String res3 = "res3";
305 
306         // a read / write lock
307         final ReadWriteLockManager manager = new ReadWriteLockManager(sLogger,
308                 TIMEOUT);
309 
310         final RendezvousBarrier restart = new RendezvousBarrier("restart", 5, TIMEOUT, sLogger);
311 
312         final TurnBarrier cb = new TurnBarrier("cb1", TIMEOUT, sLogger, 1);
313 
314         for (int i = 0; i < CONCURRENT_TESTS; i++) {
315             
316             System.out.print(".");
317 
318             // thread that accesses lock of res1 just to cause interference and
319             // possibly detect concurrency problems
320             Thread jamThread1 = new Thread(new Runnable() {
321                 public void run() {
322                     try {
323                         for (int i = 0; i < 10; i++) {
324                             manager.readLock(jamowner1, res1);
325                             Thread.sleep(10);
326                             manager.releaseAll(jamowner1);
327                             Thread.sleep(10);
328                             manager.writeLock(jamowner1, res1);
329                             Thread.sleep(10);
330                             manager.releaseAll(jamowner1);
331                             Thread.sleep(10);
332                         }
333                     } catch (LockException le) {
334                         fail("Jam Thread should not fail");
335                     } catch (InterruptedException ie) {
336                     } finally {
337                         manager.releaseAll(jamowner1);
338                         synchronized (restart) {
339                             try {
340                                 synchronized (restart) {
341                                     restart.meet();
342                                     restart.reset();
343                                 }
344                                 } catch (InterruptedException ie) {}
345                         }
346                     }
347                 }
348             }, "Jam Thread #1");
349 
350             jamThread1.start();
351 
352             // thread that accesses lock of res1 just to cause interference and
353             // possibly detect concurrency problems
354             Thread jamThread2 = new Thread(new Runnable() {
355                 public void run() {
356                     try {
357                         for (int i = 0; i < 10; i++) {
358                             manager.writeLock(jamowner2, res1);
359                             Thread.sleep(10);
360                             manager.releaseAll(jamowner2);
361                             Thread.sleep(10);
362                             manager.readLock(jamowner2, res1);
363                             Thread.sleep(10);
364                             manager.releaseAll(jamowner2);
365                             Thread.sleep(10);
366                         }
367                     } catch (LockException le) {
368                         fail("Jam Thread should not fail");
369                     } catch (InterruptedException ie) {
370                     } finally {
371                         manager.releaseAll(jamowner2);
372                         synchronized (restart) {
373                             try {
374                                 synchronized (restart) {
375                                     restart.meet();
376                                     restart.reset();
377                                 }
378                                 } catch (InterruptedException ie) {}
379                         }
380                     }
381                 }
382             }, "Jam Thread #2");
383 
384             jamThread2.start();
385 
386             Thread t1 = new Thread(new Runnable() {
387                 public void run() {
388                     try {
389                         cb.waitForTurn(2);
390                         manager.readLock(owner2, res2);
391                         cb.signalTurn(3);
392                         cb.waitForTurn(5);
393                         synchronized (manager.getLock(res1)) {
394                             cb.signalTurn(6);
395                             manager.writeLock(owner2, res1);
396                         }
397                     } catch (LockException le) {
398                         assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
399                         deadlockCnt++;
400                     } catch (InterruptedException ie) {
401                     } finally {
402                         manager.releaseAll(owner2);
403                         synchronized (restart) {
404                             try {
405                                 synchronized (restart) {
406                                     restart.meet();
407                                     restart.reset();
408                                 }
409                                 } catch (InterruptedException ie) {}
410                         }
411                     }
412                 }
413             }, "Thread #1");
414 
415             t1.start();
416 
417             Thread t2 = new Thread(new Runnable() {
418                 public void run() {
419                     try {
420                         cb.waitForTurn(3);
421                         manager.readLock(owner3, res3);
422                         synchronized (manager.getLock(res2)) {
423                             cb.signalTurn(5);
424                             manager.writeLock(owner3, res2);
425                         }
426                     } catch (LockException le) {
427                         assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
428                         deadlockCnt++;
429                     } catch (InterruptedException ie) {
430                     } finally {
431                         manager.releaseAll(owner3);
432                         synchronized (restart) {
433                             try {
434                                 synchronized (restart) {
435                                     restart.meet();
436                                     restart.reset();
437                                 }
438                                 } catch (InterruptedException ie) {}
439                         }
440                     }
441                 }
442             }, "Thread #2");
443 
444             t2.start();
445 
446             try {
447                 cb.waitForTurn(1);
448                 manager.readLock(owner1, res1);
449                 cb.signalTurn(2);
450                 cb.waitForTurn(6);
451                 manager.writeLock(owner1, res3);
452             } catch (LockException le) {
453                 assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
454                 deadlockCnt++;
455             } catch (InterruptedException ie) {
456             } finally {
457                 manager.releaseAll(owner1);
458                 synchronized (restart) {
459                     try {
460                         synchronized (restart) {
461                             restart.meet();
462                             restart.reset();
463                         }
464                     } catch (InterruptedException ie) {
465                     }
466                 }
467             }
468 
469             // XXX in special scenarios the current implementation might cause more than one
470             // owner to be a deadlock victim
471             if (deadlockCnt != 1) {
472                 sLogger.logWarning("\nMore than one thread was deadlock victim!\n");
473             }
474             assertTrue(deadlockCnt >= 1);
475             deadlockCnt = 0;
476             cb.reset();
477         }
478     }
479 
480     /*
481      * 
482      * Test shows the following
483      * - upgrade works with read locks no matter if they are acquired before or later (1-4)
484      * - write is blocked by read (5)
485      * - read is blocked by intention lock (6)
486      * - write lock coming from an intention lock always has preference over others (7)
487      * 
488      * 
489      *                  Owner           Owner           Owner
490      * Step             #1              #2              #3
491      * 1                read (ok)
492      * 2                                upgrade (ok)
493      * 3                release (ok)
494      * 4                read (ok)
495      * 5                                write (blocked 
496      *                                  because of #1)
497      * 6                                                read (blocked 
498      *                                                  because intention of #2)        
499      * 7                release         resumed
500      * 8                                release         resumed
501      * 9                                                release
502      */
503     public void testUpgrade() throws Throwable {
504 
505         sLogger.logInfo("\n\nChecking upgrade and preference lock\n\n");
506         
507         final String owner1 = "owner1";
508         final String owner2 = "owner2";
509         final String owner3 = "owner3";
510 
511         final String res1 = "res1";
512 
513         // a read / write lock
514         final ReadWriteUpgradeLockManager manager = new ReadWriteUpgradeLockManager(sLogger,
515                 TIMEOUT);
516 
517         final RendezvousBarrier restart = new RendezvousBarrier("restart", 3, TIMEOUT, sLogger);
518 
519         final TurnBarrier cb = new TurnBarrier("cb1", TIMEOUT, sLogger, 1);
520 
521         for (int i = 0; i < CONCURRENT_TESTS; i++) {
522             
523             System.out.print(".");
524 
525             Thread t1 = new Thread(new Runnable() {
526                 public void run() {
527                     try {
528                         cb.waitForTurn(2);
529                         manager.upgradeLock(owner2, res1);
530                         cb.signalTurn(3);
531                         cb.waitForTurn(5);
532                         synchronized (manager.getLock(res1)) {
533                             cb.signalTurn(6);
534                             manager.writeLock(owner2, res1);
535                         }
536                         // we must always be first as we will be preferred over
537                         // as I had the upgrade
538                         // lock before
539                         synchronized (this) {
540                             if (first == null)
541                                 first = owner2;
542                         }
543                         manager.releaseAll(owner2);
544                         synchronized (restart) {
545                             restart.meet();
546                             restart.reset();
547                         }
548                     } catch (InterruptedException ie) {
549                     }
550                 }
551             }, "Thread #1");
552 
553             t1.start();
554 
555             Thread t2 = new Thread(new Runnable() {
556                 public void run() {
557                     try {
558                         // I wait until the others are blocked
559                         // when I release my single read lock, thread #1 always
560                         // should be the
561                         // next to get the lock as it is preferred over the main
562                         // thread
563                         // that only waits for a read lock
564                         cb.waitForTurn(6);
565                         synchronized (manager.getLock(res1)) {
566                             cb.signalTurn(7);
567                             manager.readLock(owner3, res1);
568                         }
569                         synchronized (this) {
570                             if (first == null)
571                                 first = owner3;
572                         }
573                         manager.releaseAll(owner3);
574                         synchronized (restart) {
575                             restart.meet();
576                             restart.reset();
577                         }
578                     } catch (InterruptedException ie) {
579                     }
580                 }
581             }, "Thread #2");
582 
583             t2.start();
584 
585             cb.waitForTurn(1);
586             manager.readLock(owner1, res1);
587             cb.signalTurn(2);
588             cb.waitForTurn(3);
589             manager.release(owner1, res1);
590             manager.readLock(owner1, res1);
591             cb.signalTurn(5);
592             cb.waitForTurn(7);
593             synchronized (manager.getLock(res1)) {
594                 manager.releaseAll(owner1);
595             }
596             synchronized (restart) {
597                 restart.meet();
598                 restart.reset();
599             }
600 
601             assertEquals(first, owner2);
602             first = null;
603             cb.reset();
604         }
605 
606     }
607     
608     /*
609      * 
610      * Test shows that two preference locks that are imcompatible do not cause a lock out
611      * which was the case with GenericLock 1.5
612      * Before the fix this test would dealock
613      * 
614      *                  Owner           Owner           Owner
615      * Step             #1              #2              #3
616      * 1                read (ok)
617      * 2                                write preferred 
618      *                                  (blocked 
619      *                                  because of #1)
620      * 3                                                write preferred 
621      *                                                  (blocked 
622      *                                                  because of #1 and #2)
623      * 4                release
624      * 5                                resumed   or    resumed 
625      *                                  (as both are preferred, problem
626      *                                   is that that would exclude each other
627      *                                   in the algorithm used)
628      * 6                                released   or   released
629      * 7                                resumed   or    resumed 
630      * 8                                released   or   released
631      * 
632      * 
633      */
634     public void testPreference() throws Throwable {
635 
636         sLogger.logInfo("\n\nChecking incompatible preference locks\n\n");
637         
638         final String owner1 = "owner1";
639         final String owner2 = "owner2";
640         final String owner3 = "owner3";
641 
642         final String res1 = "res1";
643 
644         final ReadWriteLock lock = new ReadWriteLock(res1, sLogger);
645 
646         final RendezvousBarrier restart = new RendezvousBarrier("restart", 3, TIMEOUT, sLogger);
647 
648         final TurnBarrier cb = new TurnBarrier("cb1", TIMEOUT, sLogger, 1);
649 
650         for (int i = 0; i < CONCURRENT_TESTS; i++) {
651             
652             System.out.print(".");
653 
654             Thread t1 = new Thread(new Runnable() {
655                 public void run() {
656                     try {
657                         cb.waitForTurn(2);
658                         synchronized (lock) {
659                             cb.signalTurn(3);
660                             lock.acquire(owner2, ReadWriteLock.WRITE_LOCK, true,
661                                     GenericLock.COMPATIBILITY_REENTRANT, true, TIMEOUT);
662                         }
663                         lock.release(owner2);
664                         synchronized (restart) {
665                             restart.meet();
666                             restart.reset();
667                         }
668                     } catch (InterruptedException ie) {
669                     }
670                 }
671             }, "Thread #1");
672 
673             t1.start();
674 
675             Thread t2 = new Thread(new Runnable() {
676                 public void run() {
677                     try {
678                         cb.waitForTurn(3);
679                         synchronized (lock) {
680                             cb.signalTurn(4);
681                             lock.acquire(owner3, ReadWriteLock.WRITE_LOCK, true,
682                                     GenericLock.COMPATIBILITY_REENTRANT, true, TIMEOUT);
683                         }
684                         lock.release(owner3);
685                         synchronized (restart) {
686                             restart.meet();
687                             restart.reset();
688                         }
689                     } catch (InterruptedException ie) {
690                     }
691                 }
692             }, "Thread #2");
693 
694             t2.start();
695 
696             cb.waitForTurn(1);
697             lock.acquireRead(owner1, TIMEOUT);
698             cb.signalTurn(2);
699             cb.waitForTurn(4);
700             synchronized (lock) {
701                 lock.release(owner1);
702             }
703             synchronized (restart) {
704                 restart.meet();
705                 restart.reset();
706             }
707 
708             cb.reset();
709         }
710 
711     }
712     
713     public void testGlobalTimeout() throws Throwable {
714 
715         sLogger.logInfo("\n\nChecking global timeouts\n\n");
716         
717         final String owner1 = "owner1";
718         final String owner2 = "owner2";
719 
720         final String res1 = "res1";
721 
722         final GenericLockManager manager = new GenericLockManager(1, sLogger, TIMEOUT, -1);
723 
724         final RendezvousBarrier restart = new RendezvousBarrier("restart", 2, TIMEOUT, sLogger);
725 
726         final TurnBarrier cb = new TurnBarrier("cb1", TIMEOUT, sLogger, 1);
727 
728         for (int i = 0; i < CONCURRENT_TESTS; i++) {
729             
730             System.out.print(".");
731 
732             Thread t1 = new Thread(new Runnable() {
733                 public void run() {
734                     try {
735                         cb.waitForTurn(2);
736                         manager.lock(owner2, res1, 1, true);
737                         cb.signalTurn(3);
738                         manager.releaseAll(owner2);
739                         synchronized (restart) {
740                             restart.meet();
741                             restart.reset();
742                         }
743                     } catch (InterruptedException ie) {
744                     }
745                 }
746             }, "Thread #1");
747 
748             t1.start();
749 
750             cb.waitForTurn(1);
751             manager.startGlobalTimeout(owner1, 500);
752             manager.lock(owner1, res1, 1, true);
753             cb.signalTurn(2);
754             cb.waitForTurn(3);
755             boolean failed = false;
756             try {
757                 manager.tryLock(owner1, res1, 1, true);
758             } catch (LockException le) {
759                 failed = true;
760             }
761             assertTrue(failed);
762             manager.releaseAll(owner1);
763             failed = false;
764             try {
765                 manager.tryLock(owner1, res1, 1, true);
766             } catch (LockException le) {
767                 failed = true;
768             }
769             assertFalse(failed);
770             manager.releaseAll(owner1);
771             synchronized (restart) {
772                 restart.meet();
773                 restart.reset();
774             }
775 
776             cb.reset();
777         }
778 
779     }
780 
781     public void testStress() throws Throwable {
782 
783         sLogger.logInfo("\n\nStress checking locks\n\n");
784         
785         final String owner1 = "owner1";
786         final String owner2 = "owner2";
787         final String owner3 = "owner3";
788         final String owner4 = "owner4";
789         final String owner5 = "owner5";
790         final String owner6 = "owner6";
791         final String owner7 = "owner7";
792         final String owner8 = "owner8";
793         final String owner9 = "owner9";
794         final String owner10 = "owner10";
795 
796         final String res1 = "res1";
797         final String res2 = "res2";
798         final String res3 = "res3";
799 
800         // choose low timeout so sometimes an owner times out
801         final ReadWriteUpgradeLockManager manager = new ReadWriteUpgradeLockManager(sLogger, 100);
802 
803         final RendezvousBarrier restart = new RendezvousBarrier("restart", 5, TIMEOUT, sLogger);
804         final RendezvousBarrier start = new RendezvousBarrier("start", 5, TIMEOUT, sLogger);
805 
806         for (int i = 0; i < CONCURRENT_TESTS; i++) {
807             
808             System.out.print(".");
809 
810             Thread t1 = new Thread(new Runnable() {
811                 public void run() {
812                     try {
813                         try {
814                             synchronized (start) {
815                                 start.meet();
816                                 start.reset();
817                             }
818                             manager.readLock(owner1, res1);
819                             manager.readLock(owner1, res2);
820                             manager.upgradeLock(owner1, res3);
821                             manager.writeLock(owner1, res3);
822                         } catch (LockException ie) {
823                         } finally {
824                             manager.releaseAll(owner1);
825                             synchronized (restart) {
826                                 restart.meet();
827                                 restart.reset();
828                             }
829                         }
830                     } catch (InterruptedException ie) {
831                     }
832                 }
833             }, "Thread #1");
834             t1.start();
835 
836             Thread t2 = new Thread(new Runnable() {
837                 public void run() {
838                     try {
839                         try {
840                             synchronized (start) {
841                                 start.meet();
842                                 start.reset();
843                             }
844                             manager.readLock(owner2, res1);
845                             manager.readLock(owner2, res2);
846                             manager.upgradeLock(owner2, res3);
847                             manager.writeLock(owner2, res3);
848                         } catch (LockException ie) {
849                         } finally {
850                             manager.releaseAll(owner2);
851                             synchronized (restart) {
852                                 restart.meet();
853                                 restart.reset();
854                             }
855                         }
856                     } catch (InterruptedException ie) {
857                     }
858                 }
859             }, "Thread #2");
860             t2.start();
861 
862             Thread t3 = new Thread(new Runnable() {
863                 public void run() {
864                     try {
865                         try {
866                             synchronized (start) {
867                                 start.meet();
868                                 start.reset();
869                             }
870                             manager.readLock(owner3, res1);
871                             manager.readLock(owner3, res2);
872                             manager.upgradeLock(owner3, res3);
873                             manager.writeLock(owner3, res3);
874                         } catch (LockException ie) {
875                         } finally {
876                             manager.releaseAll(owner3);
877                             synchronized (restart) {
878                                 restart.meet();
879                                 restart.reset();
880                             }
881                         }
882                     } catch (InterruptedException ie) {
883                     }
884                 }
885             }, "Thread #3");
886             t3.start();
887 
888             Thread t4 = new Thread(new Runnable() {
889                 public void run() {
890                     try {
891                         try {
892                             synchronized (start) {
893                                 start.meet();
894                                 start.reset();
895                             }
896                             manager.readLock(owner4, res1);
897                             manager.readLock(owner4, res2);
898                             manager.upgradeLock(owner4, res3);
899                             manager.writeLock(owner4, res3);
900                         } catch (LockException ie) {
901                         } finally {
902                             manager.releaseAll(owner4);
903                             synchronized (restart) {
904                                 restart.meet();
905                                 restart.reset();
906                             }
907                         }
908                     } catch (InterruptedException ie) {
909                     }
910                 }
911             }, "Thread #4");
912             t4.start();
913 
914             try {
915                 try {
916                     synchronized (start) {
917                         start.meet();
918                         start.reset();
919                     }
920                     manager.readLock("reader", res1);
921                     manager.readLock("reader", res2);
922                     manager.readLock("reader", res3);
923 
924                 } catch (LockException ie) {
925                 } finally {
926                     manager.releaseAll("reader");
927                     try {
928                         synchronized (restart) {
929                             restart.meet();
930                             restart.reset();
931                         }
932                     } catch (InterruptedException ie) {
933                     }
934                 }
935             } catch (InterruptedException ie) {
936             }
937         }
938 
939     }
940 
941     public void testChaos() throws Throwable {
942 
943         sLogger.logInfo("\n\nChaos testing locks for internal deadlocks resp. concurrent mods\n\n");
944 
945         final String owner1 = "owner1";
946         final String owner2 = "owner2";
947         final String owner3 = "owner3";
948         final String owner4 = "owner4";
949         final String owner5 = "owner5";
950         final String owner6 = "owner6";
951         final String owner7 = "owner7";
952         final String owner8 = "owner8";
953         final String owner9 = "owner9";
954         final String owner10 = "owner10";
955 
956         final String res1 = "res1";
957         final String res2 = "res2";
958         final String res3 = "res3";
959 
960         // choose low timeout so sometimes an owner times out
961         final ReadWriteUpgradeLockManager manager = new ReadWriteUpgradeLockManager(sLogger, 100);
962 
963         int concurrentThreads = 7;
964         int threads = CONCURRENT_TESTS * concurrentThreads;
965         
966         final RendezvousBarrier end = new RendezvousBarrier("end", threads + 1, TIMEOUT, sLogger);
967         
968         sLogger.logInfo("\n\nStarting "+threads+" threads\n\n");
969 
970         for (int i = 0; i < CONCURRENT_TESTS; i++) {
971 
972             final int cnt = i;
973             
974             System.out.print(".");
975 
976             Thread t1 = new Thread(new Runnable() {
977                 public void run() {
978                     try {
979                         manager.readLock(owner1, res1);
980                         manager.readLock(owner1, res2);
981                         manager.upgradeLock(owner1, res3);
982                         manager.writeLock(owner1, res3);
983                     } catch (LockException ie) {
984                         System.out.print("-");
985                     } finally {
986                         manager.releaseAll(owner1);
987                         end.call();
988                     }
989                 }
990             }, "Thread #1");
991 
992             Thread t2 = new Thread(new Runnable() {
993                 public void run() {
994                     try {
995                         manager.readLock(owner2, res1);
996                         manager.readLock(owner2, res2);
997                         manager.upgradeLock(owner2, res3);
998                         manager.writeLock(owner2, res3);
999                     } catch (LockException ie) {
1000                         System.out.print("-");
1001                     } finally {
1002                         manager.releaseAll(owner2);
1003                         end.call();
1004                     }
1005                 }
1006             }, "Thread #2");
1007 
1008             Thread t3 = new Thread(new Runnable() {
1009                 public void run() {
1010                     try {
1011                         manager.startGlobalTimeout(owner3, 10 + cnt);
1012                         manager.readLock(owner3, res1);
1013                         manager.readLock(owner3, res2);
1014                         manager.upgradeLock(owner3, res3);
1015                         manager.writeLock(owner3, res3);
1016                     } catch (LockException le) {
1017                         if (le.getCode() == LockException.CODE_TIMED_OUT) {
1018                             System.out.print("*");
1019                         } else {
1020                             System.out.print("-");
1021                         }
1022                     } finally {
1023                         manager.releaseAll(owner3);
1024                         end.call();
1025                     }
1026                 }
1027             }, "Thread #3");
1028 
1029             Thread t4 = new Thread(new Runnable() {
1030                 public void run() {
1031                     try {
1032                         manager.readLock(owner4, res1);
1033                         manager.readLock(owner4, res2);
1034                         manager.upgradeLock(owner4, res3);
1035                         manager.writeLock(owner4, res3);
1036                     } catch (LockException le) {
1037                         System.out.print("-");
1038                     } finally {
1039                         manager.releaseAll(owner4);
1040                         end.call();
1041                     }
1042                 }
1043             }, "Thread #4");
1044 
1045                 Thread deadlock1 = new Thread(new Runnable() {
1046                 public void run() {
1047                     try {
1048                         manager.writeLock(owner5, res2);
1049                         manager.writeLock(owner5, res1);
1050                     } catch (LockException le) {
1051                         assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
1052                         System.out.print("-");
1053                     } finally {
1054                         manager.releaseAll(owner5);
1055                         end.call();
1056                     }
1057                 }
1058             }, "Deadlock1 Thread");
1059 
1060             Thread deadlock2 = new Thread(new Runnable() {
1061                 public void run() {
1062                     try {
1063                         manager.readLock(owner6, res1);
1064                         manager.readLock(owner6, res2);
1065                     } catch (LockException le) {
1066                         assertEquals(le.getCode(), LockException.CODE_DEADLOCK_VICTIM);
1067                         System.out.print("-");
1068                     } finally {
1069                         manager.releaseAll(owner6);
1070                         end.call();
1071                     }
1072                 }
1073             }, "Deadlock1 Thread");
1074 
1075             Thread reader = new Thread(new Runnable() {
1076                 public void run() {
1077                     try {
1078                         manager.readLock("reader", res1);
1079                         manager.readLock("reader", res2);
1080                         manager.readLock("reader", res3);
1081                     } catch (LockException ie) {
1082                         System.out.print("-");
1083                     } finally {
1084                         manager.releaseAll("reader");
1085                         end.call();
1086                     }
1087                 }
1088             }, "Reader Thread");
1089 
1090 
1091             t4.start();
1092             t3.start();
1093             reader.start();
1094             t1.start();
1095             deadlock2.start();
1096             t2.start();
1097             deadlock1.start();
1098         }
1099         // wait until all threads have really terminated
1100         end.meet();
1101 
1102     }
1103 }