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