User: fleury
Date: 00/08/10 09:42:17
Modified: src/main/org/jboss/ejb/plugins
EntitySynchronizationInterceptor.java
Log:
A rewrite of it.
We do not rely on maps anymore.
The maps did not buy us anything (aggregation is not real in VM and distributed
should be done right by JTM) and we payed a double price of synchronized and Map
lookup. we can do it O(1).
Also we remove the implicit dependency on the "tx in CTX"!= "tx in MI" to determine
whether to store or not. The information "isInvoked" gives that.
Revision Changes Path
1.9 +152 -172
jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java
Index: EntitySynchronizationInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/EntitySynchronizationInterceptor.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- EntitySynchronizationInterceptor.java 2000/08/10 04:24:02 1.8
+++ EntitySynchronizationInterceptor.java 2000/08/10 16:42:17 1.9
@@ -48,7 +48,7 @@
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.8 $
+* @version $Revision: 1.9 $
*/
public class EntitySynchronizationInterceptor
extends AbstractInterceptor
@@ -62,7 +62,6 @@
public static final int C = 2; // Passivate
// Attributes ----------------------------------------------------
- HashMap synchs = new HashMap(); // tx -> synch
int commitOption = A;
@@ -95,47 +94,30 @@
public void register(EnterpriseContext ctx, Transaction tx)
{
- // Associate ctx with tx
- synchronized (synchs)
- {
- // Get synchronization for this tx - create if there is none
- InstanceSynchronization synch =
(InstanceSynchronization)synchs.get(tx);
- if (synch == null)
- {
- // Register new synch with current tx
- synch = new InstanceSynchronization(tx);
- synchs.put(tx, synch);
-
- try
- {
- tx.registerSynchronization(synch);
- } catch (Exception e)
- {
- throw new EJBException(e);
- }
- }
+ // Create a new synchronization
+ InstanceSynchronization synch = new InstanceSynchronization(tx);
+
+ try {
+
+ tx.registerSynchronization(synch);
+ }
+ catch (Exception e) {
- synch.add(ctx);
- ((EntityEnterpriseContext)ctx).setTransaction(tx);
+ throw new EJBException(e);
}
+
+ // register
+ synch.add(ctx);
}
- public void deregister(EntityEnterpriseContext ctx, Transaction tx)
+ public void deregister(EntityEnterpriseContext ctx)
{
+ // MF FIXME: I suspect this is redundant now
+ // (won't the pool clean it up?)
+
// Deassociate ctx with tx
- synchronized (synchs)
- {
- // Get synchronization for this tx
- InstanceSynchronization synch =
(InstanceSynchronization)synchs.get(tx);
- if (synch == null)
- {
- return;
- }
-
- synch.remove(ctx);
- ctx.setTransaction(null);
- ctx.setInvoked(false);
- }
+ ctx.setTransaction(null);
+ ctx.setInvoked(false);
}
// Interceptor implementation --------------------------------------
@@ -160,7 +142,7 @@
}
// Currently synched with underlying storage
- ((EntityEnterpriseContext)ctx).setSynchronized(true);
+ ((EntityEnterpriseContext)ctx).setValid(true);
}
}
}
@@ -168,60 +150,67 @@
public Object invoke(MethodInvocation mi)
throws Exception
{
+ // We are going to work with the context a lot
EntityEnterpriseContext ctx =
(EntityEnterpriseContext)mi.getEnterpriseContext();
+ // The Tx coming as part of the Method Invocation
+ Transaction tx = mi.getTransaction();
- Transaction tx = ctx.getTransaction();
- Transaction current = mi.getTransaction();
+ //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("newTx: "+ tx);
- //DEBUG Logger.debug("TX:"+(current.getStatus() ==
Status.STATUS_ACTIVE));
-
- if (current != null &&
- current.getStatus() == Status.STATUS_ACTIVE)
- {
+ // Is my state valid?
+ if (!ctx.isValid()) {
- // Synchronize with DB
- if (!ctx.isSynchronized())
- {
- //DEBUG Logger.debug("SYNCH");
-
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
- ctx.setSynchronized(true);
- }
+ // If not tell the persistence manager to load the state
+
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
- try
- {
+ // Now the state is valid
+ ctx.setValid(true);
+ }
+
+ // So we can go on with the invocation
+
+ if (tx != null &&
+ tx.getStatus() == Status.STATUS_ACTIVE) {
+
+ try {
+
return getNext().invoke(mi);
- } finally
- {
- if (ctx.getId() != null)
- {
- // Associate ctx with tx
- if (tx != null)
- {
- ctx.setInvoked(true); // This causes
ejbStore to be invoked on tx commit
- register(ctx, current);
+ }
+
+ finally {
+
+ // Do we have a valid bean (not removed)
+ if (ctx.getId() != null) {
+
+ // If the context was not invoked previously...
+ if (!ctx.isInvoked()) {
+
+ // It is now and this will cause
ejbStore to be called...
+ ctx.setInvoked(true);
+
+ // ... on a transaction callback that
we register here.
+ register(ctx, tx);
}
- } else
- {
+ }
+ else {
+
// Entity was removed
- if (ctx.getTransaction() != null)
- {
- // Disassociate ctx with tx
- deregister(ctx, current);
+ if (ctx.getTransaction() != null) {
+
+ // Disassociate ctx
+ deregister(ctx);
}
}
- }
- } else
- {
- // No tx
-
- // Synchronize with DB
- if (!ctx.isSynchronized())
- {
- //DEBUG Logger.debug("SYNCH");
-
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
- ctx.setSynchronized(true);
+
+ //Logger.debug("CTX out: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("PresentTx:"+tx);
+
}
+ }
+
+ else { // No tx
try
{
@@ -236,7 +225,7 @@
} catch (Exception e)
{
// Exception - force reload on next call
- ctx.setSynchronized(false);
+ ctx.setValid(false);
throw e;
}
}
@@ -248,9 +237,12 @@
class InstanceSynchronization
implements Synchronization
{
- ArrayList ctxList = new ArrayList();
+ // The transaction we follow
Transaction tx;
+ // The context we manage
+ EnterpriseContext ctx;
+
InstanceSynchronization(Transaction tx)
{
this.tx = tx;
@@ -258,38 +250,27 @@
public void add(EnterpriseContext ctx)
{
- ctxList.add(ctx.getId());
+ this.ctx = ctx;
}
- public void remove(EnterpriseContext ctx)
- {
- ctxList.remove(ctx.getId());
- }
// Synchronization implementation -----------------------------
public void beforeCompletion()
{
- InstanceCache cache =
((EntityContainer)getContainer()).getInstanceCache();
-
try
{
-
- for (int i = 0; i < ctxList.size(); i++)
+ try
{
// Lock instance
- try
- {
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)cache.get(ctxList.get(i));
- // Store instance if business method
was
- if (ctx.isInvoked())
-
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
-
- // Save for after completion
- ctxList.set(i, ctx);
- } catch (NoSuchEntityException e)
- {
- // Object has been removed -- ignore
- }
+
((EntityContainer)getContainer()).getInstanceCache().get(ctx.getId());
+
+ // Store instance if business method was
+ if (((EntityEnterpriseContext)
ctx).isInvoked())
+
((EntityContainer)getContainer()).getPersistenceManager().storeEntity((EntityEnterpriseContext)ctx);
+
+ } catch (NoSuchEntityException e)
+ {
+ // Object has been removed -- ignore
}
} catch (RemoteException e)
{
@@ -310,83 +291,82 @@
if (status == Status.STATUS_ROLLEDBACK)
{
- for (int i = 0; i < ctxList.size(); i++)
+ try
{
- try
- {
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)ctxList.get(i);
-
- ctx.setId(null);
- ctx.setTransaction(null);
-
container.getInstanceCache().remove(ctx);
- container.getInstancePool().free(ctx);
// TODO: should this be done? still valid instance?
- } catch (Exception e)
- {
- // Ignore
- }
+
+ ctx.setId(null);
+ ctx.setTransaction(null);
+ container.getInstanceCache().remove(ctx);
+ container.getInstancePool().free(ctx); //
TODO: should this be done? still valid instance?
+ } catch (Exception e)
+ {
+ // Ignore
}
} else
{
- for (int i = 0; i < ctxList.size(); i++)
+
+ // The transaction is done
+ ctx.setTransaction(null);
+
+ // We are afterCompletion so the invoked can be set to
false (db sync is done)
+ ((EntityEnterpriseContext) ctx).setInvoked(false);
+
+ switch (commitOption)
{
- switch (commitOption)
- {
- // Keep instance cached after tx commit
- case A:
- try
- {
-
EntityEnterpriseContext ctx = (EntityEnterpriseContext)ctxList.get(i);
-
ctx.setTransaction(null);
- ctx.setInvoked(false);
-
container.getInstanceCache().release(ctx);
- } catch (Exception e)
- {
- Logger.debug(e);
- }
- break;
-
- // Keep instance, but invalidate state
- case B:
- try
- {
-
EntityEnterpriseContext ctx = (EntityEnterpriseContext)ctxList.get(i);
-
ctx.setTransaction(null);
- ctx.setInvoked(false);
-
-
ctx.setSynchronized(false); // Invalidate state
-
container.getInstanceCache().release(ctx);
- } catch (Exception e)
- {
- Logger.debug(e);
- }
- break;
-
- // Passivate instance
- case C:
- try
- {
-
EntityEnterpriseContext ctx = (EntityEnterpriseContext)ctxList.get(i);
-
ctx.setTransaction(null);
- ctx.setInvoked(false);
-
-
container.getInstanceCache().get(ctx.getId()); // Lock in cache
-
((EntityContainer)getContainer()).getPersistenceManager().passivateEntity(ctx); //
Passivate instance
-
container.getInstanceCache().remove(ctx.getId()); // Remove from cache
-
-
container.getInstancePool().free(ctx); // Add to instance pool
+ // Keep instance cached after tx commit
+ case A:
+ try
+ {
+ // The state is still valid
(only point of access is us)
+ ((EntityEnterpriseContext)
ctx).setValid(true);
- } catch (Exception e)
- {
- Logger.debug(e);
- }
- break;
- }
+ // Release it though
+
container.getInstanceCache().release(ctx);
+ } catch (Exception e)
+ {
+ Logger.debug(e);
+ }
+ break;
+
+ // Keep instance active, but invalidate state
+ case B:
+ try
+ {
+ // Invalidate state (there
might be other points of entry)
+ ((EntityEnterpriseContext)
ctx).setValid(false);
+
+ // Release it though
+
container.getInstanceCache().release(ctx);
+ } catch (Exception e)
+ {
+ Logger.debug(e);
+ }
+ break;
+
+ // Invalidate everything AND Passivate instance
+ case C:
+ try
+ {
+ //Lock in cache
+
container.getInstanceCache().get(ctx.getId());
+
+ // Passivate instance
+
((EntityContainer)getContainer()).getPersistenceManager().passivateEntity((EntityEnterpriseContext)ctx);
+
+ //Remove from the cache, it is
not active anymore
+
container.getInstanceCache().remove(ctx.getId());
+
+ // Back to the pool
+
container.getInstancePool().free(ctx);
+
+ } catch (Exception e)
+ {
+ Logger.debug(e);
+ }
+ break;
}
}
-
- // Remove from tx/synch mapping
- synchs.remove(this);
// Notify all who are waiting for this tx to end
synchronized (tx)
- [jBoss-Dev] CVS update: jboss/src/main/org/jboss/ejb... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
- [jBoss-Dev] CVS update: jboss/src/main/org/jbos... jBoss CVS Development
