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
  
  
  

Reply via email to