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);
  +        }
  +    }
   }