Coverage Report - org.apache.ojb.otm.lock.wait.TimeoutStrategy
 
Classes in this File Line Coverage Branch Coverage Complexity
TimeoutStrategy
N/A
N/A
5.667
 
 1  
 package org.apache.ojb.otm.lock.wait;
 2  
 
 3  
 /* Copyright 2003-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.util.HashMap;
 19  
 import org.apache.ojb.otm.core.Transaction;
 20  
 import org.apache.ojb.otm.lock.LockingException;
 21  
 import org.apache.ojb.otm.lock.ObjectLock;
 22  
 
 23  
 public class TimeoutStrategy implements LockWaitStrategy
 24  
 {
 25  
 
 26  
     /**
 27  
      * Maps tx to the lock that tx waits for.
 28  
      * Is used for deadlock detection
 29  
      */
 30  
     private static HashMap _waitsFor = new HashMap();
 31  
 
 32  
     private long _timeout;
 33  
 
 34  
     /**
 35  
      * @param timeout the number of milliseconds to wait before throwing exception
 36  
      */
 37  
     public TimeoutStrategy(long timeout)
 38  
     {
 39  
         if (timeout <= 0)
 40  
         {
 41  
             throw new IllegalArgumentException("Illegal timeout value: " + timeout);
 42  
         }
 43  
         _timeout = timeout;
 44  
     }
 45  
 
 46  
     /**
 47  
      * The default timeout is 30 seconds
 48  
      */
 49  
     public TimeoutStrategy() 
 50  
     {
 51  
         this(30000);
 52  
     }
 53  
 
 54  
     /**
 55  
     * @see org.apache.ojb.otm.lock.wait.LockWaitStrategy#waitForLock(ObjectLock, Transaction)
 56  
     */
 57  
     public void waitForLock(ObjectLock lock, Transaction tx)
 58  
         throws LockingException
 59  
     {
 60  
         Transaction writerTx;
 61  
         ObjectLock writerWaitsForLock;
 62  
 
 63  
         // test for deadlock
 64  
         writerTx = lock.getWriter();
 65  
         while (writerTx != null)
 66  
         {
 67  
             writerWaitsForLock = (ObjectLock) _waitsFor.get(writerTx);
 68  
             if (writerWaitsForLock == null)
 69  
             {
 70  
                 break;
 71  
             }
 72  
             writerTx = writerWaitsForLock.getWriter();
 73  
             if (writerTx == null)
 74  
             {
 75  
                 break;
 76  
             }
 77  
             if (writerTx == tx)
 78  
             {
 79  
                 StringBuffer sb = new StringBuffer();
 80  
 
 81  
                 // deadlock detected.
 82  
                 // Now we traverse the cycle once more to provide more info
 83  
                 writerTx = lock.getWriter();
 84  
                 sb.append(lock.getTargetIdentity());
 85  
                 while (writerTx != tx)
 86  
                 {
 87  
                     writerWaitsForLock = (ObjectLock) _waitsFor.get(writerTx);
 88  
                     sb.append(" -> ");
 89  
                     sb.append(writerWaitsForLock.getTargetIdentity());
 90  
                     writerTx = writerWaitsForLock.getWriter();
 91  
                 }
 92  
                 throw new DeadlockException(sb.toString());
 93  
             }
 94  
         }
 95  
 
 96  
         // No deadlock detected, then wait the given timeout
 97  
         _waitsFor.put(tx, lock);
 98  
         try
 99  
         {
 100  
             long now = System.currentTimeMillis();
 101  
             long deadline = System.currentTimeMillis() + _timeout;
 102  
 
 103  
             do
 104  
             {
 105  
                 if (lock.getWriter() == null)
 106  
                 {
 107  
                     return;
 108  
                 }
 109  
 
 110  
                 try
 111  
                 {
 112  
                     long toSleep = Math.min(deadline - now, 1000);
 113  
                     Thread.sleep(toSleep);
 114  
                     now += toSleep;
 115  
                 } catch (InterruptedException ex) {
 116  
                     now = System.currentTimeMillis();
 117  
                 }
 118  
             }
 119  
             while (now < deadline);
 120  
 
 121  
             writerTx = lock.getWriter();
 122  
 
 123  
             if (writerTx != null)
 124  
             {
 125  
                 throw new ConcurrentModificationException(
 126  
                         "Object [id: " + lock.getTargetIdentity()
 127  
                         + "] locked by Transaction " + writerTx);
 128  
             }
 129  
         }
 130  
         finally
 131  
         {
 132  
             _waitsFor.remove(tx);
 133  
         }
 134  
     }
 135  
 }