[jboss-cvs] JBossAS SVN: r60248 - branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/cache/tree.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sun Feb 4 00:05:42 EST 2007
Author: bstansberry at jboss.com
Date: 2007-02-04 00:05:42 -0500 (Sun, 04 Feb 2007)
New Revision: 60248
Modified:
branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/cache/tree/StatefulTreeCache.java
Log:
Sync up with trunk
Modified: branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/cache/tree/StatefulTreeCache.java
===================================================================
--- branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/cache/tree/StatefulTreeCache.java 2007-02-04 04:59:10 UTC (rev 60247)
+++ branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/cache/tree/StatefulTreeCache.java 2007-02-04 05:05:42 UTC (rev 60248)
@@ -21,7 +21,7 @@
*/
package org.jboss.ejb3.cache.tree;
-import java.util.HashMap;
+import java.util.Set;
import javax.ejb.EJBException;
import javax.ejb.NoSuchEJBException;
@@ -35,12 +35,13 @@
import org.jboss.cache.CacheException;
import org.jboss.cache.AbstractTreeCacheListener;
import org.jboss.cache.DataNode;
-import org.jboss.cache.Node;
import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheMBean;
import org.jboss.ejb3.Container;
+import org.jboss.ejb3.EJBContainer;
import org.jboss.ejb3.Pool;
import org.jboss.ejb3.cache.ClusteredStatefulCache;
+import org.jboss.ejb3.stateful.ProxiedStatefulBeanContext;
import org.jboss.ejb3.stateful.StatefulBeanContext;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.mx.util.MBeanServerLocator;
@@ -77,7 +78,7 @@
try
{
ctx = (StatefulBeanContext) pool.get();
- cache.put(cacheNode + "/" + ctx.getId(), "bean", ctx);
+ cache.put(new Fqn(cacheNode, ctx.getId().toString()), "bean", ctx);
ctx.inUse = true;
ctx.lastUsed = System.currentTimeMillis();
++createCount;
@@ -99,7 +100,7 @@
try
{
ctx = (StatefulBeanContext) pool.get(initTypes, initValues);
- Fqn id = Fqn.fromString(cacheNode + "/" + ctx.getId());
+ Fqn id = new Fqn(cacheNode, ctx.getId().toString());
cache.put(id, "bean", ctx);
ctx.inUse = true;
ctx.lastUsed = System.currentTimeMillis();
@@ -119,7 +120,7 @@
public StatefulBeanContext get(Object key) throws EJBException
{
StatefulBeanContext entry = null;
- Fqn id = Fqn.fromString(cacheNode + "/" +key);
+ Fqn id = new Fqn(cacheNode, key.toString());
try
{
Object obj = cache.get(id, "bean");
@@ -127,7 +128,8 @@
}
catch (CacheException e)
{
- throw new RuntimeException(e);
+ RuntimeException re = convertToRuntimeException(e);
+ throw re;
}
if (entry == null)
{
@@ -136,32 +138,33 @@
entry.inUse = true;
// Mark it to eviction thread that don't passivate it yet.
evictRegionManager.markNodeCurrentlyInUse(id, MarkInUseWaitTime);
- if(log.isDebugEnabled())
+ entry.lastUsed = System.currentTimeMillis();
+
+ if(log.isTraceEnabled())
{
- log.debug("get: retrieved bean with cache id " +id.toString());
+ log.trace("get: retrieved bean with cache id " +id.toString());
}
-
- entry.lastUsed = System.currentTimeMillis();
return entry;
}
public void remove(Object key)
{
StatefulBeanContext ctx = null;
- Fqn id = Fqn.fromString(cacheNode + "/" +key);
+ Fqn id = new Fqn(cacheNode, key.toString());
try
{
- if(log.isDebugEnabled())
+ if(log.isTraceEnabled())
{
- log.debug("remove: cache id " +id.toString());
+ log.trace("remove: cache id " +id.toString());
}
cache.remove(id);
}
catch (CacheException e)
{
- throw new RuntimeException(e);
+ RuntimeException re = convertToRuntimeException(e);
+ throw re;
}
-// if (ctx != null) pool.remove(ctx);
+ if (ctx != null) pool.remove(ctx);
}
public void finished(StatefulBeanContext ctx)
@@ -170,7 +173,7 @@
{
ctx.inUse = false;
ctx.lastUsed = System.currentTimeMillis();
- Fqn id = Fqn.fromString(cacheNode + "/" + ctx.getId());
+ Fqn id = new Fqn(cacheNode, ctx.getId().toString());
// OK, it is free to passivate now.
evictRegionManager.unmarkNodeCurrentlyInUse(id);
}
@@ -180,11 +183,24 @@
{
try
{
- cache.put(cacheNode + "/" + ctx.getId(), "bean", ctx);
+ // Don't replicate proxies, as they are in the cache
+ // as elements of their containing bean context
+ // TODO -- if this is a ProxiedStatefulBeanContext
+ // should we replicate the parent context, since that's where
+ // the data is?
+ if (!(ctx instanceof ProxiedStatefulBeanContext))
+ {
+ cache.put(new Fqn(cacheNode, ctx.getId().toString()), "bean", ctx);
+ }
+ else if (log.isTraceEnabled())
+ {
+ log.trace("replicate(): ignoring replicate call for proxy to " + ctx.getId());
+ }
}
catch (CacheException e)
{
- throw new RuntimeException(e);
+ RuntimeException re = convertToRuntimeException(e);
+ throw re;
}
}
@@ -218,9 +234,11 @@
public void start()
{
- // register to listen for cache event
- // TODO this approach may not be scalable when there are many beans since then we will need to go thru
- // N listeners to figure out which this event this belongs to.
+ // register to listen for cache events
+
+ // TODO this approach may not be scalable when there are many beans
+ // since then we will need to go thru N listeners to figure out which
+ // one this event belongs to. Consider having a singleton listener
listener = new ClusteredStatefulCacheListener();
cache.addTreeCacheListener(listener);
}
@@ -229,29 +247,39 @@
{
// Remove the listener
cache.removeTreeCacheListener(listener);
+
+ // BES 11/16/2006 uncomment if we switch to per-region marshalling
+ // If we do, we don't need to remove the node below; deactivate() does it
+// if (region != null)
+// {
+// region.deactivate();
+// region.unregisterContextClassLoader();
+// }
+ // Remove the eviction region
+ RegionManager rm = cache.getEvictionRegionManager();
+ rm.removeRegion(cacheNode);
+
Option opt = new Option();
opt.setCacheModeLocal(true);
try {
// remove locally.
cache.remove(cacheNode, opt);
- } catch (CacheException e) {
+ }
+ catch (CacheException e)
+ {
log.error("Stop(): can't remove bean from the underlying distributed cache");
}
- // Remove the eviction region
- RegionManager rm = cache.getEvictionRegionManager();
- rm.removeRegion(cacheNode);
-
- log.info("stop(): StatefulTreeCache stopped successfully for " +cacheNode);
+ log.debug("stop(): StatefulTreeCache stopped successfully for " +cacheNode);
}
public int getCacheSize()
{
try
{
- Node node = cache.get(cacheNode);
- return node.getChildren().size();
+ Set children = cache.getChildrenNames(cacheNode);
+ return (children == null ? 0 : children.size());
} catch (CacheException e)
{
e.printStackTrace();
@@ -268,71 +296,127 @@
{
return passivatedCount;
}
+
+ /**
+ * Creates a RuntimeException, but doesn't pass CacheException as the cause
+ * as it is a type that likely doesn't exist on a client.
+ * Instead creates a RuntimeException with the original exception's
+ * stack trace.
+ */
+ private RuntimeException convertToRuntimeException(CacheException e)
+ {
+ RuntimeException re = new RuntimeException(e.getClass().getName() + " " + e.getMessage());
+ re.setStackTrace(e.getStackTrace());
+ return re;
+ }
/**
- * A TreeCacheListener. Note that extends it from AbstractTreeCacheListener is a bit heavy since
- * it will get all the treecache events (instead of just passivation/activation). But we will have to
- * wait untill JBossCache2.0 for the refactoring then.
+ * A TreeCacheListener that allows us to get notifications of passivations and
+ * activations and thus notify the cached StatefulBeanContext.
*/
public class ClusteredStatefulCacheListener extends AbstractTreeCacheListener
{
protected Logger log = Logger.getLogger(ClusteredStatefulCacheListener.class);
- public void nodeActivate(Fqn fqn, boolean pre) {
- if(pre) return; // we are not interested in postActivate event
+ @Override
+ public void nodeActivate(Fqn fqn, boolean pre)
+ {
+ // Ignore everything but "post" events for nodes in our region
+ if(pre) return;
if(fqn.size() != FQN_SIZE) return;
- if(!fqn.isChildOrEquals(cacheNode)) return; // don't care about fqn that doesn't belong to me.
+ if(!fqn.isChildOrEquals(cacheNode)) return;
StatefulBeanContext bean = null;
try {
// TODO Can this cause deadlock in the cache level? Should be ok but need review.
bean = (StatefulBeanContext) cache.get(fqn, "bean");
- } catch (CacheException e) {
+ }
+ catch (CacheException e)
+ {
log.error("nodeActivate(): can't retrieve bean instance from: " +fqn + " with exception: " +e);
return;
}
+
if(bean == null)
{
- throw new IllegalStateException("StatefuleTreeCache.nodeActivate(): null bean instance.");
+ throw new IllegalStateException("nodeActivate(): null bean instance.");
}
--passivatedCount;
-// log.debug("nodeActivate(): send postActivate event on fqn: " +fqn);
if(log.isTraceEnabled())
{
- log.trace("nodeActivate(): send postActivate event on fqn: " +fqn);
+ log.trace("nodeActivate(): sending postActivate event on fqn: " +fqn);
}
bean.postActivate();
}
- public void nodePassivate(Fqn fqn, boolean pre) {
- if(!pre) return; // we are not interested in postPassivate event
+ @Override
+ public void nodePassivate(Fqn fqn, boolean pre)
+ {
+ // Ignore everything but "pre" events for nodes in our region
+ if(!pre) return;
if(fqn.size() != FQN_SIZE) return;
- if(!fqn.isChildOrEquals(cacheNode)) return; // don't care about fqn that doesn't belong to me.
+ if(!fqn.isChildOrEquals(cacheNode)) return;
- try {
- // TODO Can this cause deadlock in the cache level? Should be ok but need review.
- Node node = cache.get(fqn);
- StatefulBeanContext bean = (StatefulBeanContext) node.getData().get("bean");
- if (bean != null)
+ StatefulBeanContext bean = null;
+ try
+ {
+ // EJBTHREE-746 Use peek to bypass interceptors and thus avoid generating another
+ // eviction event (which will cause another attempt to passivate)
+ // Caller thread (eviction) already has a lock on the node
+ // With JBC 2.0 there is a BypassInterceptors Option we can use
+ DataNode node = cache.peek(fqn);
+ if (node != null)
{
- bean.prePassivate();
- ++passivatedCount;
+ bean = (StatefulBeanContext) node.get("bean");
+ if (bean != null)
+ {
+ if (bean.inUse)
+ {
+ // Abort the eviction
+ throw new IllegalStateException("Cannot passivate bean " + fqn + " -- it is currently in use");
+ }
+ if(log.isTraceEnabled())
+ {
+ log.trace("nodePassivate(): send prePassivate event to bean at fqn: " +fqn);
+ }
+ bean.prePassivate();
+ ++passivatedCount;
+ }
}
-
- } catch (CacheException e) {
- log.error("nodePassivate(): can't retrieve bean instance from: " +fqn + " with exception: " +e);
- return;
}
-
-// log.debug("nodePassivate(): send prePassivate event on fqn: " +fqn);
- if(log.isTraceEnabled())
+ catch (NoSuchEJBException e)
{
- log.trace("nodePassivate(): send prePassivate event on fqn: " +fqn);
+ if (bean instanceof ProxiedStatefulBeanContext)
+ {
+ // This is probably an orphaned proxy; double check and remove it
+ try
+ {
+ bean.getContainedIn();
+ // If that didn't fail, it's not an orphan
+ throw e;
+ }
+ catch (NoSuchEJBException n)
+ {
+ log.debug("nodePassivate(): removing orphaned proxy at " + fqn);
+ try
+ {
+ cache.remove(fqn);
+ }
+ catch (CacheException c)
+ {
+ log.error("nodePassivate(): could not remove orphaned proxy at " + fqn, c);
+ // Just fall through and let the eviction try
+ }
+ }
+ }
+ else
+ {
+ throw e;
+ }
}
-
}
}
}
More information about the jboss-cvs-commits
mailing list