Ok aaron amid his general craziness did raise a problem with the home
exceptions and a missing lock... yes a missplaced else, I just commited the
fix in CVS.

Thank you aaron ;-)

Also in there is the stuff that I saw yesterday at SUN, namely that a notify
will work better,

regards

marc


|-----Original Message-----
|From: [EMAIL PROTECTED]
|[mailto:[EMAIL PROTECTED]]On Behalf Of jBoss CVS
|Development
|Sent: Saturday, October 21, 2000 2:32 PM
|To: [EMAIL PROTECTED]
|Subject: [jBoss-Dev] CVS update:
|jboss/src/main/org/jboss/ejb/pluginsEntitySynchronizationInterceptor.jav
|a EntityInstanceInterceptor.ja
|
|
|  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/EntitySyn
|chronizationInterceptor.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/EntityIns
|tanceInterceptor.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/AbstractI
|nstancePool.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