[jbosscache-commits] JBoss Cache SVN: r5918 - in core/trunk/src: main/java/org/jboss/cache/buddyreplication and 2 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Thu May 29 11:08:09 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-05-29 11:08:09 -0400 (Thu, 29 May 2008)
New Revision: 5918

Added:
   core/trunk/src/main/java/org/jboss/cache/RegionEmptyException.java
   core/trunk/src/test/java/org/jboss/cache/buddyreplication/EmptyRegionTest.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
   core/trunk/src/main/java/org/jboss/cache/statetransfer/StateTransferManager.java
Log:
JBCACHE-1349:  Buddy replication state transfer fails if a marshalling region is empty

Added: core/trunk/src/main/java/org/jboss/cache/RegionEmptyException.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RegionEmptyException.java	                        (rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/RegionEmptyException.java	2008-05-29 15:08:09 UTC (rev 5918)
@@ -0,0 +1,29 @@
+package org.jboss.cache;
+
+/**
+ * Exception to represent a region being empty when state was expected in that region.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 2.2.0
+ */
+public class RegionEmptyException extends CacheException
+{
+   public RegionEmptyException()
+   {
+   }
+
+   public RegionEmptyException(Throwable cause)
+   {
+      super(cause);
+   }
+
+   public RegionEmptyException(String msg)
+   {
+      super(msg);
+   }
+
+   public RegionEmptyException(String msg, Throwable cause)
+   {
+      super(msg, cause);
+   }
+}

Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java	2008-05-29 14:49:10 UTC (rev 5917)
+++ core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java	2008-05-29 15:08:09 UTC (rev 5918)
@@ -15,6 +15,7 @@
 import org.jboss.cache.Node;
 import org.jboss.cache.RPCManager;
 import org.jboss.cache.Region;
+import org.jboss.cache.RegionEmptyException;
 import org.jboss.cache.RegionManager;
 import org.jboss.cache.commands.ReplicableCommand;
 import org.jboss.cache.commands.VisitableCommand;
@@ -788,10 +789,7 @@
                {
                   Fqn f = r.getFqn();
                   state = acquireState(f);
-                  if (state != null)
-                  {
-                     stateMap.put(f, state);
-                  }
+                  if (state != null) stateMap.put(f, state);
                }
             }
             else if (!configuration.isInactiveOnStartup())
@@ -885,7 +883,10 @@
             byte[] state = generateState(fqn, timeouts[i], force);
             if (log.isDebugEnabled())
             {
-               log.debug("acquireState(): got state");
+               if (state == null)
+                  log.debug("acquireState(): Got null state.  Region is probably empty.");
+               else
+                  log.debug("acquireState(): Got state");
             }
             return state;
          }
@@ -950,7 +951,14 @@
       {
          ExposedByteArrayOutputStream baos = new ExposedByteArrayOutputStream(16 * 1024);
          out = new MarshalledValueOutputStream(baos);
-         stateTransferManager.getState(out, fqn, timeout, force, false);
+         try
+         {
+            stateTransferManager.getState(out, fqn, timeout, force, false);
+         }
+         catch (RegionEmptyException ree)
+         {
+            return null;
+         }
          result = baos.getRawBuffer();
       }
       finally

Modified: core/trunk/src/main/java/org/jboss/cache/statetransfer/StateTransferManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/statetransfer/StateTransferManager.java	2008-05-29 14:49:10 UTC (rev 5917)
+++ core/trunk/src/main/java/org/jboss/cache/statetransfer/StateTransferManager.java	2008-05-29 15:08:09 UTC (rev 5918)
@@ -12,6 +12,7 @@
 import org.jboss.cache.CacheSPI;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.NodeSPI;
+import org.jboss.cache.RegionEmptyException;
 import org.jboss.cache.RegionManager;
 import org.jboss.cache.config.Configuration;
 import org.jboss.cache.factories.annotations.Inject;
@@ -20,6 +21,7 @@
 import org.jboss.cache.lock.LockManager;
 import static org.jboss.cache.lock.LockType.READ;
 import org.jboss.cache.lock.TimeoutException;
+import org.jboss.cache.marshall.InactiveRegionException;
 import org.jboss.cache.marshall.Marshaller;
 import org.jboss.cache.marshall.NodeData;
 import org.jboss.cache.marshall.NodeDataMarker;
@@ -83,7 +85,7 @@
    public void getState(ObjectOutputStream out, Fqn fqn, long timeout, boolean force, boolean suppressErrors) throws Throwable
    {
       // can't give state for regions currently being activated/inactivated
-      boolean canProvideState = (!regionManager.isInactive(fqn) && cache.peek(fqn, false, false) != null);
+      boolean canProvideState = (!regionManager.isInactive(fqn) && cache.peek(fqn, false) != null);
 
       boolean fetchTransientState = configuration.isFetchInMemoryState();
       CacheLoaderManager cacheLoaderManager = cache.getCacheLoaderManager();
@@ -126,19 +128,20 @@
             if (regionManager.isInactive(fqn))
             {
                exceptionMessage += " Region for fqn " + fqn + " is inactive.";
+               e = new InactiveRegionException(exceptionMessage);
             }
+            // this is not really an exception.  Just provide empty state. The exception is just a signal.  Yes, lousy.  - JBCACHE-1349
             if (cache.peek(fqn, false, false) == null)
             {
-               exceptionMessage += " There is no cache node at fqn " + fqn;
+               e = new RegionEmptyException();
             }
-            e = new CacheException(exceptionMessage);
          }
          if (!fetchPersistentState && !fetchTransientState)
          {
             e = new CacheException("Cache instance at " + cache.getLocalAddress() + " is not configured to provide state");
          }
          marshaller.objectToObjectStream(e, out);
-         throw e;
+         if (e != null) throw e;
       }
    }
 

Added: core/trunk/src/test/java/org/jboss/cache/buddyreplication/EmptyRegionTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/buddyreplication/EmptyRegionTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/buddyreplication/EmptyRegionTest.java	2008-05-29 15:08:09 UTC (rev 5918)
@@ -0,0 +1,88 @@
+package org.jboss.cache.buddyreplication;
+
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Region;
+import org.jboss.cache.notifications.annotation.BuddyGroupChanged;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.event.Event;
+import org.jboss.cache.util.CachePrinter;
+import org.jboss.cache.util.TestingUtil;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * To test http://jira.jboss.org/jira/browse/JBCACHE-1349
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ */
+ at Test(groups = "functional")
+public class EmptyRegionTest extends BuddyReplicationTestsBase
+{
+   CacheSPI c1, c2;
+   Fqn regionFqn = Fqn.fromString("/a/b/c");
+   Fqn region2Fqn = Fqn.fromString("/d/e/f");
+   Region region, region2;
+   CountDownLatch buddyJoinLatch = new CountDownLatch(1);
+
+   @BeforeTest
+   public void setUp() throws Exception
+   {
+      c1 = createCache(1, null, false, false, false);
+      c1.getConfiguration().setUseRegionBasedMarshalling(true);
+      c1.getConfiguration().setFetchInMemoryState(true);
+      c2 = (CacheSPI) new DefaultCacheFactory().createCache(c1.getConfiguration().clone(), false);
+      c1.start();
+      region = c1.getRegion(regionFqn, true);
+      region2 = c1.getRegion(region2Fqn, true);
+      region.registerContextClassLoader(getClass().getClassLoader());
+      region2.registerContextClassLoader(getClass().getClassLoader());
+      c1.put(region2Fqn, "key", "value");
+
+      c2.create();
+      c2.addCacheListener(new BuddyJoinListener());
+   }
+
+   @AfterTest
+   public void tearDown()
+   {
+      TestingUtil.killCaches(c1, c2);
+   }
+
+   public void testEmptyRegion() throws InterruptedException
+   {
+      // region on c1 is empty - with no root node.
+      assert c1.getNode(regionFqn) == null : "Node should not exist";
+      assert c1.getRegion(regionFqn, false) != null : "Region should exist";
+      assert c1.getRegion(regionFqn, false).isActive() : "Region should be active";
+
+      // now start c2
+      c2.start();
+
+      // wait for buddy join notifications to complete.
+      buddyJoinLatch.await(60, TimeUnit.SECONDS);
+
+      // should not throw any exceptions!!
+
+      System.out.println("Cache1 " + CachePrinter.printCacheDetails(c1));
+      System.out.println("Cache2 " + CachePrinter.printCacheDetails(c2));
+
+      // make sure region2 stuff did get transmitted!
+      assert c2.peek(BuddyFqnTransformer.getBackupFqn(c1.getLocalAddress(), region2Fqn), false) != null : "Region2 state should have transferred!";
+   }
+
+   @CacheListener
+   public class BuddyJoinListener
+   {
+      @BuddyGroupChanged
+      public void buddyJoined(Event e)
+      {
+         buddyJoinLatch.countDown();
+      }
+   }
+}




More information about the jbosscache-commits mailing list