User: salborini
  Date: 00/10/19 20:11:45

  Modified:    src/main/org/jboss/ejb/plugins
                        EntityInstanceInterceptor.java
                        TxInterceptorCMT.java
  Log:
  Improved synchronization logic.
  
  Revision  Changes    Path
  1.22      +213 -207  
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.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- EntityInstanceInterceptor.java    2000/10/19 21:48:42     1.21
  +++ EntityInstanceInterceptor.java    2000/10/20 03:11:43     1.22
  @@ -42,8 +42,9 @@
   *
   *   @see <related>
   *   @author Rickard �berg ([EMAIL PROTECTED])
  -*   @author <a href="[EMAIL PROTECTED]">Marc Fleury</a>
  -*   @version $Revision: 1.21 $
  +*   @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
  +*   @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a>
  +*   @version $Revision: 1.22 $
   */
   public class EntityInstanceInterceptor
   extends AbstractInterceptor
  @@ -60,232 +61,237 @@
       // Public --------------------------------------------------------
       public void setContainer(Container container) 
       { 
  -       this.container = (EntityContainer)container; 
  +        this.container = (EntityContainer)container; 
       }
       
       public  Container getContainer()
       {
  -       return container;
  +        return container;
       }
       
       // Interceptor implementation --------------------------------------
       public Object invokeHome(MethodInvocation mi)
       throws Exception
       {
  -       // Get context
  -       EnterpriseContext ctx = 
((EntityContainer)getContainer()).getInstancePool().get();
  -       mi.setEnterpriseContext(ctx);
  -       
  -       // It is a new context for sure so we can lock it
  -       ctx.lock();
  -       
  -       try
  -       {
  -         // Invoke through interceptors
  -         return getNext().invokeHome(mi);
  -       } finally
  -       {
  -         // 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) {
  -              
  -              //Let the waiters know
  -              ctx.notifyAll();
  -          }
  -         }
  -       }
  +        // Get context
  +        EnterpriseContext ctx = 
((EntityContainer)getContainer()).getInstancePool().get();
  +        mi.setEnterpriseContext(ctx);
  +        
  +        // It is a new context for sure so we can lock it
  +        ctx.lock();
  +        
  +        try
  +        {
  +            // Invoke through interceptors
  +            return getNext().invokeHome(mi);
  +        } finally
  +        {
  +            // 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) {
  +                    
  +                    //Let the waiters know
  +                    ctx.notifyAll();
  +                }
  +            }
  +        }
       }
       
       public Object invoke(MethodInvocation mi)
       throws Exception
       {
  -       // The id store is a CacheKey in the case of Entity 
  -       CacheKey key = (CacheKey) mi.getId();
  -       
  -       // Get cache
  -       EnterpriseInstanceCache cache = 
(EnterpriseInstanceCache)container.getInstanceCache();
  -       Object mutex = cache.getLock(key);
  -        
  -       EnterpriseContext ctx = null;
  -       
  -       // We synchronize the locking logic (so that the invoke is unsynchronized 
and can be reentrant)
  -       do 
  -         {
  -                     synchronized (mutex)
  -         {
  -          // Get context
  -          ctx = cache.get(key);
  -          
  -          // Do we have a running transaction with the context
  -               Transaction tx = ctx.getTransaction();
  -          if (tx != null &&
  -              // And are we trying to enter with another transaction
  -              !tx.equals(mi.getTransaction())) 
  -          {
  -              // Let's put the thread to sleep a lock release will wake the thread
  -              synchronized (ctx)
  -              {
  -                 // Possible deadlock
  -                 Logger.log("LOCKING-WAITING (TRANSACTION) for id "+ctx.getId()+" 
ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" : tx.toString()));
  -                 
  -                 try{ctx.wait(100);}
  -                   catch (InterruptedException ie) {}
  -              }
  -              
  -              // Try your luck again
  -              ctx = null;
  -              continue;
  -          }
  -          
  -          if (!ctx.isLocked()){
  -              
  -              //take it!
  -              ctx.lock();  
  -          }                                                            
  -          
  -          else 
  +        // The id store is a CacheKey in the case of Entity 
  +        CacheKey key = (CacheKey) mi.getId();
  +        
  +        // Get cache
  +        EnterpriseInstanceCache cache = 
(EnterpriseInstanceCache)container.getInstanceCache();
  +        Object mutex = cache.getLock(key);
  +        
  +        EnterpriseContext ctx = null;
  +        
  +        try
  +        {
  +            do
  +            {
  +                if (mi.getTransaction() != null && mi.getTransaction().getStatus() 
== Status.STATUS_MARKED_ROLLBACK) 
  +                    throw new RuntimeException("Transaction marked for rollback, 
possibly a timeout");
  +                
  +                synchronized(this) 
  +                {
  +                    
  +                    // Get context
  +                    ctx = cache.get(key);
  +                }
  +                
  +                synchronized(ctx) 
                   {
  -                    if (!isCallAllowed(mi)) {
  +                    
  +                    // Do we have a running transaction with the context
  +                    Transaction tx = ctx.getTransaction();
  +                    if (tx != null &&
  +                        // And are we trying to enter with another transaction
  +                        !tx.equals(mi.getTransaction())) 
  +                    {
  +                        // Let's put the thread to sleep a lock release will wake 
the thread
  +                        // Possible deadlock
  +                        Logger.debug("LOCKING-WAITING (TRANSACTION) for id 
"+ctx.getId()+" ctx.hash "+ctx.hashCode()+" tx:"+((tx == null) ? "null" : 
tx.toString()));
                           
  -                        // Go to sleep and wait for the lock to be released
  -                        // This is not one of the "home calls" so we need to wait 
for the lock
  -                        synchronized (ctx)
  -                        {
  -                            // Possible deadlock
  -                            Logger.log("LOCKING-WAITING (CTX) for id 
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
  -                            
  -                            try{ctx.wait(100);}
  -                                catch (InterruptedException ie) {}
  -                        }
  +                        try {
  +                            ctx.wait();
  +                        } catch (InterruptedException ie) {}
                           
                           // Try your luck again
                           ctx = null;
                           continue;
  -                        // Not allowed reentrant call
  -                        //throw new RemoteException("Reentrant call");
  +                    
  +                    }
  +                    else 
  +                    {
  +                        // If we get here it's the right tx, or no tx
  +                        if (!ctx.isLocked())
  +                        {
  +                            //take it!
  +                            ctx.lock();
  +                        }
  +                        else
  +                        { 
  +                            if (!isCallAllowed(mi)) {
  +                                
  +                                // Go to sleep and wait for the lock to be released
  +                                // This is not one of the "home calls" so we need 
to wait for the lock
  +                                
  +                                // Possible deadlock
  +                                Logger.debug("LOCKING-WAITING (CTX) for id 
"+ctx.getId()+" ctx.hash "+ctx.hashCode());
  +                                
  +                                try{
  +                                    ctx.wait();
  +                                } catch (InterruptedException ie) {}
  +                                
  +                                // Try your luck again
  +                                ctx = null;
  +                                continue;
  +                                // Not allowed reentrant call
  +                                //throw new RemoteException("Reentrant call");
  +                            }
  +                            else
  +                            {
  +                                //We are in a home call so take the lock, take it!
  +                                ctx.lock();
  +                            }
  +                        }
  +                    }
  +                }
  +            
  +            } while (ctx == null);
  +                
  +            // Set context on the method invocation
  +            mi.setEnterpriseContext(ctx);
  +            
  +            // Go on, you won
  +            return getNext().invoke(mi);
  +        
  +        } 
  +        catch (RemoteException e)
  +        {
  +            // Discard instance
  +            // EJB 1.1 spec 12.3.1
  +            cache.remove(key);
  +            
  +            throw e;
  +        } catch (RuntimeException e)
  +        {
  +            // Discard instance
  +            // EJB 1.1 spec 12.3.1
  +            cache.remove(key);
  +            
  +            throw e;
  +        } catch (Error e)
  +        {
  +            // Discard instance
  +            // EJB 1.1 spec 12.3.1
  +            cache.remove(key);
  +            
  +            throw e;
  +        } finally
  +        {
  +            //         Logger.debug("Release instance for "+id);
  +            if (ctx != null)
  +            {
  +                // unlock the context
  +                ctx.unlock();
  +                
  +                if (ctx.getId() == null)                             
  +                {
                       
  -              } else
  -              {
  -                 //We are in a home call so take the lock, take it!
  -                 ctx.lock();  
  -              }
  -          }
  -                                                                     
  -         }
  -       } while (ctx == null);
  -         
  -       // Set context on the method invocation
  -       mi.setEnterpriseContext(ctx);
  -       
  -       try {
  -         // Go on, you won
  -         return getNext().invoke(mi);
  -       
  -       } 
  -       catch (RemoteException e)
  -       {
  -         // Discard instance
  -         // EJB 1.1 spec 12.3.1
  -         cache.remove(key);
  -         
  -         throw e;
  -       } catch (RuntimeException e)
  -       {
  -         // Discard instance
  -         // EJB 1.1 spec 12.3.1
  -         cache.remove(key);
  -         
  -         throw e;
  -       } catch (Error e)
  -       {
  -         // Discard instance
  -         // EJB 1.1 spec 12.3.1
  -         cache.remove(key);
  -         
  -         throw e;
  -       } finally
  -       {
  -         //         Logger.debug("Release instance for "+id);
  -                     if (ctx != null)
  -                     {
  -                             
  -                             synchronized (mutex) {
  -                                     
  -                                     // unlock the context
  -                                     ctx.unlock();
  -                                     
  -                                     if (ctx.getId() == null)                       
      
  -                                     {
  -                                             
  -                                             // Work only if no transaction was 
encapsulating this remove()
  -                                             if (ctx.getTransaction() == null) {
  -                                                     
  -                                                     // Remove from cache
  -                                                     cache.remove(key);
  -                                                     
  -                                                     // It has been removed -> send 
to the pool
  -                                                     
container.getInstancePool().free(ctx);
  -                                             }
  -                                     }
  -                                     
  -                                     // notify the thread waiting on ctx
  -                                     synchronized (ctx) { ctx.notifyAll();}
  -                             }
  -                     }
  -       }
  -    }
  -    
  -    // Private --------------------------------------------------------
  -    
  -    private static Method getEJBHome;
  -    private static Method getHandle;
  -    private static Method getPrimaryKey;
  -    private static Method isIdentical;
  -    private static Method remove;
  -    static 
  -    {
  -       try 
  -       {
  -         Class[] noArg = new Class[0];
  -         getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
  -         getHandle = EJBObject.class.getMethod("getHandle", noArg);
  -         getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", noArg);
  -         isIdentical = EJBObject.class.getMethod("isIdentical", new Class[] 
{EJBObject.class});
  -         remove = EJBObject.class.getMethod("remove", noArg);
  -       }
  -       catch (Exception x) {x.printStackTrace();}
  -    }
  -    
  -    private boolean isCallAllowed(MethodInvocation mi) 
  -    {
  -       boolean reentrant = 
((EntityMetaData)container.getBeanMetaData()).isReentrant();
  -       
  -       if (reentrant)
  -       {
  -         return true;
  -       }
  -       else
  -       {
  -         Method m = mi.getMethod();
  -         if (m.equals(getEJBHome) ||
  -          m.equals(getHandle) ||
  -          m.equals(getPrimaryKey) ||
  -          m.equals(isIdentical) ||
  -          m.equals(remove))
  -         {
  -          return true;
  -         }
  -       }
  -       
  -       return false;
  +                    // Work only if no transaction was encapsulating this remove()
  +                    if (ctx.getTransaction() == null) {
  +                        
  +                        // Remove from cache
  +                        cache.remove(key);
  +                        
  +                        // It has been removed -> send to the pool
  +                        container.getInstancePool().free(ctx);
  +                    }
  +                }
  +                
  +                // notify the thread waiting on ctx
  +                synchronized (ctx) { ctx.notifyAll();}
  +            }
  +        }
  +    }
  +
  +
  +// Private --------------------------------------------------------
  +
  +private static Method getEJBHome;
  +private static Method getHandle;
  +private static Method getPrimaryKey;
  +private static Method isIdentical;
  +private static Method remove;
  +static 
  +{
  +    try 
  +    {
  +        Class[] noArg = new Class[0];
  +        getEJBHome = EJBObject.class.getMethod("getEJBHome", noArg);
  +        getHandle = EJBObject.class.getMethod("getHandle", noArg);
  +        getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", noArg);
  +        isIdentical = EJBObject.class.getMethod("isIdentical", new Class[] 
{EJBObject.class});
  +        remove = EJBObject.class.getMethod("remove", noArg);
  +    }
  +    catch (Exception x) {x.printStackTrace();}
  +}
  +
  +private boolean isCallAllowed(MethodInvocation mi) 
  +{
  +    boolean reentrant = ((EntityMetaData)container.getBeanMetaData()).isReentrant();
  +    
  +    if (reentrant)
  +    {
  +        return true;
       }
  +    else
  +    {
  +        Method m = mi.getMethod();
  +        if (m.equals(getEJBHome) ||
  +            m.equals(getHandle) ||
  +            m.equals(getPrimaryKey) ||
  +            m.equals(isIdentical) ||
  +            m.equals(remove))
  +        {
  +            return true;
  +        }
  +    }
  +    
  +    return false;
  +}
   }
  
  
  
  1.7       +13 -10    jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java
  
  Index: TxInterceptorCMT.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- TxInterceptorCMT.java     2000/10/08 05:30:17     1.6
  +++ TxInterceptorCMT.java     2000/10/20 03:11:43     1.7
  @@ -40,7 +40,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.6 $
  +*   @version $Revision: 1.7 $
   */
   public class TxInterceptorCMT
   extends AbstractInterceptor
  @@ -266,8 +266,8 @@
                           
                           if (newTransaction != null) {
                               
  -                            //We started it, 
  -                            newTransaction.rollback();
  +                            //We started it, it will be rolled back in the finally 
  +                            newTransaction.setRollbackOnly();
                           }
                           
                           throw e;
  @@ -276,8 +276,8 @@
                           
                           if (newTransaction != null) {
                               
  -                            // We started it
  -                            newTransaction.rollback();
  +                            // We started it, it will be rolled back in the finally
  +                            newTransaction.setRollbackOnly();
                           }
                           
                           throw new ServerException("Exception occurred", e);
  @@ -286,8 +286,8 @@
                           
                           if (newTransaction != null) {
                               
  -                            // we started it
  -                            newTransaction.rollback();
  +                            // we started it, it will be rolled back in the finally
  +                            newTransaction.setRollbackOnly();
                           }
                           throw new ServerException("Exception 
occurred:"+e.getMessage());
                       } 
  @@ -380,21 +380,24 @@
                       catch (RemoteException e) {
                           
                           // We started it for sure
  -                        newTransaction.rollback();
  +                        // will be rolled back in the finally
  +                        newTransaction.setRollbackOnly();
                           
                           throw e;
                       } 
                       catch (RuntimeException e) {
                           
                           // We started it for sure
  -                        newTransaction.rollback();
  +                        // will be rolled back in the finally
  +                        newTransaction.setRollbackOnly();
                           
                           throw new ServerException("Exception occurred", e);
                       } 
                       catch (Error e) {
                           
                           // We started it for sure
  -                        newTransaction.rollback();
  +                        // will be rolled back in the finally
  +                        newTransaction.setRollbackOnly();
                           
                           throw new ServerException("Exception 
occurred:"+e.getMessage());
                       } 
  
  
  

Reply via email to