User: fleury  
  Date: 00/10/21 14:32:10

  Modified:    src/main/org/jboss/ejb/plugins
                        EntitySynchronizationInterceptor.java
                        EntityInstanceInterceptor.java
                        AbstractInstancePool.java
  Log:
  fix for lock on home exception... the pools notifyAll on free
  
  Revision  Changes    Path
  1.27      +384 -384  
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.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- EntitySynchronizationInterceptor.java     2000/10/17 23:47:02     1.26
  +++ EntitySynchronizationInterceptor.java     2000/10/21 21:32:09     1.27
  @@ -48,393 +48,393 @@
   *   @see <related>
   *   @author Rickard �berg ([EMAIL PROTECTED])
   *   @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
  -*   @version $Revision: 1.26 $
  +*   @version $Revision: 1.27 $
   */
   public class EntitySynchronizationInterceptor
   extends AbstractInterceptor
   {
  -     // Constants -----------------------------------------------------
  -     
  -     // Attributes ----------------------------------------------------
  -     
  -     /**
  -     *  The current commit option.
  -     */
  -     protected int commitOption;
  -     
  -     /**
  -     *  The container of this interceptor.
  -     */
  -     protected EntityContainer container;
  -     
  -     /**
  -     *  Optional isModified method
  -     */
  -     protected Method isModified;
  -     
  -     // Static --------------------------------------------------------
  -     
  -     // Constructors --------------------------------------------------
  -     
  -     // Public --------------------------------------------------------
  -     public void setContainer(Container container) 
  -     { 
  -             this.container = (EntityContainer)container; 
  -     }
  -     
  -     public void init()
  -     throws Exception
  -     {
  -             commitOption = 
container.getBeanMetaData().getContainerConfiguration().getCommitOption();
  -             // Check for isModified method
  -             try
  -             {
  -                     isModified = container.getBeanClass().getMethod("isModified", 
new Class[0]);
  -                     if (!isModified.getReturnType().equals(Boolean.TYPE))
  -                             isModified = null; // Has to have "boolean" as return 
type!
  -             } catch (Exception e)
  -             {
  -                     // Ignore
  -             }
  -     }
  -     
  -     public Container getContainer()
  -     {
  -             return container;
  -     }
  -     
  -     /**
  -     *  Register a transaction synchronization callback with a context.
  -     */
  -     private void register(EntityEnterpriseContext ctx, Transaction tx)
  -     {
  -             // Create a new synchronization
  -             InstanceSynchronization synch = new InstanceSynchronization(tx, ctx);
  -             
  -             try {
  -                     // OSH: An extra check to avoid warning.
  -                     // Can go when we are sure that we no longer get
  -                     // the JTA violation warning.
  -                     if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
  -                             
  -                             ctx.setValid(false);
  -                             
  -                             return;
  -                     }
  -                     
  -                     // We want to be notified when the transaction commits
  -                     tx.registerSynchronization(synch);
  -             
  -             } catch (RollbackException e) {
  -                     
  -                     // The state in the instance is to be discarded, we force a 
reload of state
  -                     ctx.setValid(false);
  -             
  -             } catch (Exception e) {
  -                     
  -                     throw new EJBException(e);
  -             
  -             }
  -     }
  -     
  -     private void deregister(EntityEnterpriseContext ctx)
  -     {
  -             // MF FIXME: I suspect this is redundant now
  -             // (won't the pool clean it up?)
  -             
  -             // Deassociate ctx with tx
  -             // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
  -             // OSH: Pool seems to do this: 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
  -                     EntityEnterpriseContext ctx = 
(EntityEnterpriseContext)mi.getEnterpriseContext();
  -                     if (ctx.getId() != null) {
  -                             Transaction tx = mi.getTransaction();
  -                             
  -                             if (tx != null && tx.getStatus() == 
Status.STATUS_ACTIVE)
  -                                     register(ctx, tx); // Set tx
  -                             
  -                             // Currently synched with underlying storage
  -                             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
  -             //DEBUG         Logger.debug("Tx is "+ ((tx == null)? "null" : 
tx.toString()));
  -             
  -             // Invocation with a running Transaction
  -             
  -             if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
  -                     
  -                     try {
  -                             
  -                             //Invoke down the chain
  -                             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);
  -                                     }
  -                             }
  -                             
  -                             // Entity was removed
  -                             else {
  -                                     
  -                                     if (ctx.getTransaction() != null) {
  -                                             
  -                                             //DEBUG Logger.debug("CTX out: 
isValid():"+ctx.isValid()+" isInvoked():"+ctx.isInvoked());
  -                                             //DEBUG Logger.debug("PresentTx:"+tx);
  -                                             
  -                                             // If a ctx still has a transaction we 
would need to deresgister the sync
  -                                             // The simplest is to tell the pool to 
kill the instance if tx is present
  -                                     
  -                                     }
  -                             }
  -                     }
  -             }
  -             
  -             //    
  -             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)
  -                             // OSH FIXME: Isn't this startsWith("get") 
optimization a violation of
  -                             // the EJB specification? Think of 
SequenceBean.getNext().
  -                             if (ctx.getId() != null)
  -                             {
  -                                     boolean dirty = true;
  -                                     // Check isModified bean flag
  -                                     if (isModified != null)
  -                                     {
  -                                             dirty = 
((Boolean)isModified.invoke(ctx.getInstance(), new Object[0])).booleanValue();
  -                                     }
  -                                     
  -                                     // Store entity
  -                                     if (dirty)
  -                                             
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
  -                             }
  -                             
  -                             return result;
  -                     } catch (Exception e) {
  -                             // Exception - force reload on next call
  -                             ctx.setValid(false);
  -                             throw e;
  -                     }
  -             }
  -     }
  -     
  -     
  -     // Protected  ----------------------------------------------------
  -     
  -     // Inner classes -------------------------------------------------
  -     
  -     private class InstanceSynchronization
  -     implements Synchronization
  -     {
  -             /**
  -             *  The transaction we follow.
  -             */
  -             private Transaction tx;
  -             
  -             /**
  -             *  The context we manage.
  -             */
  -             private EntityEnterpriseContext ctx;
  -             
  -             /**
  -             *  Create a new instance synchronization instance.
  -             */
  -             InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
  -             {
  -                     this.tx = tx;
  -                     this.ctx = ctx;
  -             }
  -             
  -             // Synchronization implementation -----------------------------
  -             
  -             public void beforeCompletion()
  -             {
  -                     // DEBUG Logger.debug("beforeCompletion called for ctx 
"+ctx.hashCode());
  -                     
  -                     if (ctx.getId() != null) {
  -                             
  -                             // This is an independent point of entry. We need to 
make sure the 
  -                             // thread is associated with the right context class 
loader
  -                             ClassLoader oldCl = 
Thread.currentThread().getContextClassLoader();
  -                             
Thread.currentThread().setContextClassLoader(container.getClassLoader());
  -                             
  -                             try {
  -                                     
  -                                     try {
  -                                             
  -                                             // MF FIXME: should we throw an 
exception if lock is present (app error)
  -                                             // it would mean that someone is 
commiting when all the work is not done
  -                                             
  -                                             // Store instance if business method 
was invoked
  -                                             if (ctx.isInvoked()) {
  -                                                     
  -                                                     //DEBUG 
Logger.debug("EntitySynchronization sync calling store on ctx "+ctx.hashCode());
  -                                                     
  -                                                     // Check isModified bean flag
  -                                                     boolean dirty = true;
  -                                                     if (isModified != null)
  -                                                     {
  -                                                             try
  -                                                             {
  -                                                                     dirty = 
((Boolean)isModified.invoke(ctx.getInstance(), new Object[0])).booleanValue();
  -                                                             } catch (Exception e)
  -                                                             {
  -                                                                     // Ignore
  -                                                                     
e.printStackTrace();
  -                                                             }
  -                                                     }
  -                                                     
  -                                                     if (dirty)
  -                                                             
container.getPersistenceManager().storeEntity(ctx);
  -                                             }
  -                                     } catch (NoSuchEntityException e) {
  -                                             // Object has been removed -- ignore
  -                                     }
  -                             }
  -                             catch (RemoteException e) {
  -                                     Logger.exception(e);
  -                                     
  -                                     // Store failed -> rollback!
  -                                     try {
  -                                             tx.setRollbackOnly();
  -                                     } catch (SystemException ex) {
  -                                             // DEBUG ex.printStackTrace();
  -                                     } catch (IllegalStateException ex) {
  -                                             // DEBUG ex.printStackTrace();
  -                                     }
  -                             }
  -                             finally {
  -                                     
  -                                     
Thread.currentThread().setContextClassLoader(oldCl);
  -                             }
  -                     }
  -             }
  -             
  -             
  -             public void afterCompletion(int status)
  -             {
  -                     
  -                     // This is an independent point of entry. We need to make sure 
the 
  -                     // thread is associated with the right context class loader
  -                     ClassLoader oldCl = 
Thread.currentThread().getContextClassLoader();
  -                     
Thread.currentThread().setContextClassLoader(container.getClassLoader());
  -                     
  -                     try 
  -                     {
  -                             
  -                             //DEBUG Logger.debug("afterCompletion called for ctx 
"+ctx.hashCode());
  -                             
  -                             // If rolled back -> invalidate instance
  -                             // If removed -> send back to the pool
  -                             if (status == Status.STATUS_ROLLEDBACK || ctx.getId() 
== null) { 
  -                                     
  -                                     try { 
  -                                             
  -                                             // finish the transaction association
  -                                             ctx.setTransaction(null);
  -                                             
  -                                             // remove from the cache
  -                                             
container.getInstanceCache().remove(ctx.getCacheKey());
  -                                             
  -                                             // return to pool
  -                                             container.getInstancePool().free(ctx); 
  -                                     
  -                                     } catch (Exception e) {
  -                                             // Ignore
  -                                     }
  -                                     
  -                             } else { 
  -                                             
  -                                     // We are afterCompletion so the invoked can 
be set to false (db sync is done)
  -                                     ctx.setInvoked(false);
  -                                             
  -                                     switch (commitOption) { 
  -                                             // Keep instance cached after tx commit
  -                                             case 
ConfigurationMetaData.A_COMMIT_OPTION:
  -                                                     // The state is still valid 
(only point of access is us)
  -                                                     ctx.setValid(true); 
  -                                             break;
  -                                                     
  -                                             // Keep instance active, but 
invalidate state
  -                                             case 
ConfigurationMetaData.B_COMMIT_OPTION:
  -                                                     // Invalidate state (there 
might be other points of entry)
  -                                                     ctx.setValid(false); 
  -                                             break;
  -                                                     
  -                                             // Invalidate everything AND Passivate 
instance
  -                                             case 
ConfigurationMetaData.C_COMMIT_OPTION:
  -                                                     try { 
  -                                                             
container.getInstanceCache().release(ctx);      
  -                                                     } catch (Exception e) { 
  -                                                             Logger.debug(e);
  -                                                     }
  -                                             break;
  -                                     }
  -                                     
  -                                     // finish the transaction association
  -                                     ctx.setTransaction(null);
  -                             }
  -                     }
  -                     
  -                     finally { 
  -                             
  -                             Thread.currentThread().setContextClassLoader(oldCl);
  -                             
  -                             // Notify all who are waiting for this tx to end, they 
are waiting since the locking logic
  -                             synchronized (ctx) {ctx.notifyAll();}
  -                     }
  -             }
  -     }
  +    // Constants -----------------------------------------------------
  +    
  +    // Attributes ----------------------------------------------------
  +    
  +    /**
  +    *  The current commit option.
  +    */
  +    protected int commitOption;
  +    
  +    /**
  +    *  The container of this interceptor.
  +    */
  +    protected EntityContainer container;
  +    
  +    /**
  +    *  Optional isModified method
  +    */
  +    protected Method isModified;
  +    
  +    // Static --------------------------------------------------------
  +    
  +    // Constructors --------------------------------------------------
  +    
  +    // Public --------------------------------------------------------
  +    public void setContainer(Container container) 
  +    { 
  +       this.container = (EntityContainer)container; 
  +    }
  +    
  +    public void init()
  +    throws Exception
  +    {
  +       commitOption = 
container.getBeanMetaData().getContainerConfiguration().getCommitOption();
  +       // Check for isModified method
  +       try
  +       {
  +         isModified = container.getBeanClass().getMethod("isModified", new 
Class[0]);
  +         if (!isModified.getReturnType().equals(Boolean.TYPE))
  +          isModified = null; // Has to have "boolean" as return type!
  +       } catch (Exception e)
  +       {
  +         // Ignore
  +       }
  +    }
  +    
  +    public Container getContainer()
  +    {
  +       return container;
  +    }
  +    
  +    /**
  +    *  Register a transaction synchronization callback with a context.
  +    */
  +    private void register(EntityEnterpriseContext ctx, Transaction tx)
  +    {
  +       // Create a new synchronization
  +       InstanceSynchronization synch = new InstanceSynchronization(tx, ctx);
  +       
  +       try {
  +         // OSH: An extra check to avoid warning.
  +         // Can go when we are sure that we no longer get
  +         // the JTA violation warning.
  +         if (tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) {
  +          
  +          ctx.setValid(false);
  +          
  +          return;
  +         }
  +         
  +         // We want to be notified when the transaction commits
  +         tx.registerSynchronization(synch);
  +       
  +       } catch (RollbackException e) {
  +         
  +         // The state in the instance is to be discarded, we force a reload of state
  +         ctx.setValid(false);
  +       
  +       } catch (Exception e) {
  +         
  +         throw new EJBException(e);
  +       
  +       }
  +    }
  +    
  +    private void deregister(EntityEnterpriseContext ctx)
  +    {
  +       // MF FIXME: I suspect this is redundant now
  +       // (won't the pool clean it up?)
  +       
  +       // Deassociate ctx with tx
  +       // OSH: TxInterceptor seems to do this: ctx.setTransaction(null);
  +       // OSH: Pool seems to do this: 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
  +         EntityEnterpriseContext ctx = 
(EntityEnterpriseContext)mi.getEnterpriseContext();
  +         if (ctx.getId() != null) {
  +          Transaction tx = mi.getTransaction();
  +          
  +          if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE)
  +              register(ctx, tx); // Set tx
  +          
  +          // Currently synched with underlying storage
  +          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
  +       //DEBUG               Logger.debug("Tx is "+ ((tx == null)? "null" : 
tx.toString()));
  +       
  +       // Invocation with a running Transaction
  +       
  +       if (tx != null && tx.getStatus() == Status.STATUS_ACTIVE) {
  +         
  +         try {
  +          
  +          //Invoke down the chain
  +          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);
  +              }
  +          }
  +          
  +          // Entity was removed
  +          else {
  +              
  +              if (ctx.getTransaction() != null) {
  +                 
  +                 //DEBUG Logger.debug("CTX out: isValid():"+ctx.isValid()+" 
isInvoked():"+ctx.isInvoked());
  +                 //DEBUG Logger.debug("PresentTx:"+tx);
  +                 
  +                 // If a ctx still has a transaction we would need to deresgister 
the sync
  +                 // The simplest is to tell the pool to kill the instance if tx is 
present
  +              
  +              }
  +          }
  +         }
  +       }
  +       
  +       //    
  +       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)
  +          // OSH FIXME: Isn't this startsWith("get") optimization a violation of
  +          // the EJB specification? Think of SequenceBean.getNext().
  +          if (ctx.getId() != null)
  +          {
  +              boolean dirty = true;
  +              // Check isModified bean flag
  +              if (isModified != null)
  +              {
  +                 dirty = ((Boolean)isModified.invoke(ctx.getInstance(), new 
Object[0])).booleanValue();
  +              }
  +              
  +              // Store entity
  +              if (dirty)
  +                 
((EntityContainer)getContainer()).getPersistenceManager().storeEntity(ctx);
  +          }
  +          
  +          return result;
  +         } catch (Exception e) {
  +          // Exception - force reload on next call
  +          ctx.setValid(false);
  +          throw e;
  +         }
  +       }
  +    }
  +    
  +    
  +    // Protected  ----------------------------------------------------
  +    
  +    // Inner classes -------------------------------------------------
  +    
  +    private class InstanceSynchronization
  +    implements Synchronization
  +    {
  +       /**
  +       *  The transaction we follow.
  +       */
  +       private Transaction tx;
  +       
  +       /**
  +       *  The context we manage.
  +       */
  +       private EntityEnterpriseContext ctx;
  +       
  +       /**
  +       *  Create a new instance synchronization instance.
  +       */
  +       InstanceSynchronization(Transaction tx, EntityEnterpriseContext ctx)
  +       {
  +         this.tx = tx;
  +         this.ctx = ctx;
  +       }
  +       
  +       // Synchronization implementation -----------------------------
  +       
  +       public void beforeCompletion()
  +       {
  +         // DEBUG Logger.debug("beforeCompletion called for ctx "+ctx.hashCode());
  +         
  +         if (ctx.getId() != null) {
  +          
  +          // This is an independent point of entry. We need to make sure the 
  +          // thread is associated with the right context class loader
  +          ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
  +          Thread.currentThread().setContextClassLoader(container.getClassLoader());
  +          
  +          try {
  +              
  +              try {
  +                 
  +                 // MF FIXME: should we throw an exception if lock is present (app 
error)
  +                 // it would mean that someone is commiting when all the work is 
not done
  +                 
  +                 // Store instance if business method was invoked
  +                 if (ctx.isInvoked()) {
  +                   
  +                   //DEBUG Logger.debug("EntitySynchronization sync calling store 
on ctx "+ctx.hashCode());
  +                   
  +                   // Check isModified bean flag
  +                   boolean dirty = true;
  +                   if (isModified != null)
  +                   {
  +                    try
  +                    {
  +                        dirty = ((Boolean)isModified.invoke(ctx.getInstance(), new 
Object[0])).booleanValue();
  +                    } catch (Exception e)
  +                    {
  +                        // Ignore
  +                        e.printStackTrace();
  +                    }
  +                   }
  +                   
  +                   if (dirty)
  +                    container.getPersistenceManager().storeEntity(ctx);
  +                 }
  +              } catch (NoSuchEntityException e) {
  +                 // Object has been removed -- ignore
  +              }
  +          }
  +          catch (RemoteException e) {
  +              Logger.exception(e);
  +              
  +              // Store failed -> rollback!
  +              try {
  +                 tx.setRollbackOnly();
  +              } catch (SystemException ex) {
  +                 // DEBUG ex.printStackTrace();
  +              } catch (IllegalStateException ex) {
  +                 // DEBUG ex.printStackTrace();
  +              }
  +          }
  +          finally {
  +              
  +              Thread.currentThread().setContextClassLoader(oldCl);
  +          }
  +         }
  +       }
  +       
  +       
  +       public void afterCompletion(int status)
  +       {
  +         
  +         // This is an independent point of entry. We need to make sure the 
  +         // thread is associated with the right context class loader
  +         ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
  +         Thread.currentThread().setContextClassLoader(container.getClassLoader());
  +         
  +         try 
  +         {
  +          
  +          //DEBUG Logger.debug("afterCompletion called for ctx "+ctx.hashCode());
  +          
  +          // If rolled back -> invalidate instance
  +          // If removed -> send back to the pool
  +          if (status == Status.STATUS_ROLLEDBACK || ctx.getId() == null) { 
  +              
  +              try { 
  +                 
  +                 // finish the transaction association
  +                 ctx.setTransaction(null);
  +                 
  +                 // remove from the cache
  +                 container.getInstanceCache().remove(ctx.getCacheKey());
  +                 
  +                 // return to pool
  +                 container.getInstancePool().free(ctx); 
  +              
  +              } catch (Exception e) {
  +                 // Ignore
  +              }
  +              
  +          } else { 
  +                 
  +              // We are afterCompletion so the invoked can be set to false (db sync 
is done)
  +              ctx.setInvoked(false);
  +                 
  +              switch (commitOption) { 
  +                 // Keep instance cached after tx commit
  +                 case ConfigurationMetaData.A_COMMIT_OPTION:
  +                   // The state is still valid (only point of access is us)
  +                   ctx.setValid(true); 
  +                 break;
  +                   
  +                 // Keep instance active, but invalidate state
  +                 case ConfigurationMetaData.B_COMMIT_OPTION:
  +                   // Invalidate state (there might be other points of entry)
  +                   ctx.setValid(false); 
  +                 break;
  +                   
  +                 // Invalidate everything AND Passivate instance
  +                 case ConfigurationMetaData.C_COMMIT_OPTION:
  +                   try { 
  +                    container.getInstanceCache().release(ctx);       
  +                   } catch (Exception e) { 
  +                    Logger.debug(e);
  +                   }
  +                 break;
  +              }
  +              
  +              // finish the transaction association
  +              ctx.setTransaction(null);
  +          }
  +         }
  +         
  +         finally { 
  +          
  +          Thread.currentThread().setContextClassLoader(oldCl);
  +          
  +                // Notify next waiting for this tx to end, they are waiting since 
the locking logic
  +                synchronized (ctx) {ctx.notify();}
  +         }
  +       }
  +    }
   }
   
  
  
  
  1.23      +30 -16    
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.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- EntityInstanceInterceptor.java    2000/10/20 03:11:43     1.22
  +++ EntityInstanceInterceptor.java    2000/10/21 21:32:10     1.23
  @@ -44,7 +44,7 @@
   *   @author Rickard �berg ([EMAIL PROTECTED])
   *   @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
   *   @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
  -*   @version $Revision: 1.22 $
  +*   @version $Revision: 1.23 $
   */
   public class EntityInstanceInterceptor
   extends AbstractInterceptor
  @@ -89,18 +89,22 @@
               // Always unlock, no matter what
               ctx.unlock();
               
  -            // Still free? Not free if create() was called successfully
  -            if (ctx.getId() == null)
  -            {
  -                container.getInstancePool().free(ctx);
  -            } 
  -            else
  -            {
  -                // DEBUG           Logger.debug("Entity was created; not returned 
to pool");
  -                synchronized (ctx) {
  +            synchronized (ctx) {
  +                
  +                // Still free? Not free if create() was called successfully
  +                if (ctx.getId() == null)
  +                {
  +                    container.getInstancePool().free(ctx);
  +                
  +                    // the pool will notify all everyone
  +                } 
  +                else
  +                {
  +                    // DEBUG           Logger.debug("Entity was created; not 
returned to pool");
                       
  -                    //Let the waiters know
  -                    ctx.notifyAll();
  +                    //Let one waiter know
  +                    ctx.notify();
  +                    
                   }
               }
           }
  @@ -146,7 +150,7 @@
                           Logger.debug("LOCKING-WAITING (TRANSACTION) for id 
"+ctx.getId()+" ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" : 
tx.toString()));
                           
                           try {
  -                            ctx.wait();
  +                            ctx.wait(5000);
                           } catch (InterruptedException ie) {}
                           
                           // Try your luck again
  @@ -173,7 +177,7 @@
                                   Logger.debug("LOCKING-WAITING (CTX) for id 
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
                                   
                                   try{
  -                                    ctx.wait();
  +                                    ctx.wait(5000);
                                   } catch (InterruptedException ie) {}
                                   
                                   // Try your luck again
  @@ -240,11 +244,21 @@
                           
                           // It has been removed -> send to the pool
                           container.getInstancePool().free(ctx);
  +                        
  +                        // The pool will notify everyone waiting on this
  +                        
                       }
                   }
                   
  -                // notify the thread waiting on ctx
  -                synchronized (ctx) { ctx.notifyAll();}
  +                else {
  +                 
  +                    // MF FIXME for speed reason I use notify
  +                    // however we would need to lock on the tx and ctx so we can 
  +                    // notify the right population, slightly more complicated...
  +                    
  +                    // notify the next thread waiting on ctx
  +                    synchronized (ctx) { ctx.notify();}
  +                }
               }
           }
       }
  
  
  
  1.7       +15 -12    jboss/src/main/org/jboss/ejb/plugins/AbstractInstancePool.java
  
  Index: AbstractInstancePool.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/AbstractInstancePool.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- AbstractInstancePool.java 2000/10/09 20:15:36     1.6
  +++ AbstractInstancePool.java 2000/10/21 21:32:10     1.7
  @@ -31,7 +31,7 @@
    *      
    *   @see <related>
    *   @author Rickard �berg ([EMAIL PROTECTED])
  - *   @version $Revision: 1.6 $
  + *   @version $Revision: 1.7 $
    */
   public abstract class AbstractInstancePool
      implements InstancePool, XmlLoadable
  @@ -128,8 +128,11 @@
         // Pool it
   //DEBUG      Logger.debug("Free instance:"+ctx.getId()+"#"+ctx.getTransaction());
         
  -      ctx.clear();      
  +      ctx.clear();
         
  +      // Free everyone waiting on that ctx
  +      synchronized (ctx) {ctx.notifyAll();}
  +      
         if (pool.size() < maxSize)
         {
            pool.push(ctx);
  @@ -153,16 +156,16 @@
      
      // Z implementation ----------------------------------------------
      
  -     // XmlLoadable implementation
  -     public void importXml(Element element) throws DeploymentException {
  -             String maximumSize = 
MetaData.getElementContent(MetaData.getUniqueChild(element, "MaximumSize"));
  -         try {
  -                     maxSize = Integer.parseInt(maximumSize);
  -             } catch (NumberFormatException e) {
  -                     throw new DeploymentException("Invalid MaximumSize value for 
instance pool configuration");
  -             }
  -     }
  -     
  +    // XmlLoadable implementation
  +    public void importXml(Element element) throws DeploymentException {
  +       String maximumSize = 
MetaData.getElementContent(MetaData.getUniqueChild(element, "MaximumSize"));
  +        try {
  +         maxSize = Integer.parseInt(maximumSize);
  +       } catch (NumberFormatException e) {
  +         throw new DeploymentException("Invalid MaximumSize value for instance pool 
configuration");
  +       }
  +    }
  +    
      // Package protected ---------------------------------------------
       
      // Protected -----------------------------------------------------
  
  
  

Reply via email to