You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ol...@apache.org on 2003/05/18 20:14:24 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/otm/lock/wait LockWaitStrategy.java NoWaitStrategy.java TimeoutStrategy.java
olegnitz 2003/05/18 11:14:24
Modified: src/java/org/apache/ojb/otm/lock ObjectLock.java
src/java/org/apache/ojb/otm/lock/wait LockWaitStrategy.java
NoWaitStrategy.java TimeoutStrategy.java
Log:
Deadlock detection, bugfixes
Revision Changes Path
1.6 +7 -5 db-ojb/src/java/org/apache/ojb/otm/lock/ObjectLock.java
Index: ObjectLock.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/lock/ObjectLock.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ObjectLock.java 18 May 2003 15:10:49 -0000 1.5
+++ ObjectLock.java 18 May 2003 18:14:24 -0000 1.6
@@ -124,7 +124,8 @@
public void readLock(Transaction tx)
{
- if (!isReader(tx)) {
+ if (!isReader(tx))
+ {
new LockEntry(tx);
}
}
@@ -147,6 +148,7 @@
public void releaseLock(Transaction tx)
{
LockEntry lock = (LockEntry)_readers.get(tx);
+
if (lock != null)
{
lock.release();
@@ -228,13 +230,13 @@
* the lock is released by the writer.
*
*/
- public void writeLock()
- throws LockingException
+ public void writeLock() throws LockingException
{
- while (true) {
+ while (true)
+ {
if (_writer != null && _writer._tx != _tx)
{
- waitForTx(_writer.getTx());
+ waitForTx(_tx);
}
synchronized (ObjectLock.this)
1.2 +10 -5 db-ojb/src/java/org/apache/ojb/otm/lock/wait/LockWaitStrategy.java
Index: LockWaitStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/lock/wait/LockWaitStrategy.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LockWaitStrategy.java 1 Feb 2003 18:39:57 -0000 1.1
+++ LockWaitStrategy.java 18 May 2003 18:14:24 -0000 1.2
@@ -60,14 +60,19 @@
/**
*
- * LockWaitStrategy is responsible for waiting for a particular lock to be released. Typically, the
+ * LockWaitStrategy is responsible for waiting for a particular lock to be released. Typically, the
* LockWaitStrategy implements deadlock prevention/detection/recovery mechanisms.
- *
+ *
* @author <a href="mailto:rraghuram@hotmail.com">Raghu Rajah</a>
- *
+ *
*/
public interface LockWaitStrategy
{
- public void waitForLock (ObjectLock lock, Transaction tx)
- throws LockingException;
+
+ /**
+ * @param lock The lock that the tx is waiting for
+ * @param tx The waiting tx
+ */
+ public void waitForLock(ObjectLock lock, Transaction tx)
+ throws LockingException;
}
1.3 +2 -1 db-ojb/src/java/org/apache/ojb/otm/lock/wait/NoWaitStrategy.java
Index: NoWaitStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/lock/wait/NoWaitStrategy.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- NoWaitStrategy.java 18 May 2003 15:10:49 -0000 1.2
+++ NoWaitStrategy.java 18 May 2003 18:14:24 -0000 1.3
@@ -21,7 +21,8 @@
throws LockingException
{
throw new ConcurrentModificationException(
- "Object [id: " + lock.getTargetIdentity().toString() + "] locked by Transaction " + tx);
+ "Object [id: " + lock.getTargetIdentity()
+ + "] locked by Transaction " + lock.getWriter());
}
}
1.2 +73 -18 db-ojb/src/java/org/apache/ojb/otm/lock/wait/TimeoutStrategy.java
Index: TimeoutStrategy.java
===================================================================
RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/otm/lock/wait/TimeoutStrategy.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TimeoutStrategy.java 18 May 2003 15:10:49 -0000 1.1
+++ TimeoutStrategy.java 18 May 2003 18:14:24 -0000 1.2
@@ -1,12 +1,13 @@
package org.apache.ojb.otm.lock.wait;
+import java.util.HashMap;
import org.apache.ojb.otm.core.Transaction;
import org.apache.ojb.otm.lock.LockingException;
import org.apache.ojb.otm.lock.ObjectLock;
/**
*
- * Just a timeout
+ * Deadlock detection, then timeout
*
* @author <a href="mailto:olegnitz@apache.org">Oleg Nitz</a>
*
@@ -14,12 +15,19 @@
public class TimeoutStrategy implements LockWaitStrategy
{
+ /**
+ * Maps tx to the lock that tx waits for.
+ * Is used for deadlock detection
+ */
+ private static HashMap _waitsFor = new HashMap();
+
private long _timeout;
/**
* @param timeout the number of milliseconds to wait before throwing exception
*/
- public TimeoutStrategy(long timeout) {
+ public TimeoutStrategy(long timeout)
+ {
if (timeout <= 0)
{
throw new IllegalArgumentException("Illegal timeout value: " + timeout);
@@ -30,7 +38,8 @@
/**
* The default timeout is 30 seconds
*/
- public TimeoutStrategy() {
+ public TimeoutStrategy()
+ {
this(30000);
}
@@ -40,28 +49,74 @@
public void waitForLock(ObjectLock lock, Transaction tx)
throws LockingException
{
- long now = System.currentTimeMillis();
- long deadline = System.currentTimeMillis() + _timeout;
+ Transaction writerTx;
+ ObjectLock writerWaitsForLock;
- do
+ // test for deadlock
+ writerTx = lock.getWriter();
+ while (writerTx != null)
{
- try
+ writerWaitsForLock = (ObjectLock) _waitsFor.get(writerTx);
+ if (writerWaitsForLock == null)
{
- long toSleep = Math.min(deadline - now, 1000);
- Thread.sleep(toSleep);
- now += toSleep;
- } catch (InterruptedException ex) {
- now = System.currentTimeMillis();
+ break;
}
- if (lock.getWriter() == null)
+ writerTx = writerWaitsForLock.getWriter();
+ if (writerTx == null)
{
- return;
+ break;
+ }
+ if (writerTx == tx)
+ {
+ StringBuffer sb = new StringBuffer();
+
+ // deadlock detected.
+ // Now we traverse the cycle once more to provide more info
+ writerTx = lock.getWriter();
+ sb.append(lock.getTargetIdentity());
+ while (writerTx != tx)
+ {
+ writerWaitsForLock = (ObjectLock) _waitsFor.get(writerTx);
+ sb.append(" -> ");
+ sb.append(writerWaitsForLock.getTargetIdentity());
+ writerTx = writerWaitsForLock.getWriter();
+ }
+ throw new DeadlockException(sb.toString());
}
}
- while (now < deadline);
- throw new ConcurrentModificationException(
- "Object [id: " + lock.getTargetIdentity().toString() + "] locked by Transaction " + tx);
- }
+ // No deadlock detected, then wait the given timeout
+ _waitsFor.put(tx, lock);
+ try
+ {
+ long now = System.currentTimeMillis();
+ long deadline = System.currentTimeMillis() + _timeout;
+
+ do
+ {
+ if (lock.getWriter() == null)
+ {
+ return;
+ }
+
+ try
+ {
+ long toSleep = Math.min(deadline - now, 1000);
+ Thread.sleep(toSleep);
+ now += toSleep;
+ } catch (InterruptedException ex) {
+ now = System.currentTimeMillis();
+ }
+ }
+ while (now < deadline);
+ throw new ConcurrentModificationException(
+ "Object [id: " + lock.getTargetIdentity()
+ + "] locked by Transaction " + lock.getWriter());
+ }
+ finally
+ {
+ _waitsFor.remove(tx);
+ }
+ }
}