User: salborini
Date: 00/10/19 20:11:45
Modified: src/main/org/jboss/ejb/plugins
EntityInstanceInterceptor.java
TxInterceptorCMT.java
Log:
Improved synchronization logic.
Revision Changes Path
1.22 +213 -207
jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java
Index: EntityInstanceInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntityInstanceInterceptor.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- EntityInstanceInterceptor.java 2000/10/19 21:48:42 1.21
+++ EntityInstanceInterceptor.java 2000/10/20 03:11:43 1.22
@@ -42,8 +42,9 @@
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
-* @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.21 $
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
+* @version $Revision: 1.22 $
*/
public class EntityInstanceInterceptor
extends AbstractInterceptor
@@ -60,232 +61,237 @@
// Public --------------------------------------------------------
public void setContainer(Container container)
{
- this.container = (EntityContainer)container;
+ this.container = (EntityContainer)container;
}
public Container getContainer()
{
- return container;
+ return container;
}
// Interceptor implementation --------------------------------------
public Object invokeHome(MethodInvocation mi)
throws Exception
{
- // Get context
- EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstancePool().get();
- mi.setEnterpriseContext(ctx);
-
- // It is a new context for sure so we can lock it
- ctx.lock();
-
- try
- {
- // Invoke through interceptors
- return getNext().invokeHome(mi);
- } finally
- {
- // Always unlock, no matter what
- ctx.unlock();
-
- // Still free? Not free if create() was called successfully
- if (ctx.getId() == null)
- {
- container.getInstancePool().free(ctx);
- }
- else
- {
- // DEBUG Logger.debug("Entity was created; not returned to
pool");
- synchronized (ctx) {
-
- //Let the waiters know
- ctx.notifyAll();
- }
- }
- }
+ // Get context
+ EnterpriseContext ctx =
((EntityContainer)getContainer()).getInstancePool().get();
+ mi.setEnterpriseContext(ctx);
+
+ // It is a new context for sure so we can lock it
+ ctx.lock();
+
+ try
+ {
+ // Invoke through interceptors
+ return getNext().invokeHome(mi);
+ } finally
+ {
+ // Always unlock, no matter what
+ ctx.unlock();
+
+ // Still free? Not free if create() was called successfully
+ if (ctx.getId() == null)
+ {
+ container.getInstancePool().free(ctx);
+ }
+ else
+ {
+ // DEBUG Logger.debug("Entity was created; not returned
to pool");
+ synchronized (ctx) {
+
+ //Let the waiters know
+ ctx.notifyAll();
+ }
+ }
+ }
}
public Object invoke(MethodInvocation mi)
throws Exception
{
- // The id store is a CacheKey in the case of Entity
- CacheKey key = (CacheKey) mi.getId();
-
- // Get cache
- EnterpriseInstanceCache cache =
(EnterpriseInstanceCache)container.getInstanceCache();
- Object mutex = cache.getLock(key);
-
- EnterpriseContext ctx = null;
-
- // We synchronize the locking logic (so that the invoke is unsynchronized
and can be reentrant)
- do
- {
- synchronized (mutex)
- {
- // Get context
- ctx = cache.get(key);
-
- // Do we have a running transaction with the context
- Transaction tx = ctx.getTransaction();
- if (tx != null &&
- // And are we trying to enter with another transaction
- !tx.equals(mi.getTransaction()))
- {
- // Let's put the thread to sleep a lock release will wake the thread
- synchronized (ctx)
- {
- // Possible deadlock
- Logger.log("LOCKING-WAITING (TRANSACTION) for id "+ctx.getId()+"
ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" : tx.toString()));
-
- try{ctx.wait(100);}
- catch (InterruptedException ie) {}
- }
-
- // Try your luck again
- ctx = null;
- continue;
- }
-
- if (!ctx.isLocked()){
-
- //take it!
- ctx.lock();
- }
-
- else
+ // The id store is a CacheKey in the case of Entity
+ CacheKey key = (CacheKey) mi.getId();
+
+ // Get cache
+ EnterpriseInstanceCache cache =
(EnterpriseInstanceCache)container.getInstanceCache();
+ Object mutex = cache.getLock(key);
+
+ EnterpriseContext ctx = null;
+
+ try
+ {
+ do
+ {
+ if (mi.getTransaction() != null && mi.getTransaction().getStatus()
== Status.STATUS_MARKED_ROLLBACK)
+ throw new RuntimeException("Transaction marked for rollback,
possibly a timeout");
+
+ synchronized(this)
+ {
+
+ // Get context
+ ctx = cache.get(key);
+ }
+
+ synchronized(ctx)
{
- if (!isCallAllowed(mi)) {
+
+ // Do we have a running transaction with the context
+ Transaction tx = ctx.getTransaction();
+ if (tx != null &&
+ // And are we trying to enter with another transaction
+ !tx.equals(mi.getTransaction()))
+ {
+ // Let's put the thread to sleep a lock release will wake
the thread
+ // Possible deadlock
+ Logger.debug("LOCKING-WAITING (TRANSACTION) for id
"+ctx.getId()+" ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" :
tx.toString()));
- // Go to sleep and wait for the lock to be released
- // This is not one of the "home calls" so we need to wait
for the lock
- synchronized (ctx)
- {
- // Possible deadlock
- Logger.log("LOCKING-WAITING (CTX) for id
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
-
- try{ctx.wait(100);}
- catch (InterruptedException ie) {}
- }
+ try {
+ ctx.wait();
+ } catch (InterruptedException ie) {}
// Try your luck again
ctx = null;
continue;
- // Not allowed reentrant call
- //throw new RemoteException("Reentrant call");
+
+ }
+ else
+ {
+ // If we get here it's the right tx, or no tx
+ if (!ctx.isLocked())
+ {
+ //take it!
+ ctx.lock();
+ }
+ else
+ {
+ if (!isCallAllowed(mi)) {
+
+ // Go to sleep and wait for the lock to be released
+ // This is not one of the "home calls" so we need
to wait for the lock
+
+ // Possible deadlock
+ Logger.debug("LOCKING-WAITING (CTX) for id
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
+
+ try{
+ ctx.wait();
+ } catch (InterruptedException ie) {}
+
+ // Try your luck again
+ ctx = null;
+ continue;
+ // Not allowed reentrant call
+ //throw new RemoteException("Reentrant call");
+ }
+ else
+ {
+ //We are in a home call so take the lock, take it!
+ ctx.lock();
+ }
+ }
+ }
+ }
+
+ } while (ctx == null);
+
+ // Set context on the method invocation
+ mi.setEnterpriseContext(ctx);
+
+ // Go on, you won
+ return getNext().invoke(mi);
+
+ }
+ catch (RemoteException e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ cache.remove(key);
+
+ throw e;
+ } catch (RuntimeException e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ cache.remove(key);
+
+ throw e;
+ } catch (Error e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ cache.remove(key);
+
+ throw e;
+ } finally
+ {
+ // Logger.debug("Release instance for "+id);
+ if (ctx != null)
+ {
+ // unlock the context
+ ctx.unlock();
+
+ if (ctx.getId() == null)
+ {
- } else
- {
- //We are in a home call so take the lock, take it!
- ctx.lock();
- }
- }
-
- }
- } while (ctx == null);
-
- // Set context on the method invocation
- mi.setEnterpriseContext(ctx);
-
- try {
- // Go on, you won
- return getNext().invoke(mi);
-
- }
- catch (RemoteException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
- cache.remove(key);
-
- throw e;
- } catch (RuntimeException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
- cache.remove(key);
-
- throw e;
- } catch (Error e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
- cache.remove(key);
-
- throw e;
- } finally
- {
- // Logger.debug("Release instance for "+id);
- if (ctx != null)
- {
-
- synchronized (mutex) {
-
- // unlock the context
- ctx.unlock();
-
- if (ctx.getId() == null)
- {
-
- // Work only if no transaction was
encapsulating this remove()
- if (ctx.getTransaction() == null) {
-
- // Remove from cache
- cache.remove(key);
-
- // It has been removed -> send
to the pool
-
container.getInstancePool().free(ctx);
- }
- }
-
- // notify the thread waiting on ctx
- synchronized (ctx) { ctx.notifyAll();}
- }
- }
- }
- }
-
- // Private --------------------------------------------------------
-
- private static Method getEJBHome;
- private static Method getHandle;
- private static Method getPrimaryKey;
- private static Method isIdentical;
- private static Method remove;
- static
- {
- try
- {
- Class[] noArg = new Class[0];
- getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
- getHandle = EJBObject.class.getMethod("getHandle", noArg);
- getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", noArg);
- isIdentical = EJBObject.class.getMethod("isIdentical", new Class[]
{EJBObject.class});
- remove = EJBObject.class.getMethod("remove", noArg);
- }
- catch (Exception x) {x.printStackTrace();}
- }
-
- private boolean isCallAllowed(MethodInvocation mi)
- {
- boolean reentrant =
((EntityMetaData)container.getBeanMetaData()).isReentrant();
-
- if (reentrant)
- {
- return true;
- }
- else
- {
- Method m = mi.getMethod();
- if (m.equals(getEJBHome) ||
- m.equals(getHandle) ||
- m.equals(getPrimaryKey) ||
- m.equals(isIdentical) ||
- m.equals(remove))
- {
- return true;
- }
- }
-
- return false;
+ // Work only if no transaction was encapsulating this remove()
+ if (ctx.getTransaction() == null) {
+
+ // Remove from cache
+ cache.remove(key);
+
+ // It has been removed -> send to the pool
+ container.getInstancePool().free(ctx);
+ }
+ }
+
+ // notify the thread waiting on ctx
+ synchronized (ctx) { ctx.notifyAll();}
+ }
+ }
+ }
+
+
+// Private --------------------------------------------------------
+
+private static Method getEJBHome;
+private static Method getHandle;
+private static Method getPrimaryKey;
+private static Method isIdentical;
+private static Method remove;
+static
+{
+ try
+ {
+ Class[] noArg = new Class[0];
+ getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
+ getHandle = EJBObject.class.getMethod("getHandle", noArg);
+ getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", noArg);
+ isIdentical = EJBObject.class.getMethod("isIdentical", new Class[]
{EJBObject.class});
+ remove = EJBObject.class.getMethod("remove", noArg);
+ }
+ catch (Exception x) {x.printStackTrace();}
+}
+
+private boolean isCallAllowed(MethodInvocation mi)
+{
+ boolean reentrant = ((EntityMetaData)container.getBeanMetaData()).isReentrant();
+
+ if (reentrant)
+ {
+ return true;
}
+ else
+ {
+ Method m = mi.getMethod();
+ if (m.equals(getEJBHome) ||
+ m.equals(getHandle) ||
+ m.equals(getPrimaryKey) ||
+ m.equals(isIdentical) ||
+ m.equals(remove))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
}
1.7 +13 -10 jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java
Index: TxInterceptorCMT.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TxInterceptorCMT.java 2000/10/08 05:30:17 1.6
+++ TxInterceptorCMT.java 2000/10/20 03:11:43 1.7
@@ -40,7 +40,7 @@
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
-* @version $Revision: 1.6 $
+* @version $Revision: 1.7 $
*/
public class TxInterceptorCMT
extends AbstractInterceptor
@@ -266,8 +266,8 @@
if (newTransaction != null) {
- //We started it,
- newTransaction.rollback();
+ //We started it, it will be rolled back in the finally
+ newTransaction.setRollbackOnly();
}
throw e;
@@ -276,8 +276,8 @@
if (newTransaction != null) {
- // We started it
- newTransaction.rollback();
+ // We started it, it will be rolled back in the finally
+ newTransaction.setRollbackOnly();
}
throw new ServerException("Exception occurred", e);
@@ -286,8 +286,8 @@
if (newTransaction != null) {
- // we started it
- newTransaction.rollback();
+ // we started it, it will be rolled back in the finally
+ newTransaction.setRollbackOnly();
}
throw new ServerException("Exception
occurred:"+e.getMessage());
}
@@ -380,21 +380,24 @@
catch (RemoteException e) {
// We started it for sure
- newTransaction.rollback();
+ // will be rolled back in the finally
+ newTransaction.setRollbackOnly();
throw e;
}
catch (RuntimeException e) {
// We started it for sure
- newTransaction.rollback();
+ // will be rolled back in the finally
+ newTransaction.setRollbackOnly();
throw new ServerException("Exception occurred", e);
}
catch (Error e) {
// We started it for sure
- newTransaction.rollback();
+ // will be rolled back in the finally
+ newTransaction.setRollbackOnly();
throw new ServerException("Exception
occurred:"+e.getMessage());
}