ozeigermann    2005/01/08 10:56:03

  Modified:    transaction/src/test/org/apache/commons/transaction/locking
                        GenericLockTest.java
  Log:
  Added tests for indirect deadlocks and mean chaos test with many threads
  
  Revision  Changes    Path
  1.11      +317 -6    
jakarta-commons/transaction/src/test/org/apache/commons/transaction/locking/GenericLockTest.java
  
  Index: GenericLockTest.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/transaction/src/test/org/apache/commons/transaction/locking/GenericLockTest.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- GenericLockTest.java      7 Jan 2005 12:41:58 -0000       1.10
  +++ GenericLockTest.java      8 Jan 2005 18:56:03 -0000       1.11
  @@ -224,13 +224,160 @@
                   }
               }
   
  -            assertEquals(1, deadlockCnt);
  +            // XXX in special scenarios the current implementation might 
cause both
  +            // owners to be deadlock victims
  +            if (deadlockCnt != 1) {
  +                sLogger.logWarning("More than one thread was deadlock 
victim!");
  +            }
  +            assertTrue(deadlockCnt >= 1);
               deadlockCnt = 0;
           }
       }
   
       /*
        * 
  +     * Test detection of an indirect deadlock:
  +     * 
  +     *                  Owner           Owner           Owner
  +     * Step             #1              #2              #3
  +     * 1                read res1 (ok)
  +     * 2                                read res2 (ok)
  +     * 3                                                read res3 (ok)
  +     * 4                                                write res2 (blocked 
because of #2)
  +     * 5                                write res1
  +     *                                  (blocked 
  +     *                                  because of #1)
  +     * 6                write res3
  +     *                  (blocked 
  +     *                   because #3)
  +     * 
  +     * - Thread#1 waits for Thread#3 on res3
  +     * - Thread#2 waits for Thread#1 on res1
  +     * - Thread#3 waits for Thread#2 on res2
  +     *
  +     * This needs recursion of the deadlock detection algorithm
  +     *  
  +     */
  +    public void testIndirectDeadlock() throws Throwable {
  +
  +        sLogger.logInfo("\n\nChecking detection of indirect deadlock \n\n");
  +
  +        final String owner1 = "owner1";
  +        final String owner2 = "owner2";
  +        final String owner3 = "owner3";
  +
  +        final String res1 = "res1";
  +        final String res2 = "res2";
  +        final String res3 = "res3";
  +
  +        // a read / write lock
  +        final ReadWriteLockManager manager = new 
ReadWriteLockManager(sLogger,
  +                TIMEOUT);
  +
  +        final RendezvousBarrier restart = new RendezvousBarrier("restart", 
3, TIMEOUT, sLogger);
  +
  +        final TurnBarrier cb = new TurnBarrier("cb1", TIMEOUT, sLogger, 1);
  +
  +        for (int i = 0; i < CONCURRENT_TESTS; i++) {
  +            
  +            System.out.print(".");
  +
  +            Thread t1 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        cb.waitForTurn(2);
  +                        manager.readLock(owner2, res2);
  +                        cb.signalTurn(3);
  +                        cb.waitForTurn(5);
  +                        synchronized (manager.getLock(res1)) {
  +                            cb.signalTurn(6);
  +                            manager.writeLock(owner2, res1);
  +                        }
  +                    } catch (LockException le) {
  +                        assertEquals(le.getCode(), 
LockException.CODE_DEADLOCK_VICTIM);
  +                        deadlockCnt++;
  +                    } catch (InterruptedException ie) {
  +                    } finally {
  +                        manager.releaseAll(owner2);
  +                        synchronized (restart) {
  +                            try {
  +                                synchronized (restart) {
  +                                    restart.meet();
  +                                    restart.reset();
  +                                }
  +                                } catch (InterruptedException ie) {}
  +                        }
  +                    }
  +                }
  +            }, "Thread #1");
  +
  +            t1.start();
  +
  +            Thread t2 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        cb.waitForTurn(3);
  +                        manager.readLock(owner3, res3);
  +                        synchronized (manager.getLock(res2)) {
  +                            cb.signalTurn(5);
  +                            manager.writeLock(owner3, res2);
  +                        }
  +                    } catch (LockException le) {
  +                        assertEquals(le.getCode(), 
LockException.CODE_DEADLOCK_VICTIM);
  +                        deadlockCnt++;
  +                    } catch (InterruptedException ie) {
  +                    } finally {
  +                        manager.releaseAll(owner3);
  +                        synchronized (restart) {
  +                            try {
  +                                synchronized (restart) {
  +                                    restart.meet();
  +                                    restart.reset();
  +                                }
  +                                } catch (InterruptedException ie) {}
  +                        }
  +                    }
  +                }
  +            }, "Thread #2");
  +
  +            t2.start();
  +
  +            try {
  +                cb.waitForTurn(1);
  +                manager.readLock(owner1, res1);
  +                cb.signalTurn(2);
  +                cb.waitForTurn(6);
  +                manager.writeLock(owner1, res3);
  +            } catch (LockException le) {
  +                assertEquals(le.getCode(), 
LockException.CODE_DEADLOCK_VICTIM);
  +                deadlockCnt++;
  +            } catch (InterruptedException ie) {
  +            } finally {
  +                manager.releaseAll(owner1);
  +                synchronized (restart) {
  +                    try {
  +                        synchronized (restart) {
  +                            restart.meet();
  +                            restart.reset();
  +                        }
  +                    } catch (InterruptedException ie) {
  +                    }
  +                }
  +            }
  +
  +            // XXX in special scenarios the current implementation might 
cause more than one
  +            // owner to be a deadlock victim
  +            if (deadlockCnt != 1) {
  +                sLogger.logWarning("More than one thread was deadlock 
victim!");
  +            }
  +            assertTrue(deadlockCnt >= 1);
  +            deadlockCnt = 0;
  +            cb.reset();
  +        }
  +    }
  +
  +    /*
  +     * 
        * Test shows the following
        * - upgrade works with read locks no matter if they are acquired before 
or later (1-4)
        * - write is blocked by read (5)
  @@ -500,8 +647,8 @@
               t1.start();
   
               cb.waitForTurn(1);
  +            manager.startGlobalTimeout(owner1, 500);
               manager.lock(owner1, res1, 1, true);
  -            manager.setGlobalTimeout(owner1, 500);
               cb.signalTurn(2);
               cb.waitForTurn(3);
               boolean failed = false;
  @@ -519,6 +666,7 @@
                   failed = true;
               }
               assertFalse(failed);
  +            manager.releaseAll(owner1);
               synchronized (restart) {
                   restart.meet();
                   restart.reset();
  @@ -686,6 +834,169 @@
               } catch (InterruptedException ie) {
               }
           }
  +
  +    }
  +
  +    public void testChaos() throws Throwable {
  +
  +        sLogger.logInfo("\n\nChaos testing locks for internal deadlocks 
resp. concurrent mods\n\n");
  +
  +        final String owner1 = "owner1";
  +        final String owner2 = "owner2";
  +        final String owner3 = "owner3";
  +        final String owner4 = "owner4";
  +        final String owner5 = "owner5";
  +        final String owner6 = "owner6";
  +        final String owner7 = "owner7";
  +        final String owner8 = "owner8";
  +        final String owner9 = "owner9";
  +        final String owner10 = "owner10";
  +
  +        final String res1 = "res1";
  +        final String res2 = "res2";
  +        final String res3 = "res3";
  +
  +        // choose low timeout so sometimes an owner times out
  +        final ReadWriteUpgradeLockManager manager = new 
ReadWriteUpgradeLockManager(sLogger, 100);
  +
  +        int concurrentThreads = 7;
  +        int threads = CONCURRENT_TESTS * concurrentThreads;
  +        
  +        final RendezvousBarrier end = new RendezvousBarrier("end", threads + 
1, TIMEOUT, sLogger);
  +        
  +        sLogger.logInfo("\n\nStarting "+threads+" threads\n\n");
  +
  +        for (int i = 0; i < CONCURRENT_TESTS; i++) {
  +
  +            final int cnt = i;
  +            
  +            System.out.print(".");
  +
  +            Thread t1 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.readLock(owner1, res1);
  +                        manager.readLock(owner1, res2);
  +                        manager.upgradeLock(owner1, res3);
  +                        manager.writeLock(owner1, res3);
  +                    } catch (LockException ie) {
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll(owner1);
  +                        end.call();
  +                    }
  +                }
  +            }, "Thread #1");
  +
  +            Thread t2 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.readLock(owner2, res1);
  +                        manager.readLock(owner2, res2);
  +                        manager.upgradeLock(owner2, res3);
  +                        manager.writeLock(owner2, res3);
  +                    } catch (LockException ie) {
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll(owner2);
  +                        end.call();
  +                    }
  +                }
  +            }, "Thread #2");
  +
  +            Thread t3 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.startGlobalTimeout(owner3, 10 + cnt);
  +                        manager.readLock(owner3, res1);
  +                        manager.readLock(owner3, res2);
  +                        manager.upgradeLock(owner3, res3);
  +                        manager.writeLock(owner3, res3);
  +                    } catch (LockException le) {
  +                        if (le.getCode() == LockException.CODE_TIMED_OUT) {
  +                            System.out.print("*");
  +                        } else {
  +                            System.out.print("-");
  +                        }
  +                    } finally {
  +                        manager.releaseAll(owner3);
  +                        end.call();
  +                    }
  +                }
  +            }, "Thread #3");
  +
  +            Thread t4 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.readLock(owner4, res1);
  +                        manager.readLock(owner4, res2);
  +                        manager.upgradeLock(owner4, res3);
  +                        manager.writeLock(owner4, res3);
  +                    } catch (LockException le) {
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll(owner4);
  +                        end.call();
  +                    }
  +                }
  +            }, "Thread #4");
  +
  +                Thread deadlock1 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.writeLock(owner5, res2);
  +                        manager.writeLock(owner5, res1);
  +                    } catch (LockException le) {
  +                        assertEquals(le.getCode(), 
LockException.CODE_DEADLOCK_VICTIM);
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll(owner5);
  +                        end.call();
  +                    }
  +                }
  +            }, "Deadlock1 Thread");
  +
  +            Thread deadlock2 = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.readLock(owner6, res1);
  +                        manager.readLock(owner6, res2);
  +                    } catch (LockException le) {
  +                        assertEquals(le.getCode(), 
LockException.CODE_DEADLOCK_VICTIM);
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll(owner6);
  +                        end.call();
  +                    }
  +                }
  +            }, "Deadlock1 Thread");
  +
  +            Thread reader = new Thread(new Runnable() {
  +                public void run() {
  +                    try {
  +                        manager.readLock("reader", res1);
  +                        manager.readLock("reader", res2);
  +                        manager.readLock("reader", res3);
  +                    } catch (LockException ie) {
  +                        System.out.print("-");
  +                    } finally {
  +                        manager.releaseAll("reader");
  +                        end.call();
  +                    }
  +                }
  +            }, "Reader Thread");
  +
  +
  +            t4.start();
  +            t3.start();
  +            reader.start();
  +            t1.start();
  +            deadlock2.start();
  +            t2.start();
  +            deadlock1.start();
  +        }
  +        // wait until all threads have really terminated
  +        end.meet();
   
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to