User: patriot1burke
  Date: 02/01/12 12:21:07

  Modified:    src/main/org/jboss/ejb/plugins/lock
                        QueuedPessimisticEJBLock.java BeanLockSupport.java
  Log:
  Added deadlock detection.  If application deadlock is detected and RuntimeException 
is thrown so
  that the thread does not hang until TX timeout.  It will be extremely helpful in 
debugging.
  
  Revision  Changes    Path
  1.8       +81 -54    
jboss/src/main/org/jboss/ejb/plugins/lock/QueuedPessimisticEJBLock.java
  
  Index: QueuedPessimisticEJBLock.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/lock/QueuedPessimisticEJBLock.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- QueuedPessimisticEJBLock.java     2001/12/19 06:04:48     1.7
  +++ QueuedPessimisticEJBLock.java     2002/01/12 20:21:07     1.8
  @@ -36,7 +36,7 @@
    * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
    * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
    *
  - * @version $Revision: 1.7 $
  + * @version $Revision: 1.8 $
    *
    * <p><b>Revisions:</b><br>
    * <p><b>2001/08/03: billb</b>
  @@ -238,59 +238,85 @@
      protected boolean waitForTx(Transaction miTx, boolean trace) throws Exception
      {
         boolean wasScheduled = false;
  -
  -      // Do we have a running transaction with the context?
  -      // We loop here until either until success or until transaction timeout
  -      // If we get out of the loop successfully, we can successfully
  -      // set the transaction on this puppy.
  -      while (this.tx != null &&
  -             // And are we trying to enter with another transaction?
  -             !this.tx.equals(miTx))
  -      {
  -         wasScheduled = true;
  -         // That's no good, only one transaction per context
  -         // Let's put the thread to sleep the transaction demarcation will wake 
them up
  -         if( trace ) log.trace("Transactional contention on context"+id);
  -         
  -         TxLock txLock = getTxLock(miTx);
  -         
  -         if( trace ) log.trace("Begin wait on Tx="+this.tx);
  -         
  -         // And lock the threads on the lock corresponding to the Tx in MI
  -         synchronized(txLock)
  -         {
  -            releaseSync(); 
  -            try
  -            {
  -               txLock.wait(txTimeout);
  -            } catch (InterruptedException ignored) {}
  -         } // end synchronized(txLock)
  -         
  -         this.sync();
  -         
  -         if( trace ) log.trace("End wait on TxLock="+this.tx);
  -         if (isTxExpired(miTx))
  -         {
  -            log.error(Thread.currentThread() + "Saw rolled back tx="+miTx+" waiting 
for txLock"
  -                      // +" On method: " + mi.getMethod().getName()
  -                      // +" txWaitQueue size: " + txWaitQueue.size()
  -                      );
  -            if (txLock.isQueued)
  -            {
  -               // Remove the TxLock from the queue because this thread is exiting.
  -               // Don't worry about notifying other threads that share the same 
transaction.
  -               // They will timeout and throw the below RuntimeException
  -               txLocks.remove(txLock);
  -               txWaitQueue.remove(txLock);
  -            }
  -            else if (this.tx != null && tx.equals(miTx))
  -            {
  -               // We're not qu
  -               nextTransaction();
  -            }
  -            throw new RuntimeException("Transaction marked for rollback, possibly a 
timeout");
  -         }
  -      } // end while(tx!=miTx)
  +      boolean addedWaiting = false;
  +      try
  +      {
  +      // Do we have a running transaction with the context?
  +      // We loop here until either until success or until transaction timeout
  +      // If we get out of the loop successfully, we can successfully
  +      // set the transaction on this puppy.
  +      while (this.tx != null &&
  +             // And are we trying to enter with another transaction?
  +             !this.tx.equals(miTx))
  +      {
  +         // For deadlock detection.
  +         // miTx is waiting for this.tx to finish so put it
  +         // in the waiting table and do deadlock detection.
  +         if (miTx != null && !addedWaiting)
  +         {
  +            synchronized (waiting)
  +            {
  +               waiting.put(miTx, this.tx);
  +               addedWaiting = true;
  +            }
  +            deadlockDetection(miTx);
  +         }
  +         wasScheduled = true;
  +         // That's no good, only one transaction per context
  +         // Let's put the thread to sleep the transaction demarcation will wake 
them up
  +         if( trace ) log.trace("Transactional contention on context"+id);
  +         
  +         TxLock txLock = getTxLock(miTx);
  +         
  +         if( trace ) log.trace("Begin wait on Tx="+this.tx);
  +         
  +         // And lock the threads on the lock corresponding to the Tx in MI
  +         synchronized(txLock)
  +         {
  +            releaseSync(); 
  +            try
  +            {
  +               txLock.wait(txTimeout);
  +            } catch (InterruptedException ignored) {}
  +         } // end synchronized(txLock)
  +         
  +         this.sync();
  +         
  +         if( trace ) log.trace("End wait on TxLock="+this.tx);
  +         if (isTxExpired(miTx))
  +         {
  +            log.error(Thread.currentThread() + "Saw rolled back tx="+miTx+" waiting 
for txLock"
  +                      // +" On method: " + mi.getMethod().getName()
  +                      // +" txWaitQueue size: " + txWaitQueue.size()
  +                      );
  +            if (txLock.isQueued)
  +            {
  +               // Remove the TxLock from the queue because this thread is exiting.
  +               // Don't worry about notifying other threads that share the same 
transaction.
  +               // They will timeout and throw the below RuntimeException
  +               txLocks.remove(txLock);
  +               txWaitQueue.remove(txLock);
  +            }
  +            else if (this.tx != null && tx.equals(miTx))
  +            {
  +               // We're not qu
  +               nextTransaction();
  +            }
  +            throw new RuntimeException("Transaction marked for rollback, possibly a 
timeout");
  +         }
  +      } // end while(tx!=miTx)
  +      }
  +      finally
  +      {
  +      // miTx is now long waiting for a tx to finish so remove it from the waiting 
table.
  +      if (miTx != null && addedWaiting)
  +      {
  +         synchronized (waiting)
  +         {
  +            waiting.remove(miTx);
  +         }
  +      }
  +      }
   
         // If we get here, this means that we have the txlock
         this.tx = miTx;
  @@ -444,5 +470,6 @@
            System.out.println(Thread.currentThread() + " removing lock!");
         */
      }
  +
   }
   
  
  
  
  1.10      +31 -1     jboss/src/main/org/jboss/ejb/plugins/lock/BeanLockSupport.java
  
  Index: BeanLockSupport.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/lock/BeanLockSupport.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- BeanLockSupport.java      2001/12/19 06:04:48     1.9
  +++ BeanLockSupport.java      2002/01/12 20:21:07     1.10
  @@ -15,6 +15,8 @@
   import org.jboss.ejb.BeanLock;
   import org.jboss.invocation.Invocation;
   import org.jboss.logging.Logger;
  +import java.util.HashMap;
  +import java.util.HashSet;
   
   
   /**
  @@ -22,7 +24,7 @@
    *
    * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
    * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
  - * @version $Revision: 1.9 $
  + * @version $Revision: 1.10 $
    *
    * <p><b>Revisions:</b><br>
    *  <p><b>2001/07/29: marcf</b>
  @@ -164,5 +166,33 @@
         }
     
         return false;
  +   }
  +
  +   // This following is for deadlock detection
  +   protected static HashMap waiting = new HashMap();
  +
  +   public void deadlockDetection(Transaction miTx)
  +   {
  +      HashSet set = new HashSet();
  +      set.add(miTx);
  +      
  +      Object checkTx = this.tx;
  +      synchronized(waiting)
  +      {
  +      while (checkTx != null)
  +      {
  +         Object waitingFor = waiting.get(checkTx);
  +         if (waitingFor != null)
  +         {
  +            if (set.contains(waitingFor))
  +            {
  +               log.error("Application deadlock detected: " + miTx + " has deadlock 
conditions");
  +               throw new RuntimeException("application deadlock detected");
  +            }
  +            set.add(waitingFor);
  +         }
  +         checkTx = waitingFor;
  +      }
  +      }
      }
   }
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to