User: fleury
Date: 00/08/17 13:13:15
Modified: src/main/org/jboss/ejb/plugins BMPPersistenceManager.java
CMPPersistenceManager.java
EntityInstanceInterceptor.java
EntitySynchronizationInterceptor.java
NoPassivationEntityInstanceCache.java
RandomEntityInstanceCache.java
Log:
Support for fastCache
DOESN'T FULLY WORK YET..
I NEED TO GO TO THE OFFICE THOUGH!!!!!!!! (dies in one of the TestBeans test)
Revision Changes Path
1.4 +10 -2 jboss/src/main/org/jboss/ejb/plugins/BMPPersistenceManager.java
Index: BMPPersistenceManager.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/BMPPersistenceManager.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- BMPPersistenceManager.java 2000/07/25 09:55:57 1.3
+++ BMPPersistenceManager.java 2000/08/17 20:13:13 1.4
@@ -17,6 +17,7 @@
import javax.ejb.EntityBean;
import javax.ejb.CreateException;
+import org.jboss.util.FastKey;
import org.jboss.ejb.Container;
import org.jboss.ejb.EntityContainer;
import org.jboss.ejb.EntityPersistenceManager;
@@ -27,7 +28,8 @@
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.3 $
+ * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+ * @version $Revision: 1.4 $
*/
public class BMPPersistenceManager
implements EntityPersistenceManager
@@ -109,11 +111,17 @@
// set the id
ctx.setId(id);
+ // Create a new FastKey
+ FastKey fastKey = new FastKey(id);
+
+ // Pass it implicitely!
+ ctx.setFastKey(fastKey);
+
// Lock instance in cache
con.getInstanceCache().insert(ctx);
// Create EJBObject
- ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(id));
+ ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(fastKey));
try {
postCreateMethod.invoke(ctx.getInstance(), args);
1.3 +215 -208 jboss/src/main/org/jboss/ejb/plugins/CMPPersistenceManager.java
Index: CMPPersistenceManager.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/CMPPersistenceManager.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- CMPPersistenceManager.java 2000/07/14 19:13:58 1.2
+++ CMPPersistenceManager.java 2000/08/17 20:13:14 1.3
@@ -22,6 +22,7 @@
import org.jboss.ejb.EntityPersistenceManager;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.EntityPersistenceStore;
+import org.jboss.util.FastKey;
/**
* The CMP Persistence Manager implements the semantics of the CMP
@@ -32,217 +33,223 @@
*
* @see <related>
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.2 $
+* @version $Revision: 1.3 $
*/
public class CMPPersistenceManager
implements EntityPersistenceManager {
- // Constants -----------------------------------------------------
-
- // Attributes ----------------------------------------------------
- EntityContainer con;
- // Physical persistence implementation
- EntityPersistenceStore store;
-
- // The EJB Methods, the reason for this class
- Method ejbLoad;
- Method ejbStore;
- Method ejbActivate;
- Method ejbPassivate;
- Method ejbRemove;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container c) {
- con = (EntityContainer)c;
- if (store != null) store.setContainer(c);
- }
-
-
- public void setPersistenceStore(EntityPersistenceStore store) {
- this.store= store;
-
- //Give it the container
- if (con!= null) store.setContainer(con);
- }
-
- public void init()
- throws Exception {
-
- // The common EJB methods
- ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
- ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
- ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
- ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new
Class[0]);
- ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
-
- // Initialize the sto re
- store.init();
- }
-
- public void start()
- throws Exception {
-
- store.start();
- }
-
- public void stop() {
- store.stop();
- }
-
- public void destroy() {
- store.destroy();
- }
-
- public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
- throws RemoteException, CreateException {
- // Get methods
- try {
-
- Method createMethod =
con.getBeanClass().getMethod("ejbCreate", m.getParameterTypes());
- Method postCreateMethod =
con.getBeanClass().getMethod("ejbPostCreate", m.getParameterTypes());
-
- // Call ejbCreate on the target bean
- createMethod.invoke(ctx.getInstance(), args);
-
- // Have the store persist the new instance, the return is the
key
- Object id = store.createEntity(m, args, ctx);
-
- // Set the key on the target context
- ctx.setId(id);
-
- // Lock instance in cache
- con.getInstanceCache().insert(ctx);
-
- // Create EJBObject
-
ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(id));
-
- postCreateMethod.invoke(ctx.getInstance(), args);
-
- }
- catch (InvocationTargetException e) {
- throw new CreateException("Create failed:"+e);
- }
- catch (NoSuchMethodException e) {
- throw new CreateException("Create methods not found:"+e);
- }
- catch (IllegalAccessException e) {
- throw new CreateException("Could not create entity:"+e);
- }
- }
-
- public Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException {
-
- return store.findEntity(finderMethod, args, ctx);
- }
-
- public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
- throws RemoteException, FinderException {
-
- return store.findEntities(finderMethod, args, ctx);
- }
-
- /*
- * activateEntity(EnterpriseContext ctx)
- *
- * The method calls the target beans for spec compliant callbacks.
- * Since these are pure EJB calls it is not obvious that the store should
- * expose the interfaces. In case of jaws however we found that store specific
- * contexts could be set in the activateEntity calls and hence a propagation of
- * the call made sense. The persistence store is called for "extension"
purposes.
- *
- * @see activateEntity on EntityPersistenceStore.java
- */
- public void activateEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- // Call bean
- try
- {
- ejbActivate.invoke(ctx.getInstance(), new Object[0]);
- } catch (Exception e)
- {
- throw new ServerException("Activation failed", e);
- }
-
- store.activateEntity(ctx);
- }
-
- public void loadEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- try {
-
- // Have the store deal with create the fields of the instance
- store.loadEntity(ctx);
-
- // Call ejbLoad on bean instance, wake up!
- ejbLoad.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e) {
- throw new ServerException("Load failed", e);
- }
- }
-
- public void storeEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
- // System.out.println("Store entity");
- try {
-
- // Prepare the instance for storage
- ejbStore.invoke(ctx.getInstance(), new Object[0]);
-
- // Have the store deal with storing the fields of the instance
- store.storeEntity(ctx);
- }
-
- catch (Exception e) {
- throw new ServerException("Store failed", e);
- }
- }
-
- public void passivateEntity(EntityEnterpriseContext ctx)
- throws RemoteException {
-
- try {
-
- // Prepare the instance for passivation
- ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e) {
-
- throw new ServerException("Passivation failed", e);
- }
-
- store.passivateEntity(ctx);
- }
-
- public void removeEntity(EntityEnterpriseContext ctx)
- throws RemoteException, RemoveException {
-
- try {
-
- // Call ejbRemove
- ejbRemove.invoke(ctx.getInstance(), new Object[0]);
- }
- catch (Exception e){
-
- throw new RemoveException("Could not remove "+ctx.getId());
- }
+ // Constants -----------------------------------------------------
+
+ // Attributes ----------------------------------------------------
+ EntityContainer con;
+ // Physical persistence implementation
+ EntityPersistenceStore store;
+
+ // The EJB Methods, the reason for this class
+ Method ejbLoad;
+ Method ejbStore;
+ Method ejbActivate;
+ Method ejbPassivate;
+ Method ejbRemove;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container c) {
+ con = (EntityContainer)c;
+ if (store != null) store.setContainer(c);
+ }
+
+
+ public void setPersistenceStore(EntityPersistenceStore store) {
+ this.store= store;
+
+ //Give it the container
+ if (con!= null) store.setContainer(con);
+ }
+
+ public void init()
+ throws Exception {
+
+ // The common EJB methods
+ ejbLoad = EntityBean.class.getMethod("ejbLoad", new Class[0]);
+ ejbStore = EntityBean.class.getMethod("ejbStore", new Class[0]);
+ ejbActivate = EntityBean.class.getMethod("ejbActivate", new Class[0]);
+ ejbPassivate = EntityBean.class.getMethod("ejbPassivate", new Class[0]);
+ ejbRemove = EntityBean.class.getMethod("ejbRemove", new Class[0]);
+
+ // Initialize the sto re
+ store.init();
+ }
+
+ public void start()
+ throws Exception {
+
+ store.start();
+ }
+
+ public void stop() {
+ store.stop();
+ }
+
+ public void destroy() {
+ store.destroy();
+ }
+
+ public void createEntity(Method m, Object[] args, EntityEnterpriseContext ctx)
+ throws RemoteException, CreateException {
+ // Get methods
+ try {
+
+ Method createMethod = con.getBeanClass().getMethod("ejbCreate",
m.getParameterTypes());
+ Method postCreateMethod = con.getBeanClass().getMethod("ejbPostCreate",
m.getParameterTypes());
+
+ // Call ejbCreate on the target bean
+ createMethod.invoke(ctx.getInstance(), args);
+
+ // Have the store persist the new instance, the return is the key
+ Object id = store.createEntity(m, args, ctx);
+
+ // Set the key on the target context
+ ctx.setId(id);
+
+ // Create a new FastKey
+ FastKey fastKey = new FastKey(id);
+
+ // Pass it implicitely!
+ ctx.setFastKey(fastKey);
+
+ // Lock instance in cache
+ con.getInstanceCache().insert(ctx);
+
+ // Create EJBObject
+ ctx.setEJBObject(con.getContainerInvoker().getEntityEJBObject(fastKey));
+
+ postCreateMethod.invoke(ctx.getInstance(), args);
+
+ }
+ catch (InvocationTargetException e) {
+ throw new CreateException("Create failed:"+e);
+ }
+ catch (NoSuchMethodException e) {
+ throw new CreateException("Create methods not found:"+e);
+ }
+ catch (IllegalAccessException e) {
+ throw new CreateException("Could not create entity:"+e);
+ }
+ }
+
+ public Object findEntity(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException {
- store.removeEntity(ctx);
- }
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
-
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
+ return store.findEntity(finderMethod, args, ctx);
+ }
+
+ public Collection findEntities(Method finderMethod, Object[] args,
EntityEnterpriseContext ctx)
+ throws RemoteException, FinderException {
+
+ return store.findEntities(finderMethod, args, ctx);
+ }
+
+ /*
+ * activateEntity(EnterpriseContext ctx)
+ *
+ * The method calls the target beans for spec compliant callbacks.
+ * Since these are pure EJB calls it is not obvious that the store should
+ * expose the interfaces. In case of jaws however we found that store specific
+ * contexts could be set in the activateEntity calls and hence a propagation of
+ * the call made sense. The persistence store is called for "extension"
purposes.
+ *
+ * @see activateEntity on EntityPersistenceStore.java
+ */
+ public void activateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ // Call bean
+ try
+ {
+ ejbActivate.invoke(ctx.getInstance(), new Object[0]);
+ } catch (Exception e)
+ {
+ throw new ServerException("Activation failed", e);
+ }
+
+ store.activateEntity(ctx);
+ }
+
+ public void loadEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ try {
+
+ // Have the store deal with create the fields of the instance
+ store.loadEntity(ctx);
+
+ // Call ejbLoad on bean instance, wake up!
+ ejbLoad.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e) {
+ throw new ServerException("Load failed", e);
+ }
+ }
+
+ public void storeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+ // System.out.println("Store entity");
+ try {
+
+ // Prepare the instance for storage
+ ejbStore.invoke(ctx.getInstance(), new Object[0]);
+
+ // Have the store deal with storing the fields of the instance
+ store.storeEntity(ctx);
+ }
+
+ catch (Exception e) {
+ throw new ServerException("Store failed", e);
+ }
+ }
+
+ public void passivateEntity(EntityEnterpriseContext ctx)
+ throws RemoteException {
+
+ try {
+
+ // Prepare the instance for passivation
+ ejbPassivate.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e) {
+
+ throw new ServerException("Passivation failed", e);
+ }
+
+ store.passivateEntity(ctx);
+ }
+
+ public void removeEntity(EntityEnterpriseContext ctx)
+ throws RemoteException, RemoveException {
+
+ try {
+
+ // Call ejbRemove
+ ejbRemove.invoke(ctx.getInstance(), new Object[0]);
+ }
+ catch (Exception e){
+
+ throw new RemoveException("Could not remove "+ctx.getId());
+ }
+
+ store.removeEntity(ctx);
+ }
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
}
1.5 +48 -44
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.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- EntityInstanceInterceptor.java 2000/08/12 00:15:53 1.4
+++ EntityInstanceInterceptor.java 2000/08/17 20:13:14 1.5
@@ -33,13 +33,14 @@
import org.jboss.ejb.InstanceCache;
import org.jboss.ejb.InstancePool;
import org.jboss.ejb.MethodInvocation;
+import org.jboss.util.FastKey;
/**
* This container acquires the given instance.
*
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.4 $
+ * @version $Revision: 1.5 $
*/
public class EntityInstanceInterceptor
extends AbstractInterceptor
@@ -47,7 +48,7 @@
// Constants -----------------------------------------------------
// Attributes ----------------------------------------------------
- protected EntityContainer container;
+ protected EntityContainer container;
// Static --------------------------------------------------------
@@ -56,12 +57,12 @@
// Public --------------------------------------------------------
public void setContainer(Container container)
{
- this.container = (EntityContainer)container;
+ this.container = (EntityContainer)container;
}
-
+
public Container getContainer()
{
- return container;
+ return container;
}
// Interceptor implementation --------------------------------------
@@ -92,53 +93,56 @@
public Object invoke(MethodInvocation mi)
throws Exception
{
+ // The id store is a FastKey in the case of Entity
+ FastKey fastKey = (FastKey) mi.getId();
+
// Get context
- // The cache will properly managed the tx-ctx locking, in case the mi
transaction is different.
-
mi.setEnterpriseContext(((EntityContainer)getContainer()).getInstanceCache().get(mi.getId()));
+ // The cache will properly managed the tx-ctx locking, in case the mi
transaction is different.
+
mi.setEnterpriseContext(((EntityContainer)getContainer()).getInstanceCache().get(fastKey));
try
{
// Invoke through interceptors
return getNext().invoke(mi);
} catch (RemoteException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(mi.getId());
-
- throw e;
- } catch (RuntimeException e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(mi.getId());
-
- throw e;
- } catch (Error e)
- {
- // Discard instance
- // EJB 1.1 spec 12.3.1
-
((EntityContainer)getContainer()).getInstanceCache().remove(mi.getId());
-
- throw e;
- } finally
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ ((EntityContainer)getContainer()).getInstanceCache().remove(fastKey.id);
+
+ throw e;
+ } catch (RuntimeException e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ ((EntityContainer)getContainer()).getInstanceCache().remove(fastKey.id);
+
+ throw e;
+ } catch (Error e)
+ {
+ // Discard instance
+ // EJB 1.1 spec 12.3.1
+ ((EntityContainer)getContainer()).getInstanceCache().remove(fastKey.id);
+
+ throw e;
+ } finally
{
// System.out.println("Release instance for "+id);
- EnterpriseContext ctx = mi.getEnterpriseContext();
- if (ctx != null)
- {
- if (ctx.getId() == null)
- {
- // Remove from cache
-
((EntityContainer)getContainer()).getInstanceCache().remove(mi.getId());
-
- // It has been removed -> send to free pool
- container.getInstancePool().free(ctx);
- }
- {
- // Return context
-
((EntityContainer)getContainer()).getInstanceCache().release(ctx);
- }
- }
+ EnterpriseContext ctx = mi.getEnterpriseContext();
+ if (ctx != null)
+ {
+ if (ctx.getId() == null)
+ {
+ // Remove from cache
+
((EntityContainer)getContainer()).getInstanceCache().remove(fastKey.id);
+
+ // It has been removed -> send to free pool
+ container.getInstancePool().free(ctx);
+ }
+ {
+ // Return context
+ ((EntityContainer)getContainer()).getInstanceCache().release(ctx);
+ }
+ }
}
}
}
1.10 +323 -323
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.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- EntitySynchronizationInterceptor.java 2000/08/10 16:42:17 1.9
+++ EntitySynchronizationInterceptor.java 2000/08/17 20:13:14 1.10
@@ -48,332 +48,332 @@
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-* @version $Revision: 1.9 $
+* @version $Revision: 1.10 $
*/
public class EntitySynchronizationInterceptor
extends AbstractInterceptor
{
- // Constants -----------------------------------------------------
- public static final int TIMEOUT = 10000;
-
- // Commit time options
- public static final int A = 0; // Keep instance cached
- public static final int B = 1; // Invalidate state
- public static final int C = 2; // Passivate
-
- // Attributes ----------------------------------------------------
-
- int commitOption = A;
-
- protected EntityContainer container;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = (EntityContainer)container;
- }
-
- public Container getContainer()
- {
- return container;
- }
-
- public void setCommitOption(int commitOption)
- {
- this.commitOption = commitOption;
- }
-
- public int getCommitOption()
- {
- return commitOption;
- }
-
- public void register(EnterpriseContext ctx, Transaction tx)
- {
- // Create a new synchronization
- InstanceSynchronization synch = new InstanceSynchronization(tx);
-
- try {
-
- tx.registerSynchronization(synch);
- }
- catch (Exception e) {
-
- throw new EJBException(e);
- }
-
- // register
- synch.add(ctx);
- }
-
- public void deregister(EntityEnterpriseContext ctx)
- {
- // MF FIXME: I suspect this is redundant now
- // (won't the pool clean it up?)
-
- // Deassociate ctx with tx
- ctx.setTransaction(null);
- ctx.setInvoked(false);
- }
-
- // Interceptor implementation --------------------------------------
-
- public Object invokeHome(MethodInvocation mi)
- throws Exception
- {
- try
- {
- return getNext().invokeHome(mi);
- } finally
- {
- // Anonymous was sent in, so if it has an id it was created
- EnterpriseContext ctx = mi.getEnterpriseContext();
- if (ctx.getId() != null)
- {
- if (mi.getTransaction() != null &&
- mi.getTransaction().getStatus() ==
Status.STATUS_ACTIVE)
- {
- // Set tx
- register(ctx, mi.getTransaction());
- }
-
- // Currently synched with underlying storage
- ((EntityEnterpriseContext)ctx).setValid(true);
- }
- }
- }
-
- 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();
-
- //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
- //Logger.debug("newTx: "+ tx);
-
- // Is my state valid?
- if (!ctx.isValid()) {
-
- // If not tell the persistence manager to load the state
-
((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
-
- // 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 {
-
- // 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 {
-
- // Entity was removed
- if (ctx.getTransaction() != null) {
-
- // Disassociate ctx
- deregister(ctx);
- }
- }
-
- //Logger.debug("CTX out: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
- //Logger.debug("PresentTx:"+tx);
-
- }
- }
-
- else { // No tx
-
- try
- {
- Object result = getNext().invoke(mi);
-
- // Store after each invocation -- not on exception
though, or removal
- // And skip reads too ("get" methods)
- if (ctx.getId() != null &&
!mi.getMethod().getName().startsWith("get"))
-
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
-
- return result;
- } catch (Exception e)
- {
- // Exception - force reload on next call
- ctx.setValid(false);
- throw e;
- }
- }
- }
-
- // Protected ----------------------------------------------------
-
- // Inner classes -------------------------------------------------
- class InstanceSynchronization
- implements Synchronization
- {
- // The transaction we follow
- Transaction tx;
-
- // The context we manage
- EnterpriseContext ctx;
-
- InstanceSynchronization(Transaction tx)
- {
- this.tx = tx;
- }
-
- public void add(EnterpriseContext ctx)
- {
- this.ctx = ctx;
- }
-
-
- // Synchronization implementation -----------------------------
- public void beforeCompletion()
- {
- try
- {
- try
- {
- // Lock instance
-
((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)
- {
- // Store failed -> rollback!
- try
- {
- tx.setRollbackOnly();
- } catch (SystemException ex)
- {
- ex.printStackTrace();
- }
- }
- }
-
- public void afterCompletion(int status)
- {
- // If rolled back -> invalidate instance
- if (status == Status.STATUS_ROLLEDBACK)
- {
-
- try
- {
-
- 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
- {
-
- // 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)
- {
- // Keep instance cached after tx commit
- case A:
- try
- {
- // The state is still valid
(only point of access is us)
- ((EntityEnterpriseContext)
ctx).setValid(true);
-
- // 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;
-
- }
- }
-
- // Notify all who are waiting for this tx to end
- synchronized (tx)
- {
- tx.notifyAll();
- }
- }
- }
+ // Constants -----------------------------------------------------
+ public static final int TIMEOUT = 10000;
+
+ // Commit time options
+ public static final int A = 0; // Keep instance cached
+ public static final int B = 1; // Invalidate state
+ public static final int C = 2; // Passivate
+
+ // Attributes ----------------------------------------------------
+
+ int commitOption = A;
+
+ protected EntityContainer container;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void setContainer(Container container)
+ {
+ this.container = (EntityContainer)container;
+ }
+
+ public Container getContainer()
+ {
+ return container;
+ }
+
+ public void setCommitOption(int commitOption)
+ {
+ this.commitOption = commitOption;
+ }
+
+ public int getCommitOption()
+ {
+ return commitOption;
+ }
+
+ public void register(EnterpriseContext ctx, Transaction tx)
+ {
+ // Create a new synchronization
+ InstanceSynchronization synch = new InstanceSynchronization(tx);
+
+ try {
+
+ tx.registerSynchronization(synch);
+ }
+ catch (Exception e) {
+
+ throw new EJBException(e);
+ }
+
+ // register
+ synch.add(ctx);
+ }
+
+ public void deregister(EntityEnterpriseContext ctx)
+ {
+ // MF FIXME: I suspect this is redundant now
+ // (won't the pool clean it up?)
+
+ // Deassociate ctx with tx
+ ctx.setTransaction(null);
+ ctx.setInvoked(false);
+ }
+
+ // Interceptor implementation --------------------------------------
+
+ public Object invokeHome(MethodInvocation mi)
+ throws Exception
+ {
+ try
+ {
+ return getNext().invokeHome(mi);
+ } finally
+ {
+ // Anonymous was sent in, so if it has an id it was created
+ EnterpriseContext ctx = mi.getEnterpriseContext();
+ if (ctx.getId() != null)
+ {
+ if (mi.getTransaction() != null &&
+ mi.getTransaction().getStatus() == Status.STATUS_ACTIVE)
+ {
+ // Set tx
+ register(ctx, mi.getTransaction());
+ }
+
+ // Currently synched with underlying storage
+ ((EntityEnterpriseContext)ctx).setValid(true);
+ }
+ }
+ }
+
+ 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();
+
+ //Logger.debug("CTX in: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("newTx: "+ tx);
+
+ // Is my state valid?
+ if (!ctx.isValid()) {
+
+ // If not tell the persistence manager to load the state
+ ((EntityContainer)getContainer()).getPersistenceManager().loadEntity(ctx);
+
+ // 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 {
+
+ // 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 {
+
+ // Entity was removed
+ if (ctx.getTransaction() != null) {
+
+ // Disassociate ctx
+ deregister(ctx);
+ }
+ }
+
+ //Logger.debug("CTX out: isValid():"+ctx.isValid()+"
isInvoked():"+ctx.isInvoked());
+ //Logger.debug("PresentTx:"+tx);
+
+ }
+ }
+
+ else { // No tx
+
+ try
+ {
+ Object result = getNext().invoke(mi);
+
+ // Store after each invocation -- not on exception though, or removal
+ // And skip reads too ("get" methods)
+ if (ctx.getId() != null && !mi.getMethod().getName().startsWith("get"))
+
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
+
+ return result;
+ } catch (Exception e)
+ {
+ // Exception - force reload on next call
+ ctx.setValid(false);
+ throw e;
+ }
+ }
+ }
+
+ // Protected ----------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+ class InstanceSynchronization
+ implements Synchronization
+ {
+ // The transaction we follow
+ Transaction tx;
+
+ // The context we manage
+ EnterpriseContext ctx;
+
+ InstanceSynchronization(Transaction tx)
+ {
+ this.tx = tx;
+ }
+
+ public void add(EnterpriseContext ctx)
+ {
+ this.ctx = ctx;
+ }
+
+
+ // Synchronization implementation -----------------------------
+ public void beforeCompletion()
+ {
+ try
+ {
+ try
+ {
+ // Lock instance
+ ((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)
+ {
+ // Store failed -> rollback!
+ try
+ {
+ tx.setRollbackOnly();
+ } catch (SystemException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public void afterCompletion(int status)
+ {
+ // If rolled back -> invalidate instance
+ if (status == Status.STATUS_ROLLEDBACK)
+ {
+
+ try
+ {
+
+ ctx.setId(null);
+ ctx.setTransaction(null);
+ container.getInstanceCache().remove(ctx.getId());
+ container.getInstancePool().free(ctx); // TODO: should this be done?
still valid instance?
+ } catch (Exception e)
+ {
+ // Ignore
+ }
+ } else
+ {
+
+ // 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)
+ {
+ // Keep instance cached after tx commit
+ case A:
+ try
+ {
+ // The state is still valid (only point of access is us)
+ ((EntityEnterpriseContext) ctx).setValid(true);
+
+ // 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;
+
+ }
+ }
+
+ // Notify all who are waiting for this tx to end
+ synchronized (tx)
+ {
+ tx.notifyAll();
+ }
+ }
+ }
}
1.7 +308 -195
jboss/src/main/org/jboss/ejb/plugins/NoPassivationEntityInstanceCache.java
Index: NoPassivationEntityInstanceCache.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/NoPassivationEntityInstanceCache.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- NoPassivationEntityInstanceCache.java 2000/08/12 00:40:46 1.6
+++ NoPassivationEntityInstanceCache.java 2000/08/17 20:13:14 1.7
@@ -1,17 +1,19 @@
/*
- * jBoss, the OpenSource EJB server
- *
- * Distributable under GPL license.
- * See terms of license at gnu.org.
- */
+* jBoss, the OpenSource EJB server
+*
+* Distributable under GPL license.
+* See terms of license at gnu.org.
+*/
package org.jboss.ejb.plugins;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.Map;
import java.util.HashMap;
-import java.util.Stack;
+import java.util.Stack;
+import java.util.LinkedList;
import java.util.Collections;
+import java.util.Iterator;
import javax.transaction.SystemException;
@@ -23,210 +25,321 @@
import org.jboss.ejb.EntityPersistenceManager;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.EntityEnterpriseContext;
+import org.jboss.util.FastKey;
import org.jboss.metadata.EntityMetaData;
/**
- * <description>
- *
- * @see <related>
- * @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.6 $
- */
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.7 $
+*/
public class NoPassivationEntityInstanceCache
- implements InstanceCache
+implements InstanceCache
{
- // Constants -----------------------------------------------------
+ // Constants -----------------------------------------------------
- // Attributes ----------------------------------------------------
- Container con;
-
- Map active = Collections.synchronizedMap(new HashMap());
- boolean isReentrant;
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
-
- /**
+ // Attributes ----------------------------------------------------
+ Container con;
+
+ Map fastCache = Collections.synchronizedMap(new HashMap());
+ Map fastKeys = Collections.synchronizedMap(new HashMap());
+ boolean isReentrant;
+
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+
+ /**
* Set the callback to the container. This is for initialization.
* The IM may extract the configuration from the container.
*
* @param c
*/
- public void setContainer(Container c)
- {
- this.con = c;
- }
-
- public void init()
- throws Exception
- {
- isReentrant = ((EntityMetaData)con.getBeanMetaData()).isReentrant();
- }
-
- public void start()
- throws Exception
- {
- }
-
- public void stop()
- {
- }
-
- public void destroy()
- {
- }
-
- public synchronized EnterpriseContext get(Object id)
- throws RemoteException
- {
- // TODO: minimize synchronization of IM
-
- EntityEnterpriseContext ctx;
- InstanceInfo info = null;
- while ((ctx = (EntityEnterpriseContext)active.get(id)) != null)
- {
- synchronized(ctx)
- {
- info = (InstanceInfo)ctx.getCacheContext();
- if (!info.isLocked())
- break;
-//DEBUG System.out.println("Cache is waiting for
"+id+"("+info.isLocked()+","+ctx.getTransaction()+")");
-
- // Check if same tx; reentrant call
- try
- {
- if (ctx.getTransaction() != null &&
ctx.getTransaction().equals(con.getTransactionManager().getTransaction()))
- {
- if (isReentrant)
- {
- break;
- } else
- {
- // MF FIXME
- // This is wrong but doing it right requires time
- // The problem is that the entity EJB calls
from an instance
- // come back on the instance and in the presence
of a
- // transaction it throws the exception....
- // Since I suspect most people will use the
EJBObject method calls before they set the reentrant right :)
- // I would rather bypass the default for now.
-
- //throw new RemoteException("Reentrant call
not allowed");
- break;
- }
- }
- } catch (SystemException e)
+ public void setContainer(Container c)
+ {
+ this.con = c;
+ }
+
+ public void init()
+ throws Exception
+ {
+ isReentrant = ((EntityMetaData)con.getBeanMetaData()).isReentrant();
+ }
+
+ public void start()
+ throws Exception
+ {
+ }
+
+ public void stop()
+ {
+ }
+
+ public void destroy()
+ {
+ }
+
+ /**
+ * get(Object fastKey)
+ *
+ * get works from the hack of the fastKey.
+ * The class contains a "fastCache" that hashes fastKeys representing
+ * EJBObjects on client to the context of an instance.
+ * In case the fastKey is not found in fastCache then the method goes on to find
if
+ * it is already loaded but under a different fastKey (I.e. an EJBOBject is
already
+ * working on this instance) in case it does, it adds the new pair fastKey,
instance to the
+ * cache. In case it is not found it creates a new context and associates
fastKey to instance
+ * in the cache. Remove takes care of working from the DB primary Key and
killing
+ * all the associations of fastKey to context. (can be many)
+ * This class relies on the proper implementation of the hash and equals for the
+ * lookup by db key, but is lenient in case something screws up...
+ *
+ * MF FIXME: The synchronization is probably very f*cked up, someone needs to
think
+ * through the use cases of this puppy. I know it is most probably broken as is.
+ */
+
+ public synchronized EnterpriseContext get(Object id)
+ throws RemoteException
+ {
+
+ if (!(id instanceof FastKey)) {
+
+ // That instance should be used by a FastKey already
+ // retrieve the List of Keys for that instance
+ LinkedList keysList = (LinkedList) fastKeys.get(id);
+
+ // Get the context for the first one (they are all associated to that
context)
+ return get((FastKey) keysList.getFirst());
+ }
+
+ // Use the FastKey for the rest of the method
+ FastKey fastKey = (FastKey) id;
+
+ // TODO: minimize synchronization of IM
+
+ EntityEnterpriseContext ctx;
+ InstanceInfo info = null;
+ while ((ctx = (EntityEnterpriseContext)fastCache.get(fastKey)) != null)
+ {
+ synchronized(ctx)
{
- throw new ServerException("Could not check for re-entrancy", e);
+ info = (InstanceInfo)ctx.getCacheContext();
+ if (!info.isLocked())
+ break;
+ //DEBUG System.out.println("Cache is waiting for
"+id+"("+info.isLocked()+","+ctx.getTransaction()+")");
+
+ // Check if same tx; reentrant call
+ try
+ {
+ if (ctx.getTransaction() != null &&
ctx.getTransaction().equals(con.getTransactionManager().getTransaction()))
+ {
+ if (isReentrant)
+ {
+ break;
+ } else
+ {
+ // MF FIXME
+ // This is wrong but doing it right requires time
+ // The problem is that the entity EJB calls from an
instance
+ // come back on the instance and in the presence of a
+ // transaction it throws the exception....
+ // Since I suspect most people will use the EJBObject
method calls before they set the reentrant right :)
+ // I would rather bypass the default for now.
+
+ //throw new RemoteException("Reentrant call not
allowed");
+ break;
+ }
+ }
+ } catch (SystemException e)
+ {
+ throw new ServerException("Could not check for re-entrancy", e);
+ }
+
+
+ // Wait for previous tx to finish
+ try
+ {
+ ctx.wait(5000);
+ } catch (InterruptedException e)
+ {
+ // Someone else is using this id right now
+ throw new ServerException("Time out",e);
+ }
}
-
+ }
+
+ if (ctx == null) // Not in fast cache under that fastKey
+ {
+ //Maybe it is in the cache but under another fastKey, check for the DB
id
+ if (fastKeys.containsKey(fastKey.id)) {
+
+ // Ok, the instance is in fastCache but under another fastKey
+
+ // retrieve the List of Keys for that instance
+ LinkedList keysList = (LinkedList) fastKeys.get(fastKey.id);
+
+ // Get the context for the first one (they are all associated to
that context)
+ ctx = (EntityEnterpriseContext) fastCache.get(keysList.getFirst());
+
+ // Add the fastkey to the List
+ keysList.addLast(fastKey);
+
+ // MF FIXME: I don't think we need this operation but just in case
+ fastKeys.put(fastKey.id, keysList);
+
+ // Store the context in the fastCache
+ fastCache.put(fastKey, ctx);
+
+ // Redo the call the previous cache will work the synchronization
+ return get(fastKey);
+ }
- // Wait for previous tx to finish
- try
- {
- ctx.wait(5000);
- } catch (InterruptedException e)
- {
- // Someone else is using this id right now
- throw new ServerException("Time out",e);
+ // The instance is brand new and not know to the cache structures
+ else {
+
+ // Get new instance from pool
+ ctx =
(EntityEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
+
+ // The context only knows about the Database id
+ ctx.setId(fastKey.id);
+
+ // Activate it
+ ((EntityContainer)con).getPersistenceManager().activateEntity(ctx);
+
+ // Initiate the fastKeys List for this Id
+ //LinkedList keysList = (LinkedList)
Collections.synchronizedList(new LinkedList());
+ LinkedList keysList = new LinkedList();
+
+ // Add this fastKey at least
+ keysList.addLast(fastKey);
+
+ // Keep the list under the DB ID
+ fastKeys.put(fastKey.id, keysList);
+
+ // implicit passing with the ctx
+ ctx.setFastKey(fastKey);
+
+ // insert
+ insert(ctx);
}
- }
- }
-
- if (ctx == null) // Not in cache
- {
- // Get new instance from pool
- ctx =
(EntityEnterpriseContext)((InstancePoolContainer)con).getInstancePool().get();
-
- // Activate
- ctx.setId(id);
- ((EntityContainer)con).getPersistenceManager().activateEntity(ctx);
- insert(ctx);
- } else
- {
- // Lock the instance
- info.lock();
- }
-
- // At this point we own the instance with the given identity
-// System.out.println("Got entity:"+ctx.getId());
- return ctx;
- }
-
- public synchronized void insert(EnterpriseContext ctx)
- {
- InstanceInfo info = createInstanceInfo(ctx);
- ((EntityEnterpriseContext)ctx).setCacheContext(info);
- info.lock();
- active.put(ctx.getId(), ctx);
- }
-
- public void release(EnterpriseContext ctx)
- {
- // This context is now available for other threads
- synchronized(ctx)
- {
- ((InstanceInfo)((EntityEnterpriseContext)ctx).getCacheContext()).unlock();
-// System.out.println("Release entity:"+ctx.getId());
- if
(!((InstanceInfo)((EntityEnterpriseContext)ctx).getCacheContext()).isLocked())
+ } else
+ {
+ // Lock the instance
+ info.lock();
+ }
+
+ // At this point we own the instance with the given identity
+ // System.out.println("Got entity:"+ctx.getId());
+ return ctx;
+ }
+
+ public synchronized void insert( EnterpriseContext ctx)
+ {
+ InstanceInfo info = createInstanceInfo(ctx);
+ ((EntityEnterpriseContext)ctx).setCacheContext(info);
+ info.lock();
+
+ // Cache can know about the instance now
+ fastCache.put(((EntityEnterpriseContext)ctx).getFastKey(), ctx);
+
+ }
+
+ public void release(EnterpriseContext ctx)
+ {
+ // This context is now available for other threads
+ synchronized(ctx)
+ {
+
((InstanceInfo)((EntityEnterpriseContext)ctx).getCacheContext()).unlock();
+ // System.out.println("Release entity:"+ctx.getId());
+ if
(!((InstanceInfo)((EntityEnterpriseContext)ctx).getCacheContext()).isLocked())
+ ctx.notifyAll();
+ }
+ }
+
+ /*
+ * unfortunately a f*cked up hash and equals will create leaks in
+ * the maps :(((((
+ *
+ * Actually that may be one way to diagnose bad behaviour of the stuff
+ * (I guess, MF)
+ */
+ public synchronized void remove(Object id)
+ {
+ // remote the List of keys from the ID map, it returns the list
+ LinkedList list = (LinkedList) fastKeys.remove(id);
+
+ // If the fastKey wasn't used there is no link to a context
+ if (list == null) return ;
+
+ Iterator keysIterator = list.listIterator();
+
+ // We need to remove all the associations that exists with the context
+ Object ctx = null;
+
+ while (keysIterator.hasNext()) {
+
+ Object currentFastKey = keysIterator.next();
+
+ // remove the fastKey from fastCache
+ ctx = fastCache.remove(currentFastKey);
+ }
+
+
+ // We will need notification (MF FIXME actually not anymore imho)
+ synchronized(ctx)
+ {
ctx.notifyAll();
- }
- }
-
- public synchronized void remove(Object id)
- {
- Object ctx = active.remove(id);
- synchronized(ctx)
- {
- ctx.notifyAll();
- }
- }
-
- // Z implementation ----------------------------------------------
-
- // Package protected ---------------------------------------------
-
- // Protected -----------------------------------------------------
- protected InstanceInfo createInstanceInfo(EnterpriseContext ctx)
- {
- return new InstanceInfo(ctx);
- }
-
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
- class InstanceInfo
- {
- int locked = 0; // 0 == unlocked, >0 == locked
-
- EntityEnterpriseContext ctx;
-
- InstanceInfo(EnterpriseContext ctx)
- {
- this.ctx = (EntityEnterpriseContext)ctx;
- }
-
- public void lock()
- {
- locked++;
- }
-
- public void unlock()
- {
- locked--;
- }
-
- public boolean isLocked()
- {
- return locked > 0;
- }
-
- public EntityEnterpriseContext getContext()
- {
- return ctx;
- }
- }
+ }
+ }
+
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+ protected InstanceInfo createInstanceInfo(EnterpriseContext ctx)
+ {
+ return new InstanceInfo(ctx);
+ }
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+ class InstanceInfo
+ {
+ int locked = 0; // 0 == unlocked, >0 == locked
+
+ EntityEnterpriseContext ctx;
+
+ InstanceInfo(EnterpriseContext ctx)
+ {
+ this.ctx = (EntityEnterpriseContext)ctx;
+ }
+
+ public void lock()
+ {
+ locked++;
+ }
+
+ public void unlock()
+ {
+ locked--;
+ }
+
+ public boolean isLocked()
+ {
+ return locked > 0;
+ }
+
+ public EntityEnterpriseContext getContext()
+ {
+ return ctx;
+ }
+ }
}
1.3 +126 -103
jboss/src/main/org/jboss/ejb/plugins/RandomEntityInstanceCache.java
Index: RandomEntityInstanceCache.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/RandomEntityInstanceCache.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- RandomEntityInstanceCache.java 2000/06/16 13:10:23 1.2
+++ RandomEntityInstanceCache.java 2000/08/17 20:13:14 1.3
@@ -1,9 +1,9 @@
/*
- * jBoss, the OpenSource EJB server
- *
- * Distributable under GPL license.
- * See terms of license at gnu.org.
- */
+* jBoss, the OpenSource EJB server
+*
+* Distributable under GPL license.
+* See terms of license at gnu.org.
+*/
package org.jboss.ejb.plugins;
import java.rmi.RemoteException;
@@ -11,6 +11,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.HashMap;
+import java.util.LinkedList;
import org.jboss.ejb.Container;
import org.jboss.ejb.EntityContainer;
@@ -23,113 +24,135 @@
import org.jboss.logging.Logger;
/**
- * <description>
- *
- * @see <related>
- * @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.2 $
- */
+* <description>
+*
+* @see <related>
+* @author Rickard �berg ([EMAIL PROTECTED])
+* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+* @version $Revision: 1.3 $
+*/
public class RandomEntityInstanceCache
- extends NoPassivationEntityInstanceCache
+extends NoPassivationEntityInstanceCache
{
- // Constants -----------------------------------------------------
+ // Constants -----------------------------------------------------
- // Attributes ----------------------------------------------------
- boolean running = false; // Passivator thread running?
-
- int minActive = 100; // Always try to passivate if more than this nr are active
-
- long timeout = 60*1000L; // Passivation sweep sleep time
-
- // Static --------------------------------------------------------
-
- // Constructors --------------------------------------------------
-
- // Public --------------------------------------------------------
- public void start()
- throws Exception
- {
- running = true;
- new Thread(new Passivator()).start();
- }
-
- public void stop()
- {
- running = false;
- }
-
- // Z implementation ----------------------------------------------
+ // Attributes ----------------------------------------------------
+ boolean running = false; // Passivator thread running?
- // Package protected ---------------------------------------------
+ int minActive = 100; // Always try to passivate if more than this nr are active
- // Protected -----------------------------------------------------
+ long timeout = 60*1000L; // Passivation sweep sleep time
- // Private -------------------------------------------------------
-
- // Inner classes -------------------------------------------------
- class Passivator
- implements Runnable
- {
- RandomEntityInstanceCache cache;
-
- public void run()
- {
- Logger.debug("Passivator started");
- // Passivation loop
- while(running)
- {
-// System.out.println("Clearing cache");
- // Passivate old. Lock cache first
- synchronized(RandomEntityInstanceCache.this)
+ // Static --------------------------------------------------------
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+ public void start()
+ throws Exception
+ {
+ running = true;
+ new Thread(new Passivator()).start();
+ }
+
+ public void stop()
+ {
+ running = false;
+ }
+
+ // Z implementation ----------------------------------------------
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+ class Passivator
+ implements Runnable
+ {
+ RandomEntityInstanceCache cache;
+
+ public void run()
+ {
+ Logger.debug("Passivator started");
+ // Passivation loop
+ while(running)
{
- int currentActive = active.size();
- if (currentActive > minActive)
- {
- InstancePool pool = ((EntityContainer)con).getInstancePool();
-
- Logger.debug("Too many active instances:"+currentActive);
- // Passivate some instance; they need to be unlocked though
- Collection values = active.values();
- Iterator enum = values.iterator();
- while(enum.hasNext())
- {
- EntityEnterpriseContext ctx =
(EntityEnterpriseContext)enum.next();
- Logger.debug("Checking:"+ctx.getId());
- InstanceInfo info = (InstanceInfo)ctx.getCacheContext();
- if (!info.isLocked())
- {
- // Passivate
+ // System.out.println("Clearing cache");
+ // Passivate old. Lock cache first
+ synchronized(RandomEntityInstanceCache.this)
+ {
+ // Do not use cache (many to one entries)
+ int currentActive = fastKeys.size();
+ if (currentActive > minActive)
+ {
+ InstancePool pool =
((EntityContainer)con).getInstancePool();
+
+ Logger.debug("Too many active instances:"+currentActive);
+
+ // Passivate some instance; they need to be unlocked though
+
+ Iterator ids = fastKeys.keySet().iterator();
+
+ while(ids.hasNext())
+ {
+
+ Object id = ids.next();
+
+ //Get the context
+ EntityEnterpriseContext ctx =
+ (EntityEnterpriseContext)fastCache.get(((LinkedList)
fastKeys.get(id)).getFirst());
+
+
+ // Make sure we can work on it
+ Logger.debug("Checking:"+ctx.getId());
+ InstanceInfo info = (InstanceInfo)ctx.getCacheContext();
+
+ //We we locked?
+ if (!info.isLocked())
+ {
+ // Nope then Passivate
+ try
+ {
+ Logger.debug("Passivating:"+ctx.getId());
+
((EntityContainer)con).getPersistenceManager().passivateEntity(ctx);
+
+
+ // Get the List by removing from fastKeys
+ LinkedList keysList = (LinkedList)
fastKeys.remove(ids.next());
+
+ // Remove all the fastKeys from the cache
+ Iterator iterator = keysList.listIterator();
+
+ while (iterator.hasNext()) {
+
+ fastCache.remove(iterator.next());
+ }
+
+ currentActive--;
+ }
+
+ catch (Exception e) { Logger.log("Could not
passivate instance");}
+ }
+
+ if (currentActive == minActive) break;
+
+ }
+
+ // System.out.println("Passivation done");
+ // Sleep
try
{
- Logger.debug("Passivating:"+ctx.getId());
-
((EntityContainer)con).getPersistenceManager().passivateEntity(ctx);
- enum.remove();
- RandomEntityInstanceCache.this.notifyAll(); //
Necessary? (I think so!)
- pool.free(ctx);
- } catch (RemoteException e)
+ Thread.sleep(timeout);
+ } catch (InterruptedException e)
{
- e.printStackTrace(); // TODO: log this
+ // Ignore
}
-
- // Check if enough are passivated
- currentActive--;
- if (currentActive == minActive)
- break;
- }
- }
- }
- }
-
-// System.out.println("Passivation done");
- // Sleep
- try
- {
- Thread.sleep(timeout);
- } catch (InterruptedException e)
- {
- // Ignore
+ }
+ }
}
- }
- }
- }
-}
+ }
+ }
+}
\ No newline at end of file