Author: manik.surtani(a)jboss.com
Date: 2008-04-25 13:50:41 -0400 (Fri, 25 Apr 2008)
New Revision: 5697
Added:
core/trunk/src/main/java/org/jboss/cache/interceptors/BuddyRegionAwareEvictionInterceptor.java
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyFqnTransformerTest.java
core/trunk/src/test/java/org/jboss/cache/buddyreplication/EvictionOfBuddyBackupsTest.java
Modified:
core/trunk/src/main/java/org/jboss/cache/Fqn.java
core/trunk/src/main/java/org/jboss/cache/Region.java
core/trunk/src/main/java/org/jboss/cache/RegionImpl.java
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyFqnTransformer.java
core/trunk/src/main/java/org/jboss/cache/eviction/EvictedEventNode.java
core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java
Log:
JBCACHE-1190 - Eviction configuration should consider buddy backup regions as well.
Modified: core/trunk/src/main/java/org/jboss/cache/Fqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-04-25 15:11:04 UTC (rev 5696)
+++ core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-04-25 17:50:41 UTC (rev 5697)
@@ -413,7 +413,11 @@
*/
public Fqn<E> getSubFqn(int startIndex, int endIndex)
{
- return new Fqn<E>(true, elements.subList(startIndex, endIndex), true);
+ List el = elements.subList(startIndex, endIndex);
+ if (containsStrings(el))
+ return new StringFqn(el);
+ else
+ return new Fqn<E>(true, el, true);
}
/**
@@ -639,7 +643,7 @@
builder.append(e);
}
}
- return builder.toString();
+ return builder.length() == 0 ? SEPARATOR : builder.toString();
}
Modified: core/trunk/src/main/java/org/jboss/cache/Region.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Region.java 2008-04-25 15:11:04 UTC (rev
5696)
+++ core/trunk/src/main/java/org/jboss/cache/Region.java 2008-04-25 17:50:41 UTC (rev
5697)
@@ -31,7 +31,7 @@
* @see org.jboss.cache.RegionManager
* @since 2.0.0
*/
-public interface Region extends Comparable<Region>
+public interface Region extends Comparable<Region>, Cloneable
{
/**
@@ -203,6 +203,7 @@
/**
* A mechanism to set status of a region, more fine grained control than just
setActive();
+ *
* @param status status of the region
* @since 2.1.0
*/
@@ -213,4 +214,6 @@
*/
Status getStatus();
+ Region clone(Fqn cloneFqn);
+
}
Modified: core/trunk/src/main/java/org/jboss/cache/RegionImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RegionImpl.java 2008-04-25 15:11:04 UTC (rev
5696)
+++ core/trunk/src/main/java/org/jboss/cache/RegionImpl.java 2008-04-25 17:50:41 UTC (rev
5697)
@@ -30,7 +30,7 @@
private static final Log log = LogFactory.getLog(RegionImpl.class);
private final RegionManager regionManager;
- private final Fqn fqn;
+ private Fqn fqn;
private Status status;
private ClassLoader classLoader;
private BlockingQueue<EvictedEventNode> nodeEventQueue = null;
@@ -259,4 +259,29 @@
return null;
}
}
+
+ public RegionImpl clone(Fqn newRoot)
+ {
+ RegionImpl clone = null;
+ try
+ {
+ clone = (RegionImpl) super.clone();
+ clone.policy = policy;
+ clone.configuration = configuration;
+ clone.status = status;
+ clone.fqn = Fqn.fromRelativeFqn(newRoot, fqn);
+ // we also need to copy all of the eviction event nodes to the clone's
queue
+ clone.createQueue();
+ for (EvictedEventNode een : this.nodeEventQueue)
+ {
+ EvictedEventNode cloneEEN = een.clone(newRoot);
+ clone.putNodeEvent(cloneEEN);
+ }
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // problems cloning? Should never get here.
+ }
+ return clone;
+ }
}
Modified:
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyFqnTransformer.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyFqnTransformer.java 2008-04-25
15:11:04 UTC (rev 5696)
+++
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyFqnTransformer.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -378,4 +378,21 @@
{
return address.toString().replace(':', '_');
}
+
+ /**
+ * Returns the buddy backp root portion of a given Fqn, provided it is a backup Fqn.
If it is not a backup Fqn, Fqn.ROOT is returned.
+ *
+ * @param fqn fqn
+ */
+ public static Fqn getBackupRootFromFqn(Fqn fqn)
+ {
+ if (isBackupFqn(fqn))
+ {
+ return fqn.getSubFqn(0, isDeadBackupFqn(fqn) ? 3 : 2);
+ }
+ else
+ {
+ return Fqn.ROOT;
+ }
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/EvictedEventNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/EvictedEventNode.java 2008-04-25
15:11:04 UTC (rev 5696)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/EvictedEventNode.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -15,7 +15,7 @@
* @author Daniel Huang (dhuang(a)jboss.org)
* @see org.jboss.cache.Region
*/
-public class EvictedEventNode
+public class EvictedEventNode implements Cloneable
{
private Fqn fqn_;
private NodeEventType type_;
@@ -98,4 +98,19 @@
{
return "EvictedEN[fqn=" + fqn_ + " event=" + type_ + "
diff=" + elementDifference_ + "]";
}
+
+ public EvictedEventNode clone(Fqn cloneFqn)
+ {
+ EvictedEventNode clone = null;
+ try
+ {
+ clone = (EvictedEventNode) super.clone();
+ clone.setFqn(Fqn.fromRelativeFqn(cloneFqn, fqn_));
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // should never get here
+ }
+ return clone;
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2008-04-25
15:11:04 UTC (rev 5696)
+++
core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -41,7 +41,8 @@
{
chainedInterceptor = clazz.newInstance();
componentRegistry.registerComponent(clazz.getName(), chainedInterceptor,
clazz);
- } else
+ }
+ else
{
// wipe next/last chaining!!
chainedInterceptor.setNext(null);
@@ -92,7 +93,8 @@
{
interceptorChain.appendIntereceptor(createInterceptor(ActivationInterceptor.class));
interceptorChain.appendIntereceptor(createInterceptor(PassivationInterceptor.class));
- } else
+ }
+ else
{
interceptorChain.appendIntereceptor(createInterceptor(CacheLoaderInterceptor.class));
interceptorChain.appendIntereceptor(createInterceptor(CacheStoreInterceptor.class));
@@ -110,7 +112,7 @@
}
// eviction interceptor to come before the optimistic node interceptor
if (configuration.getEvictionConfig() != null &&
configuration.getEvictionConfig().isValidConfig())
-
interceptorChain.appendIntereceptor(createInterceptor(EvictionInterceptor.class));
+
interceptorChain.appendIntereceptor(createInterceptor(configuration.isUsingBuddyReplication()
? BuddyRegionAwareEvictionInterceptor.class : EvictionInterceptor.class));
if (optimistic)
interceptorChain.appendIntereceptor(createInterceptor(OptimisticNodeInterceptor.class));
ChainedInterceptor callInterceptor = createInterceptor(CallInterceptor.class);
Added:
core/trunk/src/main/java/org/jboss/cache/interceptors/BuddyRegionAwareEvictionInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/BuddyRegionAwareEvictionInterceptor.java
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/BuddyRegionAwareEvictionInterceptor.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -0,0 +1,41 @@
+package org.jboss.cache.interceptors;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Region;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.eviction.NodeEventType;
+
+/**
+ * A subclass of EvictionInterceptor that is aware of and able to deal with buddy
regions.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.2.0
+ */
+public class BuddyRegionAwareEvictionInterceptor extends EvictionInterceptor
+{
+ @Override
+ protected Region getRegion(Fqn fqn, NodeEventType type)
+ {
+ Region r = super.getRegion(fqn, type);
+ if (r != null)
+ return r;
+ else if (BuddyFqnTransformer.isBackupFqn(fqn))
+ {
+ // try and grab a backup region, creating one if need be.
+ Fqn actualFqn = BuddyFqnTransformer.getActualFqn(fqn);
+ Fqn backupRoot = BuddyFqnTransformer.getBackupRootFromFqn(fqn);
+
+ // the actual region could be a few levels higher than actualFqn
+ Region actualRegion = regionManager.getRegion(actualFqn, Region.Type.EVICTION,
false);
+
+ if (actualRegion == null) return null;
+
+ //create a new region for this backup
+ Region newRegion = regionManager.getRegion(Fqn.fromRelativeFqn(backupRoot,
actualRegion.getFqn()), Region.Type.EVICTION, true);
+ newRegion.setEvictionPolicy(actualRegion.getEvictionPolicyConfig());
+
+ return newRegion;
+ }
+ else return null;
+ }
+}
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java 2008-04-25
15:11:04 UTC (rev 5696)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/EvictionInterceptor.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -70,9 +70,10 @@
boolean complete = (retVal != null && (Boolean) retVal);
if (!complete)
{
- if (fqn != null && !canIgnoreEvent(fqn, NodeEventType.ADD_NODE_EVENT))
+ Region r;
+ if (fqn != null && (r = getRegion(fqn, NodeEventType.ADD_NODE_EVENT)) !=
null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.ADD_NODE_EVENT, 0), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.ADD_NODE_EVENT, 0), r);
}
}
return retVal;
@@ -82,9 +83,10 @@
public Object handlePutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand
command) throws Throwable
{
Object retVal = invokeNextInterceptor(ctx, command);
- if (command.getFqn() != null && command.getKey() != null &&
!canIgnoreEvent(command.getFqn(), NodeEventType.ADD_ELEMENT_EVENT))
+ Region r;
+ if (command.getFqn() != null && command.getKey() != null && (r =
getRegion(command.getFqn(), NodeEventType.ADD_ELEMENT_EVENT)) != null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.ADD_ELEMENT_EVENT, 1), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.ADD_ELEMENT_EVENT, 1), r);
}
return retVal;
}
@@ -94,7 +96,8 @@
{
Object retVal = invokeNextInterceptor(ctx, command);
Fqn fqn = command.getFqn();
- if (fqn != null && !canIgnoreEvent(fqn, NodeEventType.ADD_NODE_EVENT))
+ Region r;
+ if (fqn != null && (r = getRegion(fqn, NodeEventType.ADD_NODE_EVENT)) !=
null)
{
if (command.getData() == null)
{
@@ -112,7 +115,7 @@
}
EvictedEventNode event = new EvictedEventNode(fqn,
NodeEventType.ADD_NODE_EVENT, size);
event.setResetElementCount(command.isEraseContents());
- registerEvictionEventToRegionManager(event, ctx);
+ registerEvictionEventToRegionManager(event, r);
}
}
return retVal;
@@ -133,9 +136,10 @@
else
{
Fqn fqn = command.getFqn();
- if (fqn != null && command.getKey() != null &&
!canIgnoreEvent(fqn, NodeEventType.REMOVE_ELEMENT_EVENT))
+ Region r = null;
+ if (fqn != null && command.getKey() != null && (r =
getRegion(fqn, NodeEventType.REMOVE_ELEMENT_EVENT)) != null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.REMOVE_ELEMENT_EVENT, 1), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.REMOVE_ELEMENT_EVENT, 1), r);
}
}
return retVal;
@@ -159,9 +163,10 @@
}
else
{
- if (fqn != null && !canIgnoreEvent(fqn,
NodeEventType.VISIT_NODE_EVENT))
+ Region r;
+ if (fqn != null && (r = getRegion(fqn, NodeEventType.VISIT_NODE_EVENT))
!= null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.VISIT_NODE_EVENT), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.VISIT_NODE_EVENT), r);
}
}
return retVal;
@@ -179,6 +184,7 @@
{
Object retVal = invokeNextInterceptor(ctx, command);
Fqn fqn = command.getFqn();
+ Region r;
if (retVal == null)
{
if (trace)
@@ -186,9 +192,9 @@
log.trace("No event added. Element does not exist");
}
}
- else if (fqn != null && command.getKey() != null &&
!canIgnoreEvent(fqn, NodeEventType.VISIT_NODE_EVENT))
+ else if (fqn != null && command.getKey() != null && (r =
getRegion(fqn, NodeEventType.VISIT_NODE_EVENT)) != null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.VISIT_NODE_EVENT), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(fqn,
NodeEventType.VISIT_NODE_EVENT), r);
}
return retVal;
}
@@ -197,9 +203,10 @@
public Object handleRemoveNodeCommand(InvocationContext ctx, RemoveNodeCommand
command) throws Throwable
{
Object retVal = invokeNextInterceptor(ctx, command);
- if (command.getFqn() != null && !canIgnoreEvent(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT))
+ Region r;
+ if (command.getFqn() != null && (r = getRegion(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT)) != null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT), r);
}
return retVal;
}
@@ -208,14 +215,15 @@
public Object handleRemoveDataCommand(InvocationContext ctx, RemoveDataCommand
command) throws Throwable
{
Object retVal = invokeNextInterceptor(ctx, command);
- if (command.getFqn() != null && !canIgnoreEvent(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT))
+ Region r;
+ if (command.getFqn() != null && (r = getRegion(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT)) != null)
{
- registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT), ctx);
+ registerEvictionEventToRegionManager(new EvictedEventNode(command.getFqn(),
NodeEventType.REMOVE_NODE_EVENT), r);
}
return retVal;
}
- private void registerEvictionEventToRegionManager(EvictedEventNode event,
InvocationContext ctx)
+ private void registerEvictionEventToRegionManager(EvictedEventNode event, Region
region)
{
if (event == null)
{
@@ -230,7 +238,6 @@
return;
}
- Region region = regionManager.getRegion(event.getFqn(), false);
region.putNodeEvent(event);
if (trace)
@@ -244,10 +251,10 @@
}
}
- protected boolean canIgnoreEvent(Fqn fqn, NodeEventType type)
+ protected Region getRegion(Fqn fqn, NodeEventType type)
{
Region r = regionManager.getRegion(fqn, Region.Type.EVICTION, false);
- // should never happen, we should at least get the default region.
- return r == null || r.getEvictionPolicy().canIgnoreEvent(fqn, type);
+ if (r != null && r.getEvictionPolicy().canIgnoreEvent(fqn, type)) return
null;
+ return r;
}
}
Added:
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyFqnTransformerTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyFqnTransformerTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyFqnTransformerTest.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -0,0 +1,30 @@
+package org.jboss.cache.buddyreplication;
+
+import org.jboss.cache.Fqn;
+import org.testng.annotations.Test;
+
+/**
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.2.0
+ */
+@Test(groups = "functional")
+public class BuddyFqnTransformerTest
+{
+ public void testActualFqn()
+ {
+ Fqn backupFqn = Fqn.fromString("/_BUDDY_BACKUP_/1.2.3.4_5678/a/b/c/d");
+ assert
BuddyFqnTransformer.getActualFqn(backupFqn).equals(Fqn.fromString("/a/b/c/d"));
+
+ backupFqn = Fqn.fromString("/_BUDDY_BACKUP_/1.2.3.4_5678");
+
+ Fqn actual = BuddyFqnTransformer.getActualFqn(backupFqn);
+
+ assert actual.equals(Fqn.ROOT);
+ }
+
+ public void testBackupRootFqn()
+ {
+ Fqn backupFqn = Fqn.fromString("/_BUDDY_BACKUP_/1.2.3.4_5678/a/b/c/d");
+ assert
BuddyFqnTransformer.getBackupRootFromFqn(backupFqn).equals(Fqn.fromString("/_BUDDY_BACKUP_/1.2.3.4_5678"))
: "Got " + BuddyFqnTransformer.getBackupRootFromFqn(backupFqn);
+ }
+}
Added:
core/trunk/src/test/java/org/jboss/cache/buddyreplication/EvictionOfBuddyBackupsTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/buddyreplication/EvictionOfBuddyBackupsTest.java
(rev 0)
+++
core/trunk/src/test/java/org/jboss/cache/buddyreplication/EvictionOfBuddyBackupsTest.java 2008-04-25
17:50:41 UTC (rev 5697)
@@ -0,0 +1,73 @@
+package org.jboss.cache.buddyreplication;
+
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.EvictionConfig;
+import org.jboss.cache.config.EvictionRegionConfig;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.eviction.NullEvictionPolicy;
+import org.jboss.cache.misc.TestingUtil;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+
+/**
+ * Tests the eviction of buddy backup regions
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.2.0
+ */
+@Test(groups = "functional")
+public class EvictionOfBuddyBackupsTest extends BuddyReplicationTestsBase
+{
+ private CacheSPI cache1, cache2;
+ private Fqn fqn = Fqn.fromString("/a/b/c");
+
+ @BeforeTest
+ public void setUp() throws Exception
+ {
+ cache1 = createCache(1, null, true, false);
+ cache1.getConfiguration().setEvictionConfig(getEvictionConfig());
+ cache1.start();
+
+ cache2 = (CacheSPI) new
DefaultCacheFactory().createCache(cache1.getConfiguration().clone());
+
+ TestingUtil.blockUntilViewsReceived(60000, cache1, cache2);
+ }
+
+ @AfterTest
+ public void tearDown()
+ {
+ TestingUtil.killCaches(cache1, cache2);
+ }
+
+ private EvictionConfig getEvictionConfig()
+ {
+ EvictionConfig c = new EvictionConfig();
+ c.setDefaultEvictionPolicyClass(NullEvictionPolicy.class.getName());
+ c.setWakeupIntervalSeconds(1);
+ LRUConfiguration epc = new LRUConfiguration();
+ epc.setMaxAgeSeconds(1);
+ epc.setTimeToLiveSeconds(1);
+ EvictionRegionConfig erc = new EvictionRegionConfig(fqn, epc);
+ c.setEvictionRegionConfigs(Collections.singletonList(erc));
+ return c;
+ }
+
+
+ public void testEvictionOfBackupRegions() throws Exception
+ {
+ cache1.put(fqn, "k", "v");
+ assert cache1.peek(fqn, false, false) != null : "Node should exist";
+ assert cache2.peek(BuddyFqnTransformer.getBackupFqn(cache1.getLocalAddress(), fqn),
false, false) != null : "Node should exist on backup";
+
+ // now wait for eviction to kick in - for up to 2 secs
+ TestingUtil.sleepThread(2000);
+
+ assert cache1.peek(fqn, false, false) == null : "Node should have
evicted";
+ assert cache2.peek(BuddyFqnTransformer.getBackupFqn(cache1.getLocalAddress(), fqn),
false, false) == null : "Node should have evicted on backup";
+ }
+}