oh wait, I realize I commited more than I wanted to...

I am working on the interfaces but at this point just wanted to commit the
comments...

sorry this will not compile...
mmmm

marcf

|-----Original Message-----
|From: [EMAIL PROTECTED]
|[mailto:[EMAIL PROTECTED]]On Behalf Of
|[EMAIL PROTECTED]
|Sent: Wednesday, June 27, 2001 1:38 AM
|To: [EMAIL PROTECTED]
|Subject: [JBoss-dev] CVS update: jboss/src/main/org/jboss/ejb/plugins
|AbstractInstanceCache.java
|
|
|  User: mnf999
|  Date: 01/06/26 22:37:43
|
|  Modified:    src/main/org/jboss/ejb/plugins AbstractInstanceCache.java
|  Log:
|  mmmm FIXMES in the AbstractInstanceCache...
|
|  we need to fix this poopoo
|
|  Revision  Changes    Path
|  1.12      +292 -276
|jboss/src/main/org/jboss/ejb/plugins/AbstractInstanceCache.java
|
|  Index: AbstractInstanceCache.java
|  ===================================================================
|  RCS file:
|/cvsroot/jboss/jboss/src/main/org/jboss/ejb/plugins/AbstractInstanc
|eCache.java,v
|  retrieving revision 1.11
|  retrieving revision 1.12
|  diff -u -r1.11 -r1.12
|  --- AbstractInstanceCache.java       2001/06/18 20:01:23     1.11
|  +++ AbstractInstanceCache.java       2001/06/27 05:37:43     1.12
|  @@ -1,9 +1,9 @@
|   /*
|  - * JBoss, the OpenSource EJB server
|  - *
|  - * Distributable under LGPL license.
|  - * See terms of license at gnu.org.
|  - */
|  +* JBoss, the OpenSource EJB server
|  +*
|  +* Distributable under LGPL license.
|  +* See terms of license at gnu.org.
|  +*/
|
|   package org.jboss.ejb.plugins;
|
|  @@ -47,24 +47,32 @@
|   import org.jboss.monitor.MetricsConstants;
|
|   /**
|  - * Base class for caches of entity and stateful beans. <p>
|  - * It manages the cache entries through a {@link CachePolicy} object;
|  - * the implementation of the cache policy object must respect
|the following
|  - * requirements:
|  - * <ul>
|  - * <li> Have a public constructor that takes a single argument of type
|  - * AbstractInstanceCache.class or a subclass
|  - * </ul>
|  - *
|  - * @author <a href="mailto:[EMAIL PROTECTED]";>Simone Bordet</a>
|  - * @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
|  - * @version $Revision: 1.11 $
|  - */
|  +* Base class for caches of entity and stateful beans. <p>
|  +* It manages the cache entries through a {@link CachePolicy} object;
|  +* the implementation of the cache policy object must respect
|the following
|  +* requirements:
|  +* <ul>
|  +* <li> Have a public constructor that takes a single argument of type
|  +* AbstractInstanceCache.class or a subclass
|  +* </ul>
|  +*
|  +*
|  +* @author <a href="mailto:[EMAIL PROTECTED]";>Simone Bordet</a>
|  +* @author <a href="[EMAIL PROTECTED]">Bill Burke</a>
|  +* @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
|  +*
|  +*
|  +*   Revisions:
|  +*
|  +*   20010626 marc fleury: Cache should be working with the
|MethodInvocation
|  +*
|  +* @version $Revision: 1.12 $
|  +*/
|   public abstract class AbstractInstanceCache
|  -    implements InstanceCache, XmlLoadable, Monitorable, MetricsConstants
|  +implements InstanceCache, XmlLoadable, Monitorable, MetricsConstants
|   {
|       // Constants -----------------------------------------------------
|  -
|  +
|       // Attributes ----------------------------------------------------
|       /* The object that is delegated to implement the desired
|caching policy */
|       private CachePolicy m_cache;
|  @@ -85,11 +93,11 @@
|       private Topic m_jmsTopic;
|       private TopicSession m_jmsSession;
|       private TopicPublisher m_jmsPublisher;
|  -
|  +
|       // Static --------------------------------------------------------
|  -
|  +
|       // Constructors --------------------------------------------------
|  -
|  +
|       // Monitorable implementation ------------------------------------
|       public void sample(Object s)
|       {
|  @@ -104,16 +112,16 @@
|                       }
|               }
|       }
|  -
|  +
|       // Public --------------------------------------------------------
|       public void setJMSMonitoringEnabled(boolean enable)
|{m_jmsMonitoring = enable;}
|       public boolean isJMSMonitoringEnabled() {return m_jmsMonitoring;}
|  -
|  +
|       public void sendMessage(Message message)
|       {
|               try
|               {
|  -            message.setJMSType(BEANCACHE_METRICS);
|  +                    message.setJMSType(BEANCACHE_METRICS);
|                       message.setJMSExpiration(5000);
|                       message.setLongProperty(TIME,
|System.currentTimeMillis());
|                       m_jmsPublisher.publish(m_jmsTopic, message);
|  @@ -142,22 +150,26 @@
|               }
|               return message;
|       }
|  -
|  +
|       /* From InstanceCache interface */
|       public EnterpriseContext get(Object id)
|  -            throws RemoteException, NoSuchObjectException
|  +    throws RemoteException, NoSuchObjectException
|       {
|               if (id == null) throw new
|IllegalArgumentException("Can't get an object with a null key");
|  -
|  +
|               EnterpriseContext ctx = null;
|  +
|               synchronized (getCacheLock())
|               {
|                       ctx = (EnterpriseContext)getCache().get(id);
|                       if (ctx == null)
|                       {
|                               // Here I block if the bean is
|passivating now
|  +
|  +                            // FIXME marcf: I am REALLY against
|locking on passivation, we are locking the
|  +                            // whole cache for the passivation
|of one guy. it doesn't make sense!!!!!!!!
|                               ctx = unschedulePassivation(id);
|  -
|  +
|                               // Already passivated ?
|                               if (ctx == null)
|                               {
|  @@ -165,6 +177,9 @@
|                                       {
|                                               ctx = acquireContext();
|                                               setKey(id, ctx);
|  +                                            //FIXME marcf: in
|the case of session we are saying that the WHOLE
|  +                                            // cache will be
|locked (see synchronized statement) until this guy completes
|  +                                            // DO YOU SEE IT?
|THE *WHOLE* APP LOCKED ON A ACTIVATION??? WTF?
|                                               activate(ctx);
|                                               logActivation(id);
|                                               insert(ctx);
|  @@ -182,13 +197,14 @@
|                       }
|               }
|               if (ctx == null) throw new
|NoSuchObjectException("Can't find bean with id = " + id);
|  +
|               return ctx;
|       }
|       /* From InstanceCache interface */
|       public void insert(EnterpriseContext ctx)
|       {
|               if (ctx == null) throw new
|IllegalArgumentException("Can't insert a null object in the cache");
|  -
|  +
|               CachePolicy cache = getCache();
|               synchronized (getCacheLock())
|               {
|  @@ -196,7 +212,7 @@
|                       // key, then the context is passivated and
|I will insert in cache a meaningless
|                       // context.
|                       Object key = getKey(ctx);
|  -
|  +
|                       if (cache.peek(key) == null)
|                       {
|                               cache.insert(key, ctx);
|  @@ -214,7 +230,7 @@
|       public void release(EnterpriseContext ctx)
|       {
|               if (ctx == null) throw new
|IllegalArgumentException("Can't release a null object");
|  -
|  +
|               // Here I remove the bean; call to remove(id) is wrong
|               // cause will remove also the cache lock that is needed
|               // by the passivation, that eventually will remove it.
|  @@ -237,7 +253,7 @@
|       public void remove(Object id)
|       {
|               if (id == null) throw new
|IllegalArgumentException("Can't remove an object using a null key");
|  -
|  +
|               synchronized (getCacheLock())
|               {
|                       if (getCache().peek(id) != null)
|  @@ -247,19 +263,19 @@
|               }
|               removeLock(id);
|       }
|  -
|  +
|       public boolean isActive(Object id)
|       {
|               // Check whether an object with the given id is
|available in the cache
|               return getCache().peek(id) != null;
|       }
|       /**
|  -     * Creates (if necessary) and returns an object used as
|mutex to sync passivation
|  -     * activity with other activities, in particular incoming
|invoking calls. <br>
|  -     * The mutex is automatically removed when the
|corrispondent id is removed from
|  -     * the cache, either by passivation or by removal.
|  -     * This method must be synchronized with its dual, {@link
|#removeLock}.
|  -     */
|  +    * Creates (if necessary) and returns an object used as
|mutex to sync passivation
|  +    * activity with other activities, in particular incoming
|invoking calls. <br>
|  +    * The mutex is automatically removed when the corrispondent
|id is removed from
|  +    * the cache, either by passivation or by removal.
|  +    * This method must be synchronized with its dual, {@link
|#removeLock}.
|  +    */
|       public synchronized Sync getLock(Object id)
|       {
|               Sync mutex = (Sync)m_lockMap.get(id);
|  @@ -271,22 +287,22 @@
|               return mutex;
|       }
|       /**
|  -     * Removes the mutex associated with the given id.
|  -     * This method must be synchronized with its dual, {@link #getLock}.
|  -     */
|  +    * Removes the mutex associated with the given id.
|  +    * This method must be synchronized with its dual, {@link #getLock}.
|  +    */
|       protected synchronized void removeLock(Object id)
|       {
|               Object mutex = m_lockMap.get(id);
|               if (mutex != null)
|               {
|  -                if (mutex instanceof BeanSemaphore)
|  -                {
|  -                    ((BeanSemaphore)mutex).invalidate();
|  -                }
|  -                m_lockMap.remove(id);
|  +                    if (mutex instanceof BeanSemaphore)
|  +                    {
|  +                            ((BeanSemaphore)mutex).invalidate();
|  +                    }
|  +                    m_lockMap.remove(id);
|               }
|       }
|  -
|  +
|       // XmlLoadable implementation
|----------------------------------------------
|       public void importXml(Element element) throws DeploymentException
|       {
|  @@ -302,7 +318,7 @@
|               {
|                       throw new DeploymentException("Can't create
|cache policy", x);
|               }
|  -
|  +
|               Element policyConf =
|MetaData.getOptionalChild(element, "cache-policy-conf");
|               if (policyConf != null)
|               {
|  @@ -319,7 +335,7 @@
|                       }
|               }
|       }
|  -
|  +
|       /* From Service interface*/
|       public void init() throws Exception
|       {
|  @@ -328,16 +344,16 @@
|               String threadName = "Passivator Thread for " +
|getContainer().getBeanMetaData().getEjbName();
|               ClassLoader cl = getContainer().getClassLoader();
|               m_passivator = new PassivatorQueue(threadName, cl);
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       // Setup JMS for cache monitoring
|                       Context namingContext = new InitialContext();
|                       Object factoryRef =
|namingContext.lookup("TopicConnectionFactory");
|                       TopicConnectionFactory factory =
|(TopicConnectionFactory)PortableRemoteObject.narrow(factoryRef,
|TopicConnectionFactory.class);
|  -
|  +
|                       m_jmsConnection = factory.createTopicConnection();
|  -
|  +
|                       Object topicRef =
|namingContext.lookup("topic/metrics");
|                       m_jmsTopic =
|(Topic)PortableRemoteObject.narrow(topicRef, Topic.class);
|                       m_jmsSession =
|m_jmsConnection.createTopicSession(false, Session.DUPS_OK_ACKNOWLEDGE);
|  @@ -349,7 +365,7 @@
|       {
|               getCache().start();
|               m_passivator.start();
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       m_jmsConnection.start();
|  @@ -363,9 +379,9 @@
|               {
|                       getCache().stop();
|               }
|  -
|  +
|               if (m_passivator != null) {m_passivator.stop();}
|  -
|  +
|               if (isJMSMonitoringEnabled() && m_jmsConnection != null)
|               {
|                       try
|  @@ -388,32 +404,32 @@
|                       catch (JMSException ignored) {}
|               }
|       }
|  -
|  +
|       // Y overrides ---------------------------------------------------
|  -
|  +
|       // Package protected ---------------------------------------------
|  -
|  +
|       // Protected -----------------------------------------------------
|       /**
|  -     * Schedules the given EnterpriseContext for passivation
|  -     * @see PassivationHelper#schedule
|  -     */
|  +    * Schedules the given EnterpriseContext for passivation
|  +    * @see PassivationHelper#schedule
|  +    */
|       protected void schedulePassivation(EnterpriseContext ctx)
|       {
|               m_passivationHelper.schedule(ctx);
|               logPassivationScheduled(getKey(ctx));
|       }
|       /**
|  -     * Tries to unschedule the given EnterpriseContext for
|passivation; returns
|  -     * the unscheduled context if it wasn't passivated yet, null if the
|  -     * passivation already happened.
|  -     * @see PassivationHelper#unschedule
|  -     */
|  +    * Tries to unschedule the given EnterpriseContext for
|passivation; returns
|  +    * the unscheduled context if it wasn't passivated yet, null if the
|  +    * passivation already happened.
|  +    * @see PassivationHelper#unschedule
|  +    */
|       protected EnterpriseContext unschedulePassivation(Object id)
|       {
|               return m_passivationHelper.unschedule(id);
|       }
|  -
|  +
|       protected void logActivation(Object id)
|       {
|               m_buffer.setLength(0);
|  @@ -422,7 +438,7 @@
|               m_buffer.append(" with id = ");
|               m_buffer.append(id);
|               Logger.debug(m_buffer.toString());
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       // Prepare JMS message
|  @@ -435,12 +451,12 @@
|                       {
|                               Logger.exception(x);
|                       }
|  -
|  +
|                       // Send JMS Message
|                       sendMessage(message);
|               }
|       }
|  -
|  +
|       protected void logPassivationScheduled(Object id)
|       {
|               m_buffer.setLength(0);
|  @@ -449,7 +465,7 @@
|               m_buffer.append(" with id = ");
|               m_buffer.append(id);
|               Logger.debug(m_buffer.toString());
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       // Prepare JMS message
|  @@ -463,12 +479,12 @@
|                       {
|                               Logger.exception(x);
|                       }
|  -
|  +
|                       // Send JMS Message
|                       sendMessage(message);
|               }
|       }
|  -
|  +
|       protected void logPassivation(Object id)
|       {
|               m_buffer.setLength(0);
|  @@ -477,7 +493,7 @@
|               m_buffer.append(" with id = ");
|               m_buffer.append(id);
|               Logger.debug(m_buffer.toString());
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       // Prepare JMS message
|  @@ -491,12 +507,12 @@
|                       {
|                               Logger.exception(x);
|                       }
|  -
|  +
|                       // Send JMS Message
|                       sendMessage(message);
|               }
|       }
|  -
|  +
|       protected void logPassivationPostponed(Object id)
|       {
|               m_buffer.setLength(0);
|  @@ -505,7 +521,7 @@
|               m_buffer.append(" with id = ");
|               m_buffer.append(id);
|               Logger.debug(m_buffer.toString());
|  -
|  +
|               if (isJMSMonitoringEnabled())
|               {
|                       // Prepare JMS message
|  @@ -519,86 +535,86 @@
|                       {
|                               Logger.exception(x);
|                       }
|  -
|  +
|                       // Send JMS Message
|                       sendMessage(message);
|               }
|       }
|  -
|  +
|       /**
|  -     * Returns the container for this cache.
|  -     */
|  +    * Returns the container for this cache.
|  +    */
|       protected abstract Container getContainer();
|       /**
|  -     * Returns the cache policy used for this cache.
|  -     */
|  +    * Returns the cache policy used for this cache.
|  +    */
|       protected CachePolicy getCache() {return m_cache;}
|       /**
|  -     * Returns the mutex used to sync access to the cache policy object
|  -     */
|  +    * Returns the mutex used to sync access to the cache policy object
|  +    */
|       public Object getCacheLock()
|       {
|               return m_cacheLock;
|       }
|       /**
|  -     * Passivates the given EnterpriseContext
|  -     */
|  +    * Passivates the given EnterpriseContext
|  +    */
|       protected abstract void passivate(EnterpriseContext ctx)
|throws RemoteException;
|       /**
|  -     * Activates the given EnterpriseContext
|  -     */
|  +    * Activates the given EnterpriseContext
|  +    */
|       protected abstract void activate(EnterpriseContext ctx)
|throws RemoteException;
|       /**
|  -     * Acquires an EnterpriseContext from the pool
|  -     */
|  +    * Acquires an EnterpriseContext from the pool
|  +    */
|       protected abstract EnterpriseContext acquireContext()
|throws Exception;
|       /**
|  -     * Frees the given EnterpriseContext to the pool
|  -     */
|  +    * Frees the given EnterpriseContext to the pool
|  +    */
|       protected abstract void freeContext(EnterpriseContext ctx);
|       /**
|  -     * Returns the key used by the cache to map the given context
|  -     */
|  +    * Returns the key used by the cache to map the given context
|  +    */
|       protected abstract Object getKey(EnterpriseContext ctx);
|       /**
|  -     * Sets the given id as key for the given context
|  -     */
|  +    * Sets the given id as key for the given context
|  +    */
|       protected abstract void setKey(Object id, EnterpriseContext ctx);
|       /**
|  -     * Returns whether the given context can be passivated or not
|  -     *
|  -     */
|  +    * Returns whether the given context can be passivated or not
|  +    *
|  +    */
|       protected abstract boolean canPassivate(EnterpriseContext ctx);
|  -
|  +
|       // Private -------------------------------------------------------
|  -
|  +
|       // Inner classes -------------------------------------------------
|       /**
|  -     * Helper class that schedules, unschedules, and executes
|the passivation jobs.
|  -     */
|  +    * Helper class that schedules, unschedules, and executes
|the passivation jobs.
|  +    */
|       protected class PassivationHelper
|       {
|               /* The map that holds the passivation jobs posted */
|               private Map m_passivationJobs;
|  -
|  +
|               protected PassivationHelper()
|               {
|                       m_passivationJobs =
|Collections.synchronizedMap(new HashMap());
|               }
|  -
|  +
|               /**
|  -             * Creates and schedules a {@link PassivationJob}
|for passivation
|  -             */
|  +            * Creates and schedules a {@link PassivationJob}
|for passivation
|  +            */
|               protected void schedule(EnterpriseContext bean)
|               {
|                       // Register only once the job to be able to
|unschedule its passivation
|                       Object key = getKey(bean);
|                       if (m_passivationJobs.get(key) == null)
|                       {
|  -                            // (Bill Burke) We can't rely on
|the EnterpriseContext to provide PassivationJob
|  -                            // with a valid key because it may
|get freed to the InstancePool, then
|  -                            // reused before the PassivationJob
|executes.
|  -                            //
|  +                            // (Bill Burke) We can't rely on
|the EnterpriseContext to provide PassivationJob
|  +                            // with a valid key because it may
|get freed to the InstancePool, then
|  +                            // reused before the PassivationJob
|executes.
|  +                            //
|                               PassivationJob job = new
|PassivationJob(bean, key)
|                               {
|                                       public void execute()
|throws Exception
|  @@ -606,101 +622,101 @@
|                                               EnterpriseContext
|ctx = this.getEnterpriseContext();
|                                               if (ctx.getId() == null)
|                                               {
|  -                                                // If this
|happens, then a passivation request for this bean was issued
|  -                                                // but not yet
|executed, and in the meanwhile the bean has been removed.
|  -                                                return;
|  +                                                    // If this
|happens, then a passivation request for this bean was issued
|  +                                                    // but not
|yet executed, and in the meanwhile the bean has been removed.
|  +                                                    return;
|                                               }
|  -
|  +
|                                               Object id = this.getKey();
|  -
|  +
|                                               /**
|  -                                             * Synchronization
|/ Passivation explanations:
|  -                                             * The instance
|interceptor (II) first acquires the Sync object associated
|  -                                             * with the given
|id, then asks to the instance cache (IC) for an enterprise
|  -                                             * context.
|  -                                             * The IC, if the
|context is not present, activates it and returns it.
|  -                                             * If the context
|is not in the IC then or it has already been
|  -                                             * passivated, or
|it is scheduled for passivation. If the latter is true,
|  -                                             * then the job is
|canceled and passivation does not occur, and the context
|  -                                             * is reinserted in the IC.
|  -                                             * This activity
|synchronizes in the following order the following objects:
|  -                                             * 1) the Sync
|object associated to the context's id via getLock(id)
|  -                                             * 2) the cache
|lock object via getCacheLock()
|  -                                             * 3) the
|passivation job, since cancel() is synchronized.
|  -                                             * To avoid
|deadlock, here we MUST acquire these resources in the same
|  -                                             * exact order.
|  -                                             */
|  +                                            * Synchronization /
|Passivation explanations:
|  +                                            * The instance
|interceptor (II) first acquires the Sync object associated
|  +                                            * with the given
|id, then asks to the instance cache (IC) for an enterprise
|  +                                            * context.
|  +                                            * The IC, if the
|context is not present, activates it and returns it.
|  +                                            * If the context is
|not in the IC then or it has already been
|  +                                            * passivated, or it
|is scheduled for passivation. If the latter is true,
|  +                                            * then the job is
|canceled and passivation does not occur, and the context
|  +                                            * is reinserted in the IC.
|  +                                            * This activity
|synchronizes in the following order the following objects:
|  +                                            * 1) the Sync
|object associated to the context's id via getLock(id)
|  +                                            * 2) the cache lock
|object via getCacheLock()
|  +                                            * 3) the
|passivation job, since cancel() is synchronized.
|  +                                            * To avoid
|deadlock, here we MUST acquire these resources in the same
|  +                                            * exact order.
|  +                                            */
|                                               Sync mutex =
|(Sync)getLock(id);
|  -
|  +
|                                               try
|                                               {
|                                                       mutex.acquire();
|  -
|  +
|
|synchronized (getCacheLock())
|                                                       {
|  -                                                        // This
|is absolutely fundamental: the job must be removed from
|  -                                                        // the
|map in every case. If it remains there, the call to
|  -                                                        //
|PassivationHelper.unschedule() will cause the corrispondent
|  -                                                        //
|context to be reinserted in the cache, and if then is passivated
|  -                                                        // we
|have a context without meaning in the cache
|  -
|m_passivationJobs.remove(id);
|  -
|  -
|synchronized (this)
|  -                                                        {
|  -                                                            if
|(ctx instanceof EntityEnterpriseContext)
|  -                                                            {
|  -
|// Verify that this ctx hasn't already
|  -
|// been freed and re-used by another thread.
|  -
|if (!((EntityEnterpriseContext)ctx).getCacheKey().equals(id))
|  -                                                                {
|  -
|// ctx has been freed then re-used in another thread.
|  -
|return;
|  -                                                                }
|  -                                                            }
|  -                                                            if
|(!canPassivate(ctx))
|  +                                                            //
|This is absolutely fundamental: the job must be removed from
|  +                                                            //
|the map in every case. If it remains there, the call to
|  +                                                            //
|PassivationHelper.unschedule() will cause the corrispondent
|  +                                                            //
|context to be reinserted in the cache, and if then is passivated
|  +                                                            //
|we have a context without meaning in the cache
|  +
|m_passivationJobs.remove(id);
|  +
|  +
|synchronized (this)
|                                                               {
|  -
|// This check is done because there could have been
|  -
|// a request for passivation of this bean, but before
|  -
|// being passivated it got a request and has already
|  -
|// been inserted in the cache by the cache
|  -
|if (getCache().peek(id) == null)
|  -                                                                {
|  -
|getCache().insert(id, ctx);
|  -                                                                }
|  -
|  -
|logPassivationPostponed(id);
|  -
|  -                                                                return;
|  -                                                            }
|  -                                                            else
|  -                                                            {
|  -
|if (!isCancelled())
|  -                                                                {
|  -                                                                    try
|  +
|if (ctx instanceof EntityEnterpriseContext)
|  +                                                                    {
|  +
|       // Verify that this ctx hasn't already
|  +
|       // been freed and re-used by another thread.
|  +
|       if (!((EntityEnterpriseContext)ctx).getCacheKey().equals(id))
|  +
|       {
|  +
|               // ctx has been freed then re-used in another thread.
|  +
|               return;
|  +
|       }
|  +                                                                    }
|  +
|if (!canPassivate(ctx))
|                                                                       {
|  -
|    // If the next call throws RemoteException we reinsert
|  -
|    // the bean in the cache; every successive passivation
|  -
|    // attempt will fail. The other policy would have been
|  -
|    // to remove it, but then clients unexpectedly won't
|  -
|    // find it anymore. On the other hand, on the server
|  -
|    // log it is possible to see that passivation for the
|  -
|    // bean failed, and fix it. See EJB 1.1, 6.4.1
|  -
|    passivate(ctx);
|  -
|    executed();
|  -
|    removeLock(id);
|  -
|    freeContext(ctx);
|  -
|  -
|    logPassivation(id);
|  +
|       // This check is done because there could have been
|  +
|       // a request for passivation of this bean, but before
|  +
|       // being passivated it got a request and has already
|  +
|       // been inserted in the cache by the cache
|  +
|       if (getCache().peek(id) == null)
|  +
|       {
|  +
|               getCache().insert(id, ctx);
|  +
|       }
|  +
|  +
|       logPassivationPostponed(id);
|  +
|  +
|       return;
|                                                                       }
|  -
|catch (RemoteException x)
|  +                                                                    else
|                                                                       {
|  -
|    // Can't passivate this bean, reinsert it in the cache
|  -
|    getCache().insert(id, ctx);
|  -
|    throw x;
|  +
|       if (!isCancelled())
|  +
|       {
|  +
|               try
|  +
|               {
|  +
|                       // If the next call throws RemoteException
|we reinsert
|  +
|                       // the bean in the cache; every successive
|passivation
|  +
|                       // attempt will fail. The other policy
|would have been
|  +
|                       // to remove it, but then clients unexpectedly won't
|  +
|                       // find it anymore. On the other hand, on the server
|  +
|                       // log it is possible to see that
|passivation for the
|  +
|                       // bean failed, and fix it. See EJB 1.1, 6.4.1
|  +
|                       passivate(ctx);
|  +
|                       executed();
|  +
|                       removeLock(id);
|  +
|                       freeContext(ctx);
|  +
|
|  +
|                       logPassivation(id);
|  +
|               }
|  +
|               catch (RemoteException x)
|  +
|               {
|  +
|                       // Can't passivate this bean, reinsert it
|in the cache
|  +
|                       getCache().insert(id, ctx);
|  +
|                       throw x;
|  +
|               }
|  +
|       }
|                                                                       }
|  -                                                                }
|                                                               }
|  -                                                        }
|                                                       }
|                                               }
|                                               catch
|(InterruptedException ignored) {}
|  @@ -710,7 +726,7 @@
|                                               }
|                                       }
|                               };
|  -
|  +
|                               // This method is entered only by
|one thread at a time, since the only caller
|                               // call it only after having sync
|on the cache lock via getCacheLock().
|                               // However, enforce this sync'ing
|on the passivation job's map
|  @@ -720,7 +736,7 @@
|                                       {
|                                               // Register job
|
|m_passivationJobs.put(key, job);
|  -
|  +
|                                               // Schedule the job
|for passivation
|                                               m_passivator.putJob(job);
|                                       }
|  @@ -735,15 +751,15 @@
|                       }
|               }
|               /**
|  -             * Tries to unschedule a job paired with the given
|context's id
|  -             * @return null if the bean has been passivated, the context
|  -             * paired with the given id otherwise
|  -             */
|  +            * Tries to unschedule a job paired with the given
|context's id
|  +            * @return null if the bean has been passivated, the context
|  +            * paired with the given id otherwise
|  +            */
|               protected EnterpriseContext unschedule(Object id)
|               {
|                       // I chose not to remove canceled job here
|becauses multiple
|                       // unscheduling requests can arrive. This
|way all will be served
|  -
|  +
|                       // Is the passivation job for id still to
|be executed ?
|                       PassivationJob job =
|(PassivationJob)m_passivationJobs.get(id);
|                       if (job != null)
|  @@ -768,75 +784,75 @@
|   }
|
|   /**
|  - * Abstract class for passivation jobs.
|  - * Subclasses should implement {@link #execute} synchronizing
|it in some way because
|  - * the execute method is normally called in the passivation thread,
|  - * while the cancel method is normally called from another thread.
|  - * To avoid that subclasses override methods of this class without
|  - * make them synchronized (except execute of course), they're
|declared final.
|  - */
|  +* Abstract class for passivation jobs.
|  +* Subclasses should implement {@link #execute} synchronizing it
|in some way because
|  +* the execute method is normally called in the passivation thread,
|  +* while the cancel method is normally called from another thread.
|  +* To avoid that subclasses override methods of this class without
|  +* make them synchronized (except execute of course), they're
|declared final.
|  +*/
|   abstract class PassivationJob implements Executable
|   {
|       private EnterpriseContext m_context;
|       private Object m_key;
|       private boolean m_cancelled;
|       private boolean m_executed;
|  -
|  +
|       PassivationJob(EnterpriseContext ctx, Object key)
|       {
|               m_context = ctx;
|               m_key = key;
|       }
|  -
|  +
|       public abstract void execute() throws Exception;
|  -
|  -        /**
|  -     * (Bill Burke) We can't rely on the EnterpriseContext to
|provide PassivationJob
|  -     * with a valid key because it may get freed to the
|InstancePool, then
|  -     * reused before the PassivationJob executes.
|  -     */
|  -        final Object getKey()
|  -        {
|  -        return m_key;
|  +
|  +    /**
|  +    * (Bill Burke) We can't rely on the EnterpriseContext to
|provide PassivationJob
|  +    * with a valid key because it may get freed to the
|InstancePool, then
|  +    * reused before the PassivationJob executes.
|  +    */
|  +    final Object getKey()
|  +    {
|  +            return m_key;
|       }
|       /**
|  -     * Returns the EnterpriseContext associated with this
|passivation job,
|  -     * so the bean that will be passivated.
|  -     * No need to synchronize access to this method, since the returned
|  -     * reference is immutable
|  -     */
|  +    * Returns the EnterpriseContext associated with this
|passivation job,
|  +    * so the bean that will be passivated.
|  +    * No need to synchronize access to this method, since the returned
|  +    * reference is immutable
|  +    */
|       final EnterpriseContext getEnterpriseContext()
|       {
|               return m_context;
|       }
|       /**
|  -     * Mark this job for cancellation.
|  -     * @see #isCancelled
|  -     */
|  +    * Mark this job for cancellation.
|  +    * @see #isCancelled
|  +    */
|       final synchronized void cancel()
|       {
|               m_cancelled = true;
|       }
|       /**
|  -     * Returns whether this job has been marked for cancellation
|  -     * @see #cancel
|  -     */
|  +    * Returns whether this job has been marked for cancellation
|  +    * @see #cancel
|  +    */
|       final synchronized boolean isCancelled()
|       {
|               return m_cancelled;
|       }
|       /**
|  -     * Mark this job as executed
|  -     * @see #isExecuted
|  -     */
|  +    * Mark this job as executed
|  +    * @see #isExecuted
|  +    */
|       final synchronized void executed()
|       {
|               m_executed = true;
|       }
|       /**
|  -     * Returns whether this job has been executed
|  -     * @see #executed
|  -     */
|  +    * Returns whether this job has been executed
|  +    * @see #executed
|  +    */
|       final synchronized boolean isExecuted()
|       {
|               return m_executed;
|  @@ -846,24 +862,24 @@
|   class PassivatorQueue extends WorkerQueue
|   {
|       /**
|  -     * Used for debug purposes, holds the scheduled passivation jobs
|  -     */
|  -//  private Map m_map = new HashMap();
|  -
|  +    * Used for debug purposes, holds the scheduled passivation jobs
|  +    */
|  +    //      private Map m_map = new HashMap();
|  +
|       /**
|  -     * Creates a new passivator queue with default thread name of
|  -     * "Passivator Thread".
|  -     */
|  +    * Creates a new passivator queue with default thread name of
|  +    * "Passivator Thread".
|  +    */
|       PassivatorQueue()
|       {
|               this("Passivator Thread", null);
|       }
|       /**
|  -     * Creates a new passivator queue with the given thread
|name and given
|  -     * context class loader. <br>
|  -     * @param threadName the name of the passivator thread
|  -     * @param cl the context class loader; if null the context
|class loader is not set.
|  -     */
|  +    * Creates a new passivator queue with the given thread name
|and given
|  +    * context class loader. <br>
|  +    * @param threadName the name of the passivator thread
|  +    * @param cl the context class loader; if null the context
|class loader is not set.
|  +    */
|       PassivatorQueue(String threadName, ClassLoader cl)
|       {
|               super(threadName);
|  @@ -873,43 +889,43 @@
|               }
|       }
|       /**
|  -     * Overridden for debug purposes
|  -     *//*
|  +    * Overridden for debug purposes
|  +    *//*
|       protected Executable getJobImpl() throws InterruptedException
|       {
|  -            PassivationJob j = (PassivationJob)super.getJobImpl();
|  -            EnterpriseContext ctx = j.getEnterpriseContext();
|  -            Object id = ctx.getId();
|  -            m_map.remove(id);
|  -            return j;
|  +    PassivationJob j = (PassivationJob)super.getJobImpl();
|  +    EnterpriseContext ctx = j.getEnterpriseContext();
|  +    Object id = ctx.getId();
|  +    m_map.remove(id);
|  +    return j;
|       }
|       */
|       /**
|  -     * Overridden for debug purposes
|  -     *//*
|  +    * Overridden for debug purposes
|  +    *//*
|       protected void putJobImpl(Executable job)
|       {
|  -            PassivationJob j = (PassivationJob)job;
|  -            EnterpriseContext ctx = j.getEnterpriseContext();
|  -            Object id = ctx.getId();
|  -            if (m_map.get(id) != null)
|  -            {
|  -                    // Here is a bug, job requests are
|scheduled only once per bean.
|  -                    System.err.println("DUPLICATE PASSIVATION
|JOB INSERTION FOR ID = " + ctx.getId());
|  -                    System.err.println("CTX isLocked: " +
|ctx.isLocked());
|  -                    System.err.println("CTX transaction: " +
|ctx.getTransaction());
|  -                    throw new IllegalStateException();
|  -            }
|  -            else
|  -            {
|  -                    m_map.put(id, job);
|  -            }
|  -            super.putJobImpl(job);
|  +    PassivationJob j = (PassivationJob)job;
|  +    EnterpriseContext ctx = j.getEnterpriseContext();
|  +    Object id = ctx.getId();
|  +    if (m_map.get(id) != null)
|  +    {
|  +    // Here is a bug, job requests are scheduled only once per bean.
|  +    System.err.println("DUPLICATE PASSIVATION JOB INSERTION FOR
|ID = " + ctx.getId());
|  +    System.err.println("CTX isLocked: " + ctx.isLocked());
|  +    System.err.println("CTX transaction: " + ctx.getTransaction());
|  +    throw new IllegalStateException();
|  +    }
|  +    else
|  +    {
|  +    m_map.put(id, job);
|  +    }
|  +    super.putJobImpl(job);
|       }
|       */
|       /**
|  -     * Logs exceptions thrown during job execution.
|  -     */
|  +    * Logs exceptions thrown during job execution.
|  +    */
|       protected void logJobException(Exception x)
|       {
|               // Log system exceptions
|
|
|
|
|_______________________________________________
|Jboss-development mailing list
|[EMAIL PROTECTED]
|http://lists.sourceforge.net/lists/listinfo/jboss-development



_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to