User: patriot1burke
  Date: 02/02/13 14:46:57

  Modified:    src/main/org/jboss/ejb/plugins/lock Tag: Branch_2_4
                        BeanLockSupport.java QueuedPessimisticEJBLock.java
  Added:       src/main/org/jboss/ejb/plugins/lock Tag: Branch_2_4
                        ApplicationDeadlockException.java
  Log:
  Added application deadlock detection.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.4.4.4   +47 -19    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.4.4.3
  retrieving revision 1.4.4.4
  diff -u -r1.4.4.3 -r1.4.4.4
  --- BeanLockSupport.java      20 Nov 2001 09:42:52 -0000      1.4.4.3
  +++ BeanLockSupport.java      13 Feb 2002 22:46:57 -0000      1.4.4.4
  @@ -6,10 +6,7 @@
    */
   
   package org.jboss.ejb.plugins.lock;
  -
  -import java.util.LinkedList;
  -import java.util.HashMap;
  -import java.util.Collections;
  + 
   import java.lang.reflect.Method;
   
   import javax.transaction.Transaction;
  @@ -18,13 +15,16 @@
   import org.jboss.ejb.BeanLock;
   import org.jboss.ejb.MethodInvocation;
   import org.jboss.logging.Logger;
  +import java.util.HashMap;
  +import java.util.HashSet;
  +
   
   /**
    * Support for the BeanLock
    *
    * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
    * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
  - * @version $Revision: 1.4.4.3 $
  + * @version $Revision: 1.4.4.4 $
    *
    * <p><b>Revisions:</b><br>
    *  <p><b>2001/07/29: marcf</b>
  @@ -35,9 +35,6 @@
   public abstract class BeanLockSupport
      implements BeanLock
   {
  -   /** Use a JBoss custom log4j category for trace level logging */
  -   static Logger log = Logger.getLogger(BeanLock.class);
  -
      /**
       * Number of threads invoking methods on this bean
       * (1 normally >1 if reentrant)
  @@ -56,6 +53,9 @@
      /** Are reentrant calls allowed? */
      protected boolean reentrant;
    
  +   /** Logger instance */
  +   static Logger log = Logger.getLogger(BeanLock.class);
  + 
      protected Transaction tx = null;
    
      protected boolean synched = false;
  @@ -142,23 +142,51 @@
      
      protected boolean isCallAllowed(MethodInvocation mi)
      {
  +      // is this a reentrant bean
         if (reentrant)
         {
            return true;
         }
  -      else
  +
  +      // is this a known non-entrant method
  +      Method m = mi.getMethod();
  +      if (m.equals(getEJBHome) ||
  +          m.equals(getHandle) ||
  +          m.equals(getPrimaryKey) ||
  +          m.equals(isIdentical) ||
  +          m.equals(remove))
         {
  -         Method m = mi.getMethod();
  -         if (m.equals(getEJBHome) ||
  -             m.equals(getHandle) ||
  -             m.equals(getPrimaryKey) ||
  -             m.equals(isIdentical) ||
  -             m.equals(remove))
  -         {
  -            return true;
  -         }
  +         return true;
         }
  -      
  +
         return false;
  +   }
  +
  +   // This following is for deadlock detection
  +   protected static HashMap waiting = new HashMap();
  +
  +   public void deadlockDetection(Transaction miTx) throws 
ApplicationDeadlockException
  +   {
  +      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 ApplicationDeadlockException("application deadlock 
detected");
  +            }
  +            set.add(waitingFor);
  +         }
  +         checkTx = waitingFor;
  +      }
  +      }
      }
   }
  
  
  
  1.3.4.4   +86 -58    
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.3.4.3
  retrieving revision 1.3.4.4
  diff -u -r1.3.4.3 -r1.3.4.4
  --- QueuedPessimisticEJBLock.java     20 Nov 2001 09:42:52 -0000      1.3.4.3
  +++ QueuedPessimisticEJBLock.java     13 Feb 2002 22:46:57 -0000      1.3.4.4
  @@ -9,15 +9,13 @@
   
   import java.util.LinkedList;
   import java.util.HashMap;
  -import java.util.Collections;
  -import java.lang.reflect.Method;
   
  -import javax.ejb.EJBObject;
  -import javax.transaction.Status;
   import javax.transaction.Transaction;
  +import javax.transaction.Status;
   
   import org.jboss.ejb.MethodInvocation;
   
  + 
   
   /**
    * This class is holds threads awaiting the transactional lock to be free
  @@ -33,10 +31,13 @@
    * When the reference count goes to 0, the lock is released from the
    * id -> lock mapping.
    *
  + * FIXME marcf: we should get solid numbers on this locking, bench in multi-thread 
environments
  + * We need someone with serious SUN hardware to run this lock into the ground
  + *
    * @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
    * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
    *
  - * @version $Revision: 1.3.4.3 $
  + * @version $Revision: 1.3.4.4 $
    *
    * <p><b>Revisions:</b><br>
    * <p><b>2001/08/03: billb</b>
  @@ -238,59 +239,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 +471,6 @@
            System.out.println(Thread.currentThread() + " removing lock!");
         */
      }
  +
   }
   
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.2.1   +40 -0     
jboss/src/main/org/jboss/ejb/plugins/lock/Attic/ApplicationDeadlockException.java
  
  
  
  

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

Reply via email to