actually yes it will, did not change release and insert...
never mind
marcf
|-----Original Message-----
|From: marc fleury [mailto:[EMAIL PROTECTED]]
|Sent: Wednesday, June 27, 2001 1:52 AM
|To: [EMAIL PROTECTED]
|Subject: RE: [JBoss-dev] CVS update:
|jboss/src/main/org/jboss/ejb/plugins AbstractInstanceCache.java
|
|
|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