Author: ozeigermann
Date: Fri Aug 17 09:01:57 2007
New Revision: 567075

URL: http://svn.apache.org/viewvc?view=rev&rev=567075
Log:
Made lock manager more configurable and verbose

Modified:
    
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
    
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
    
commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/memory/PessimisticTxMapTest.java

Modified: 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
URL: 
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java?view=diff&rev=567075&r1=567074&r2=567075
==============================================================================
--- 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
 (original)
+++ 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockException.java
 Fri Aug 17 09:01:57 2007
@@ -67,6 +67,11 @@
         this.resourceId = resourceId;
     }
 
+    public LockException(String message, Code code) {
+        super(message);
+        this.code = code;
+    }
+
     public LockException(String message) {
         super(message);
     }

Modified: 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
URL: 
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java?view=diff&rev=567075&r1=567074&r2=567075
==============================================================================
--- 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
 (original)
+++ 
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
 Fri Aug 17 09:01:57 2007
@@ -29,6 +29,9 @@
 public class RWLockManager<K, M> extends AbstractLockManager<K, M> implements 
LockManager<K, M> {
 
     protected ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock> locks = new 
ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock>();
+    
+    private long absolutePrewaitTime = -1;
+    private long prewaitTimeDivisor = 10;
 
     protected ResourceRWLock create(String name) {
         return new ResourceRWLock(name);
@@ -57,6 +60,9 @@
         if (time == 0) {
             locked = lock.tryLock();
         } else {
+            // we need to have this lock request registered as an additional
+            // waiter as it will not be among the queued threads at the time we
+            // do the deadlock check
             rwlock.registerWaiter();
             try {
                 locked = 
doTrickyYetEfficientLockOnlyIfThisCanNotCauseADeadlock(lock, unit
@@ -102,17 +108,14 @@
 
             long startTime = System.currentTimeMillis();
 
-            // TODO this heuristic divisor really should be configurable
-            long preWaitTime = timeMsecs / 10;
+            long preWaitTime = getPrewaitTime(timeMsecs);
             locked = lock.tryLock(preWaitTime, TimeUnit.MILLISECONDS);
             if (locked)
                 return true;
 
             // (II) deadlock detect
             cancelAllTimedOut();
-            if (wouldDeadlock(Thread.currentThread(), new HashSet<Thread>())) {
-                throw new LockException(LockException.Code.WOULD_DEADLOCK);
-            }
+            detectDeadlock(Thread.currentThread(), new HashSet<Thread>());
 
             // (III) real wait
             long now = System.currentTimeMillis();
@@ -128,7 +131,12 @@
 
     }
 
-    protected boolean wouldDeadlock(Thread thread, Set<Thread> path) {
+    long getPrewaitTime(long timeMsecs) {
+        if (absolutePrewaitTime != -1) return absolutePrewaitTime;
+        return timeMsecs / prewaitTimeDivisor;
+    }
+
+    protected void detectDeadlock(Thread thread, Set<Thread> path) {
         path.add(thread);
         // these are our locks
         // Note: No need to make a copy as we can be sure to iterate on our
@@ -146,16 +154,23 @@
                 for (Thread conflictThread : conflicts) {
                     // this means, we have found a cycle in the wait graph
                     if (path.contains(conflictThread)) {
-                        return true;
-                    } else if (wouldDeadlock(conflictThread, path)) {
-                        return true;
+                        String message = "Cycle found involving " + 
formatPath(path);
+                        throw new LockException(message, 
LockException.Code.WOULD_DEADLOCK);
+                    } else {
+                        detectDeadlock(conflictThread, path);
                     }
                 }
             }
         }
-
         path.remove(thread);
-        return false;
+    }
+
+    private String formatPath(Set<Thread> path) {
+        StringBuffer buf = new StringBuffer();
+        for (Thread thread : path) {
+            buf.append(thread.getName()).append("->");
+        }
+        return buf.toString();
     }
 
     protected void cancelAllTimedOut() {
@@ -173,6 +188,22 @@
             }
 
         }
+    }
+
+    public long getAbsolutePrewaitTime() {
+        return absolutePrewaitTime;
+    }
+
+    public void setAbsolutePrewaitTime(long absolutePrewaitTime) {
+        this.absolutePrewaitTime = absolutePrewaitTime;
+    }
+
+    public long getPrewaitTimeDivisor() {
+        return prewaitTimeDivisor;
+    }
+
+    public void setPrewaitTimeDivisor(long prewaitTimeDivisor) {
+        this.prewaitTimeDivisor = prewaitTimeDivisor;
     }
 
 }

Modified: 
commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/memory/PessimisticTxMapTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/memory/PessimisticTxMapTest.java?view=diff&rev=567075&r1=567074&r2=567075
==============================================================================
--- 
commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/memory/PessimisticTxMapTest.java
 (original)
+++ 
commons/proper/transaction/branches/TRANSACTION_2/src/test/org/apache/commons/transaction/memory/PessimisticTxMapTest.java
 Fri Aug 17 09:01:57 2007
@@ -27,6 +27,7 @@
 import org.apache.commons.logging.LogFactory;
 
 import org.apache.commons.transaction.locking.LockException;
+import org.apache.commons.transaction.locking.RWLockManager;
 import org.apache.commons.transaction.util.RendezvousBarrier;
 
 /**
@@ -98,8 +99,11 @@
     public void testConflict() {
         log.info("Checking concurrent conflict resolvation features");
 
+        final RWLockManager<Object, Object> lm = new RWLockManager<Object, 
Object>();
+        // adds more concurrency and makes test run faster
+        lm.setAbsolutePrewaitTime(0);
         final PessimisticTxMap<String, String> txMap1 = new 
PessimisticTxMap<String, String>(
-                "txMap1");
+                "txMap1", lm);
         final Map map1 = txMap1.getWrappedMap();
 
         final RendezvousBarrier restart = new RendezvousBarrier("restart", 
TIMEOUT);
@@ -108,14 +112,14 @@
         int runs = 25;
 
         for (int i = 0; i < runs; i++) {
-            System.out.print(".");
+            System.out.println(i);
 
             final RendezvousBarrier deadlockBarrier1 = new 
RendezvousBarrier("deadlock" + i,
                     TIMEOUT);
 
             Thread thread1 = new Thread(new Runnable() {
                 public void run() {
-                    txMap1.startTransaction(5, TimeUnit.SECONDS);
+                    txMap1.startTransaction(5, TimeUnit.MINUTES);
                     try {
                         // first both threads get a lock, this one on key2
                         txMap1.put("key2", "value2");
@@ -147,7 +151,7 @@
 
             thread1.start();
 
-            txMap1.startTransaction(5, TimeUnit.SECONDS);
+            txMap1.startTransaction(5, TimeUnit.MINUTES);
             try {
                 // first both threads get a lock, this one on key1
                 txMap1.get("key1");
@@ -187,6 +191,14 @@
             }
             assertTrue(deadlockCnt >= 1);
             deadlockCnt = 0;
+
+            try {
+                thread1.join();
+            } catch (InterruptedException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+
         }
         System.out.println();
         System.out.println("Of the " + runs + " there were " + conflictingRuns


Reply via email to