[jboss-cvs] JBossAS SVN: r71452 - in projects/ejb3/branches/cluster-dev/cache-jbc2: src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2 and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Mar 30 11:16:00 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-03-30 11:16:00 -0400 (Sun, 30 Mar 2008)
New Revision: 71452

Modified:
   projects/ejb3/branches/cluster-dev/cache-jbc2/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/impl/backing/jbc2/GroupedPassivatingUnitTestCase.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/jbc2/mock/JBC2MockClusterMember.java
Log:
[EJBTHREE-1026] Implement JBC2 passivation/expiration


Property changes on: projects/ejb3/branches/cluster-dev/cache-jbc2
___________________________________________________________________
Name: svn:ignore
   - .settings
eclipse-target
target
.classpath
.project

   + .settings
eclipse-target
target
.classpath
.project
${jboss.server.data.dir}${


Modified: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java	2008-03-30 15:13:12 UTC (rev 71451)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java	2008-03-30 15:16:00 UTC (rev 71452)
@@ -33,10 +33,12 @@
 import org.jboss.cache.notifications.annotation.NodeRemoved;
 import org.jboss.cache.notifications.annotation.NodeVisited;
 import org.jboss.cache.notifications.event.NodeActivatedEvent;
+import org.jboss.cache.notifications.event.NodeEvent;
 import org.jboss.cache.notifications.event.NodeModifiedEvent;
 import org.jboss.cache.notifications.event.NodePassivatedEvent;
 import org.jboss.cache.notifications.event.NodeRemovedEvent;
 import org.jboss.cache.notifications.event.NodeVisitedEvent;
+import org.jboss.logging.Logger;
 
 /**
  * Single {@link CacheListener} that handles event Fqn parsing and then
@@ -48,7 +50,9 @@
  */
 @CacheListener
 public class ClusteredCacheListener
-{
+{   
+   private static final Logger log = Logger.getLogger(ClusteredCacheListener.class);
+
    public static interface RegionHandler
    {
       void nodeVisited(OwnedItem ownedItem, NodeVisitedEvent event);
@@ -88,7 +92,7 @@
       if (event.isPre())
          return;
       
-      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy, event.isOriginLocal());
       RegionHandler handler = getRegionHandler(oi);
       if (handler != null)
       {
@@ -102,7 +106,8 @@
       if (event.isPre() || NodeModifiedEvent.ModificationType.REMOVE_DATA == event.getModificationType())
          return;
       
-      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy, event.isOriginLocal());
+      logEvent(oi, event);
       RegionHandler handler = getRegionHandler(oi);
       if (handler != null)
       {
@@ -117,7 +122,8 @@
       if (!event.isPre())
          return; 
       
-      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy, event.isOriginLocal());
+      logEvent(oi, event);
       RegionHandler handler = getRegionHandler(oi);
       if (handler != null)
       {
@@ -130,7 +136,8 @@
    {
       if(event.isPre()) return; 
       
-      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy, event.isOriginLocal());
+      logEvent(oi, event);
       RegionHandler handler = getRegionHandler(oi);
       if (handler != null)
       {
@@ -143,11 +150,20 @@
    {
       if(event.isPre()) return;
       
-      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy, event.isOriginLocal());
+      logEvent(oi, event);
       RegionHandler handler = getRegionHandler(oi);
       if (handler != null)
       {
          handler.nodePassivated(oi, event);
       }
    }
+   
+   private void logEvent(OwnedItem oi, NodeEvent event)
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("Event for " + oi + " -- " + event);
+      }
+   }
 }

Modified: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java	2008-03-30 15:13:12 UTC (rev 71451)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java	2008-03-30 15:16:00 UTC (rev 71452)
@@ -24,7 +24,6 @@
 
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -110,8 +109,6 @@
    private ClusteredCacheListener listener;
    /** Handler for listener events related to our region */
    private RegionHandlerImpl regionHandler;
-   /** Our logger */
-   private final Logger log;
    /** Our "buckets". See above */
    private String[] hashBuckets = DEFAULT_HASH_BUCKETS;
    /** Whether our cache is using buddy replication */
@@ -119,9 +116,9 @@
    /** Whether our RegionHandlerImpl should track visits */
    private boolean trackVisits;
    /** Last-use timestamps of in-memory items.  Used for passivation and expiration*/
-   private final ConcurrentMap<OwnedItem, Long> inMemoryItems;
+   private final ConcurrentMap<OwnedItem, OwnedItem> inMemoryItems;
    /** Last-use timestamps of passivated items.  Used for expiration*/
-   private final ConcurrentMap<OwnedItem, Long> passivatedItems;
+   private final ConcurrentMap<OwnedItem, OwnedItem> passivatedItems;
    
    /**
     * Create a new JBCIntegratedObjectStore.
@@ -148,16 +145,19 @@
       this.cacheConfigName = cacheConfigName;
       this.keyBase = name;
 
-      this.log = Logger.getLogger(getClass().getName() + "." + name);
+      this.log = Logger.getLogger(getClass().getName() + "-" + name);
       this.regionRootFqn = new Fqn<Object>(new Object[] { FQN_BASE, this.keyBase });
       
-      this.inMemoryItems = new ConcurrentHashMap<OwnedItem, Long>();
-      this.passivatedItems = new ConcurrentHashMap<OwnedItem, Long>();
+      this.inMemoryItems = new ConcurrentHashMap<OwnedItem, OwnedItem>();
+      this.passivatedItems = new ConcurrentHashMap<OwnedItem, OwnedItem>();
    }
 
    public boolean isClustered()
    {
-      return jbc.getConfiguration().getCacheMode() != Configuration.CacheMode.LOCAL;
+      if (jbc == null)
+         return true; // assume yes
+      else
+         return jbc.getConfiguration().getCacheMode() != Configuration.CacheMode.LOCAL;
    }
 
    public T get(Object key)
@@ -191,6 +191,9 @@
    {
       try
       {
+         if (log.isTraceEnabled())
+            log.trace("insert: " + entry.getId());
+         
          jbc.put(getFqn(entry.getId(), false), KEY, entry);
       }
       catch (CacheException e)
@@ -202,6 +205,9 @@
 
    public void passivate(T entry)
    {
+      if (log.isTraceEnabled())
+         log.trace("passivate: " + entry.getId());
+      
       Fqn<Object> id = getFqn(entry.getId(), false);
       jbc.evict(id);
    }
@@ -240,6 +246,10 @@
 
    public void update(T entry, boolean modified)
    {
+      if (log.isTraceEnabled())
+         log.trace("update: " + entry.getId() + 
+                   (modified ? " modified" : " unmodified"));
+      
       if (modified)
       {
          try
@@ -254,8 +264,9 @@
       }
       else
       {
-         OwnedItem oi = new OwnedItem(null, entry.getId(), regionRootFqn);
-         inMemoryItems.put(oi, new Long(entry.getLastUsed()));
+         OwnedItem oi = new OwnedItem(entry.getId(), regionRootFqn);
+         oi.setLastUsed(entry.getLastUsed());
+         inMemoryItems.put(oi, oi);
       }
    }
 
@@ -310,6 +321,7 @@
             break;
          }
       }
+      
       if (listener == null)
       {
          listener = new ClusteredCacheListener(usingBuddyRepl);
@@ -402,16 +414,17 @@
             T entry = (T) child.get(KEY);
             if (entry != null)
             {
-               OwnedItem oi = OwnedItem.getOwnedItem(child.getFqn(), usingBuddyRepl);
+               boolean localEvent = false; // we don't own any of these
+               OwnedItem oi = OwnedItem.getOwnedItem(child.getFqn(), usingBuddyRepl, localEvent);
                if (entry.isPrePassivated())
                {
                   jbc.evict(child.getFqn()); // we'll get a listener event for this
                }
                else
                {
-                  long lastUsed = (entry.getLastUsed() == 0) ? System.currentTimeMillis() : entry.getLastUsed();
+                  oi.setLastUsed(entry.getLastUsed() == 0 ? System.currentTimeMillis() : entry.getLastUsed());
                   // Use putIfAbsent so we don't overwrite listener events
-                  inMemoryItems.putIfAbsent(oi, lastUsed);
+                  inMemoryItems.putIfAbsent(oi, oi);
                }
             }
          }
@@ -428,23 +441,18 @@
          {
             // Remove the listener
             if (listener != null && regionHandler != null && listener.removeRegionHandler(regionRootFqn))
+            {
+               // No more regions registered, so remove the listener
                jbc.removeCacheListener(listener);
+            }
+            
+            // Null the listener so we have to re-check the cache is we start() again
+            listener = null;
    
             // Remove locally. We do this to clean up the persistent store,
             // which is not affected by the inactivateRegion call below.
             cleanBeanRegion();
    
-            try {
-               // Remove locally. We do this to clean up the persistent store,
-               // which is not affected by the region.deactivate call below.
-               jbc.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
-               jbc.removeNode(regionRootFqn);
-            }
-            catch (CacheException e)
-            {
-               log.error("stop(): can't remove bean from the underlying distributed cache");
-            }
-   
             if (region != null)
             {
                region.deactivate();
@@ -466,15 +474,57 @@
    }
 
    @Override
-   protected void processExpiration(OwnedItem item)
+   protected void processExpiration(OwnedItem ownedItem, long lastUse)
    {
-      log.error("implement processExpiration");
+      if (!isRunning())
+         return;
+      
+      // We only remove items we control
+      if (OwnedItem.LOCAL_OWNER.equals(ownedItem.getOwner()))
+      {
+         getPassivatingCache().remove(ownedItem.getId());
+      }
+      
+      // TODO -- add some mechanism for *eventually* removing items we
+      // don't control, in case their owner died. Eventually meaning
+      // after a day or so.
    }
 
    @Override
-   protected void processPassivation(OwnedItem item)
+   protected void processPassivation(OwnedItem ownedItem, long lastUse)
    {
-      log.error("implement processPassivation");     
+      if (!isRunning())
+         return;
+      
+      synchronized (ownedItem)
+      {
+         String owner = ownedItem.getOwner();
+         if (OwnedItem.LOCAL_OWNER.equals(owner))
+         {
+            getPassivatingCache().passivate(ownedItem.getId());
+         }
+         else
+         {
+            // No callbacks; the item is serialized and under the control of 
+            // another cache. We just want it out of our memory
+            
+            // FIXME race condition here; we might have taken ownership!
+            
+            Fqn<Object> id = null;
+            if (OwnedItem.REMOTE_OWNER.equals(owner))
+            {
+               id = getFqn(ownedItem.getId(), false);
+            }
+            else {
+               id = getBuddyFqn(ownedItem.getId(), ownedItem.getOwner());
+            }
+            
+            if (log.isTraceEnabled())
+               log.trace("evicting remotely owned item " + ownedItem.getId());
+            
+            jbc.evict(id);
+         }
+      }
    }
 
    @Override
@@ -482,9 +532,9 @@
    protected CacheableTimestamp<OwnedItem>[] getInMemoryEntries()
    {     
       Set<CacheableTimestamp<OwnedItem>> set = new HashSet<CacheableTimestamp<OwnedItem>>();
-      for (Map.Entry<OwnedItem, Long> entry : inMemoryItems.entrySet())
+      for (OwnedItem ownedItem : inMemoryItems.values())
       {
-         set.add(new CacheableTimestamp<OwnedItem>(entry.getKey(), entry.getValue()));
+         set.add(new CacheableTimestamp<OwnedItem>(ownedItem, ownedItem.getLastUsed()));
       }
       CacheableTimestamp<OwnedItem>[] array = new CacheableTimestamp[set.size()];
       array = set.toArray(array);
@@ -497,17 +547,17 @@
    protected CacheableTimestamp<OwnedItem>[] getAllEntries()
    {     
       Set<CacheableTimestamp<OwnedItem>> set = new HashSet<CacheableTimestamp<OwnedItem>>();
-      for (Map.Entry<OwnedItem, Long> entry : inMemoryItems.entrySet())
+      for (OwnedItem ownedItem : inMemoryItems.values())
       {
-         set.add(new CacheableTimestamp<OwnedItem>(entry.getKey(), entry.getValue()));
+         set.add(new CacheableTimestamp<OwnedItem>(ownedItem, ownedItem.getLastUsed()));
       }
       CacheableTimestamp<Object>[] inMemory = new CacheableTimestamp[set.size()];
       inMemory = set.toArray(inMemory);   
       
       set = new HashSet<CacheableTimestamp<OwnedItem>>();
-      for (Map.Entry<OwnedItem, Long> entry : passivatedItems.entrySet())
+      for (OwnedItem ownedItem : passivatedItems.values())
       {
-         set.add(new CacheableTimestamp<OwnedItem>(entry.getKey(), entry.getValue()));
+         set.add(new CacheableTimestamp<OwnedItem>(ownedItem, ownedItem.getLastUsed()));
       }
       CacheableTimestamp<OwnedItem>[] passivated = new CacheableTimestamp[set.size()];
       passivated = set.toArray(passivated);
@@ -522,6 +572,23 @@
    private Fqn<Object> getFqn(Object id, boolean regionRelative)
    {
       String beanId = id.toString();
+      int index = getIndexForId(id, beanId);
+
+      if (regionRelative)
+         return new Fqn<Object>( new Object[] {hashBuckets[index], beanId} );
+      else
+         return new Fqn<Object>(regionRootFqn, hashBuckets[index], beanId);
+   }
+   
+   private Fqn<Object> getBuddyFqn(Object id, Object owner)
+   {
+      assert owner != null : "owner cannot be null for a buddy backup Fqn";
+      
+      return new Fqn<Object>(new Object[] { BuddyManager.BUDDY_BACKUP_SUBTREE, owner, FQN_BASE, keyBase, id});
+   }
+   
+   private int getIndexForId(Object id, String stringForm)
+   {
       int index;
       if (id instanceof GUID)
       {
@@ -529,13 +596,10 @@
       }
       else
       {
-         index = (beanId.hashCode()& 0x7FFFFFFF) % hashBuckets.length;
+         index = (stringForm.hashCode()& 0x7FFFFFFF) % hashBuckets.length;
       }
-
-      if (regionRelative)
-         return new Fqn<Object>( new Object[] {hashBuckets[index], beanId} );
-      else
-         return new Fqn<Object>(regionRootFqn, hashBuckets[index], beanId);
+      
+      return index;
    }
 
    /**
@@ -573,7 +637,16 @@
       public void nodeVisited(OwnedItem oi, NodeVisitedEvent event)
       {
          if (trackVisits)
-            inMemoryItems.put(oi, System.currentTimeMillis());         
+         {
+            long now = System.currentTimeMillis();
+            oi.setLastUsed(now);
+            OwnedItem existing = inMemoryItems.putIfAbsent(oi, oi);
+            if (existing != null && !existing.isPassivating())
+            {
+               existing.setLastUsed(now);
+               existing.setLocallyOwned(event.isOriginLocal());
+            }               
+         }
       }
       
       public void nodeModified(OwnedItem oi, NodeModifiedEvent event)
@@ -584,7 +657,13 @@
          {
             long lastUsed = entry.getLastUsed();
             lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
-            inMemoryItems.put(oi, lastUsed);
+            oi.setLastUsed(lastUsed);
+            OwnedItem existing = inMemoryItems.putIfAbsent(oi, oi);
+            if (existing != null && !existing.isPassivating())
+            {
+               existing.setLastUsed(lastUsed);
+               existing.setLocallyOwned(event.isOriginLocal());
+            }               
             
             if (log.isTraceEnabled())
                log.trace(oi + " modified " + (event.isOriginLocal() ? " locally" : "remotely") );
@@ -612,9 +691,16 @@
          if (entry != null)
          {
             long lastUsed = entry.getLastUsed();
-            lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
-            inMemoryItems.put(oi, lastUsed);
-            passivatedItems.remove(oi);
+            oi.setLastUsed(lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
+            OwnedItem existing = inMemoryItems.putIfAbsent(oi, oi);
+            if (existing == null)
+            {
+               passivatedItems.remove(oi);
+            }
+            else if (!existing.isPassivating())
+            {
+               existing.setLocallyOwned(event.isOriginLocal());
+            }
             
             if (log.isTraceEnabled())
                log.trace(oi + " activated -- " + (event.isOriginLocal() ? " local" : "remote") );
@@ -628,9 +714,12 @@
          if (entry != null)
          {
             long lastUsed = entry.getLastUsed();
-            lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
-            passivatedItems.put(oi, lastUsed);
-            inMemoryItems.remove(oi);
+            oi.setLastUsed(lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
+            OwnedItem existing = passivatedItems.putIfAbsent(oi, oi);
+            if (existing == null)
+            {
+               inMemoryItems.remove(oi);
+            }
             
             if (log.isTraceEnabled())
                log.trace(oi + " passivated");

Modified: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java	2008-03-30 15:13:12 UTC (rev 71451)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java	2008-03-30 15:16:00 UTC (rev 71452)
@@ -34,30 +34,38 @@
  */
 public class OwnedItem
 {
+   public static final String LOCAL_OWNER = "local_owner";
+   public static final String REMOTE_OWNER = "remote_owner";
+   
    private static final int FQN_SIZE = JBCIntegratedObjectStore.FQN_SIZE;
    private static final int KEY_INDEX = FQN_SIZE - 1;
+   private static final int REGION_INDEX = FQN_SIZE - 2;
    private static final int OWNER_INDEX = 1;
    private static final int BR_FQN_SIZE = FQN_SIZE + OWNER_INDEX + 1;
    private static final int BR_KEY_INDEX = BR_FQN_SIZE - 1;
+   private static final int BR_REGION_INDEX = BR_FQN_SIZE - 2;
    
    private final String owner;
    private final Object id;
    private final Fqn<Object> region;
+   private boolean passivating;
+   private volatile boolean locallyOwned;
+   private long lastUsed;
    
    /**
     * Generates an OwnedItem from the given Fqn if the Fqn is a logical
     * child of <code>base</code>
     * 
     * @param fqn  the Fqn
-    * @param base the base Fqn
     * @param checkBuddy <code>true</code> if it is possible that <code>fqn</code>
     *                   belongs to a {@link BuddyManager#BUDDY_BACKUP_SUBTREE_FQN buddy-backup subtree}
-    *                   
+    * @param localOwner TODO
+    * @param base the base Fqn
     * @return an OwnedItem or <code>null</code> if <code>fqn</code> is not a
     *         logical child of <code>base</code>
     */
    @SuppressWarnings("unchecked")
-   public static OwnedItem getOwnedItem(Fqn fqn, boolean checkBuddy)
+   public static OwnedItem getOwnedItem(Fqn fqn, boolean checkBuddy, boolean localEvent)
    {
       int size = fqn.size();
       if (size < FQN_SIZE)
@@ -74,39 +82,47 @@
          {
             key = fqn.get(BR_KEY_INDEX);
             owner = (String) fqn.get(OWNER_INDEX);
-            region = fqn.getSubFqn(OWNER_INDEX, BR_KEY_INDEX);
+            region = fqn.getSubFqn(OWNER_INDEX + 1, BR_REGION_INDEX);
          }
       }
       else if (size == FQN_SIZE)
       {
-         region = fqn.getParent();
+         region = fqn.getSubFqn(0, REGION_INDEX);
          key = fqn.get(KEY_INDEX);
       }
       
-      return (key == null ? null : new OwnedItem(owner, key, region));
+      return (key == null ? null : new OwnedItem(owner, key, region, localEvent));
    }
    
-   public OwnedItem(String owner, Object id, Fqn<Object> region)
+   public OwnedItem(Object id, Fqn<Object> region)
    {
+      this(null, id, region, true);
+   }
+   
+   private OwnedItem(String owner, Object id, Fqn<Object> region, boolean locallyOwned)
+   {
       assert id != null : "id is null";
       assert region != null : "region is null";
       
       this.owner = owner;
       this.id = id;
       this.region = region;
+      this.locallyOwned = locallyOwned;
    }
    
    /**
-    * Gets the logical "owner" of the item.  A value of <code>null</code>
-    * means either there is no logical owner or this process is the owner.
-    * (Basically it means the item is stored in the main area of a JBoss CAche
-    * tree, not in a named buddy-backup region.)
+    * Gets the logical "owner" of the item.  
     * 
-    * @return
+    * @return A value of {@link #LOCAL_OWNER} means this process is the owner. 
+    *         A value of {@link #REMOTE_OWNER} means the cache is using total 
+    *         replication, but some other process is the owner. Any other 
+    *         value means buddy replication is in use and the object is 
+    *         owned by another node; the returned value identifies the 
+    *         owner's buddy backup tree. Will not return <code>null</code>.
     */
    public String getOwner()
    {
-      return owner;
+      return owner != null ? owner : (locallyOwned ? LOCAL_OWNER : REMOTE_OWNER);
    }
 
    /**
@@ -139,6 +155,45 @@
       }
    }
 
+   public boolean isPassivating()
+   {
+      return passivating;
+   }
+
+   public void setPassivating(boolean passivating)
+   {
+      this.passivating = passivating;
+   }
+
+   public boolean isLocallyOwned()
+   {
+      return locallyOwned;
+   }
+
+   public void setLocallyOwned(boolean locallyOwned)
+   {
+      if (this.locallyOwned != locallyOwned)
+      {
+         synchronized (this)
+         {
+            this.locallyOwned = locallyOwned;
+         }
+      }      
+   }
+
+   public long getLastUsed()
+   {
+      return lastUsed;
+   }
+
+   public void setLastUsed(long lastUsed)
+   {
+      if (lastUsed > this.lastUsed)
+      {
+         this.lastUsed = lastUsed;
+      }
+   }
+
    @Override
    public boolean equals(Object obj)
    {

Modified: projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/impl/backing/jbc2/GroupedPassivatingUnitTestCase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/impl/backing/jbc2/GroupedPassivatingUnitTestCase.java	2008-03-30 15:13:12 UTC (rev 71451)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/impl/backing/jbc2/GroupedPassivatingUnitTestCase.java	2008-03-30 15:16:00 UTC (rev 71452)
@@ -194,6 +194,9 @@
          cluster.getNode0().restoreTCCL();         
       }
       
+      // Let async messages propagate
+      sleep(200);
+      
       // Switch to second node
       cluster.getNode1().setTCCL();
       try
@@ -211,13 +214,13 @@
       }
       catch (Exception e)
       {
-         container1B.stop();
-         container2B.stop();
          throw e;
       }
       finally
       {
-         cluster.getNode1().restoreTCCL();         
+         cluster.getNode1().restoreTCCL();    
+         container1B.stop();
+         container2B.stop();     
       }
    }
 }

Modified: projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/jbc2/mock/JBC2MockClusterMember.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/jbc2/mock/JBC2MockClusterMember.java	2008-03-30 15:13:12 UTC (rev 71451)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/org/jboss/ejb3/test/cache/jbc2/mock/JBC2MockClusterMember.java	2008-03-30 15:16:00 UTC (rev 71452)
@@ -37,12 +37,15 @@
 import org.jboss.ejb3.test.cache.mock.MockBeanContext;
 import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
 import org.jboss.ejb3.test.cache.mock.MockEjb3System;
+import org.jboss.logging.Logger;
 
 /**
  * @author Brian Stansberry
  */
 public class JBC2MockClusterMember extends MockEjb3System
 {
+   private static final Logger log = Logger.getLogger(JBC2MockClusterMember.class);   
+   
    public static final String DEFAULT_JBC_CONFIG = "standard-session";
    private static final Map<String, String> DEFAULT_ALIAS_MAP = new HashMap<String, String>();
    
@@ -117,6 +120,8 @@
    {
       if (localClassLoader == Thread.currentThread().getContextClassLoader())
          return false;
+      
+      log.debug("Setting TCCL to " + localClassLoader);
       Thread.currentThread().setContextClassLoader(localClassLoader);
       return true;
    }
@@ -125,8 +130,9 @@
    {
       ClassLoader current = Thread.currentThread().getContextClassLoader();
       if (current == localClassLoader)
-      {
+      {         
          Thread.currentThread().setContextClassLoader(localClassLoader.getParent());
+         log.debug("Restored TCCL to " + localClassLoader.getParent());
       }
       else if (current != localClassLoader.getParent())
       {




More information about the jboss-cvs-commits mailing list