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