/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.interceptors;
import junit.framework.TestCase;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.TreeCache;
import org.jboss.cache.eviction.DummyEvictionPolicy;
import org.jboss.cache.eviction.EvictedEventNode;
import org.jboss.cache.eviction.LRUConfiguration;
import org.jboss.cache.eviction.Region;
import org.jboss.cache.eviction.RegionManager;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.marshall.MethodCallFactory;
import org.jboss.cache.marshall.MethodDeclarations;
import org.jgroups.blocks.MethodCall;
import java.util.HashMap;
import java.util.Map;
/**
* @author Daniel Huang (dhuang@jboss.org)
* @version $Revision: $
*/
public class EvictionInterceptorTest extends TestCase
{
private static final String fqn1 = "/a/b/c";
private static final String fqn2 = "/a/b";
private static final String fqn3 = "/a/b/d";
private static final String fqn4 = "/d/e/f";
private TreeCache cache;
private Interceptor interceptor;
private RegionManager regionManager;
public void setUp() throws Exception
{
super.setUp();
regionManager = new RegionManager();
LRUConfiguration config = new LRUConfiguration();
regionManager.createRegion("/a/b/c", new DummyEvictionPolicy(), config);
regionManager.createRegion("/a/b/d", new DummyEvictionPolicy(), config);
regionManager.createRegion("/a/b", new DummyEvictionPolicy(), config);
regionManager.createRegion("/d/e/f", new DummyEvictionPolicy(), config);
regionManager.createRegion("/d/e/g", new DummyEvictionPolicy(), config);
regionManager.createRegion("/d/e", new DummyEvictionPolicy(), config);
cache = new TreeCache();
cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
cache.setIsolationLevel(IsolationLevel.SERIALIZABLE);
/*CacheMgmtInterceptor
TxInterceptor
Unlock
PessimisticLockInterceptor
CallInterceptor
UnlockInterceptor
TxInterceptor
CacheMgmtInterceptor */
// make the interceptor chain (separate from the TreeCache object.
interceptor = new CacheMgmtInterceptor();
interceptor.setCache(cache);
TxInterceptor ti = new TxInterceptor();
ti.setCache(cache);
interceptor.setNext(ti);
UnlockInterceptor ui = new UnlockInterceptor();
ui.setCache(cache);
ti.setNext(ui);
PessimisticLockInterceptor pli = new PessimisticLockInterceptor();
pli.setCache(cache);
ui.setNext(pli);
EvictionInterceptor ei = new EvictionInterceptor();
ei.setCache(cache);
ei.setRegionManager(regionManager);
pli.setNext(ei);
CallInterceptor ci = new CallInterceptor();
ci.setCache(cache);
ei.setNext(ci);
cache.setCacheMode("LOCAL");
cache.startService();
}
public void tearDown() throws Exception
{
super.tearDown();
cache.remove("/");
cache.stopService();
}
public void testVisitNode() throws Throwable
{
// make sure node that doesn't exist does not result in a node visit event.
MethodCall mc = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal,
new Object[]{Fqn.fromString(fqn1)});
interceptor.invoke(mc);
Region regionABC = regionManager.getRegion(fqn1);
assertNull(regionABC.takeLastEventNode());
cache.put(fqn1, "key", "value");
assertEquals("value", cache.get(fqn1, "key"));
Node node = cache.get(fqn1);
assertNotNull(node);
assertEquals("value", node.get("key"));
cache.put(fqn3, "key", "value");
assertEquals("value", cache.get(fqn3, "key"));
node = cache.get(fqn3);
assertNotNull(node);
assertEquals("value", node.get("key"));
mc = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal,
new Object[]{Fqn.fromString(fqn1)});
interceptor.invoke(mc);
regionABC = regionManager.getRegion(fqn1);
EvictedEventNode event = regionABC.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn1, event.getFqn().toString());
assertNull(regionABC.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal,
new Object[]{Fqn.fromString(fqn2)});
interceptor.invoke(mc);
Region regionAB = regionManager.getRegion(fqn2);
event = regionAB.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn2, event.getFqn().toString());
assertNull(regionAB.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getDataMapMethodLocal, new Object[]{Fqn.fromString(fqn3)});
interceptor.invoke(mc);
Region regionABD = regionManager.getRegion(fqn3);
event = regionABD.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn3, event.getFqn().toString());
assertNull(regionABD.takeLastEventNode());
for (int i = 0; i < 10; i++)
{
Fqn fqn = Fqn.fromString(fqn3);
mc = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal, new Object[]{fqn});
interceptor.invoke(mc);
}
for (int i = 0; i < 10; i++)
{
Region region = regionManager.getRegion(fqn3);
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn3, event.getFqn().toString());
}
assertNull(regionManager.getRegion(fqn3).takeLastEventNode());
// check null handling.
mc = MethodCallFactory.create(MethodDeclarations.getDataMapMethodLocal, new Object[]{null});
interceptor.invoke(mc);
}
public void testVisitElement() throws Throwable
{
// make sure a get/visit on an empty node and empty element results in no cache events being added to event queue
// aka Region.
Fqn fqn = Fqn.fromString(fqn4);
Object key = "key";
MethodCall mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
Region region = regionManager.getRegion(fqn.toString());
assertNull(region.takeLastEventNode());
// add the node but try to get on a null element should result in no cache events being added to Region.
cache.put(fqn, "wrongkey", "");
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
assertNull(region.takeLastEventNode());
// now make sure if we try to get on the node/key we just created in cache, that this DOES add a EvictedEventNode to
// the Region.
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, "wrongkey", Boolean.FALSE});
interceptor.invoke(mc);
EvictedEventNode event = region.takeLastEventNode();
assertEquals(fqn, event.getFqn());
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertNull(region.takeLastEventNode());
cache.put(fqn4, key, "value");
// test on element granularity configured node.
fqn = Fqn.fromString(fqn4);
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
region = regionManager.getRegion(fqn.toString());
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
fqn = Fqn.fromString("/d/e/g");
for (int i = 0; i < 1000; i++)
{
key = new Integer(i);
cache.put("/d/e/g", key, "");
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.TRUE});
interceptor.invoke(mc);
}
region = regionManager.getRegion(fqn.toString());
for (int i = 0; i < 1000; i++)
{
event = region.takeLastEventNode();
assertEquals(fqn, event.getFqn());
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
}
cache.put("/a/b/c", key, "");
fqn = Fqn.fromString("/a/b/c");
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
region = regionManager.getRegion(fqn.toString());
event = region.takeLastEventNode();
assertNull(region.takeLastEventNode());
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
for (int i = 0; i < 1000; i++)
{
key = new Integer(i);
cache.put(fqn.toString(), key, "");
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.TRUE});
interceptor.invoke(mc);
}
for (int i = 0; i < 1000; i++)
{
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
}
assertNull(region.takeLastEventNode());
// check null handling
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{null, key, Boolean.TRUE});
interceptor.invoke(mc);
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{null, null, Boolean.TRUE});
interceptor.invoke(mc);
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, null, Boolean.TRUE});
interceptor.invoke(mc);
assertNull(region.takeLastEventNode());
}
public void testCreateNode() throws Throwable
{
Map data = new HashMap();
for (int i = 0; i < 100; i++)
{
Integer in = new Integer(i);
data.put(in, in);
}
// this region is node granularity
Fqn fqn = Fqn.fromString("/a/b/c");
MethodCall mc = MethodCallFactory.create(MethodDeclarations.putDataMethodLocal, new Object[]{null, fqn, data, Boolean.FALSE});
interceptor.invoke(mc);
Region region = regionManager.getRegion(fqn.toString());
EvictedEventNode event = region.takeLastEventNode();
assertEquals(EvictedEventNode.ADD_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(100, event.getElementDifference());
Node node = cache.get(fqn.toString());
assertNotNull(node);
for (int i = 0; i < 100; i++)
{
Integer in = new Integer(i);
assertTrue(node.containsKey(in));
assertEquals(in, node.get(in));
}
for (int i = 0; i < 100; i++)
{
mc = MethodCallFactory.create(MethodDeclarations.putKeyValMethodLocal, new Object[]{null, fqn, new Integer(i),
"value", Boolean.FALSE});
interceptor.invoke(mc);
assertEquals("value", cache.get(fqn.toString(), new Integer(i)));
}
for (int i = 0; i < 100; i++)
{
event = region.takeLastEventNode();
assertNotNull(event);
assertEquals(fqn, event.getFqn());
assertEquals(EvictedEventNode.ADD_ELEMENT_EVENT, event.getEvent());
}
assertNull(region.takeLastEventNode());
fqn = Fqn.fromString("/a/b");
mc = MethodCallFactory.create(MethodDeclarations.putDataEraseMethodLocal, new Object[]{null, fqn, data, Boolean.FALSE, Boolean.FALSE});
interceptor.invoke(mc);
event = regionManager.getRegion(fqn.toString()).takeLastEventNode();
assertFalse(event.isResetElementCount());
assertEquals(EvictedEventNode.ADD_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(100, event.getElementDifference());
assertNull(regionManager.getRegion(fqn.toString()).takeLastEventNode());
node = cache.get(fqn.toString());
assertEquals(100, node.numAttributes());
assertNotNull(node);
for (int i = 0; i < 100; i++)
{
Integer in = new Integer(i);
assertTrue(node.containsKey(in));
assertEquals(in, node.get(in));
}
mc = MethodCallFactory.create(MethodDeclarations.putDataEraseMethodLocal, new Object[]{null, fqn, data, Boolean.FALSE, Boolean.TRUE});
interceptor.invoke(mc);
event = regionManager.getRegion(fqn.toString()).takeLastEventNode();
assertEquals(EvictedEventNode.ADD_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(100, event.getElementDifference());
assertTrue(event.isResetElementCount());
assertNull(regionManager.getRegion(fqn.toString()).takeLastEventNode());
node = cache.get(fqn.toString());
assertEquals(100, node.numAttributes());
assertNotNull(node);
for (int i = 0; i < 100; i++)
{
Integer in = new Integer(i);
assertTrue(node.containsKey(in));
assertEquals(in, node.get(in));
}
}
public void testCreateElement() throws Throwable
{
Fqn fqn = Fqn.fromString("/d/e/f");
Region region = regionManager.getRegion(fqn.toString());
Object key = "key";
Object value = "value";
MethodCall mc = MethodCallFactory.create(MethodDeclarations.putKeyValMethodLocal,
new Object[]{null, fqn, key, value, Boolean.FALSE});
interceptor.invoke(mc);
assertEquals("value", cache.get(fqn, key));
EvictedEventNode event = region.takeLastEventNode();
assertEquals(EvictedEventNode.ADD_ELEMENT_EVENT, event.getEvent());
assertEquals(1, event.getElementDifference());
assertEquals(fqn, event.getFqn());
assertEquals("value", cache.get(fqn, key));
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.putFailFastKeyValueMethodLocal,
new Object[]{null, fqn, key, value, Boolean.FALSE, new Long(1000)});
interceptor.invoke(mc);
assertEquals("value", cache.get(fqn, key));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.ADD_ELEMENT_EVENT, event.getEvent());
assertEquals(1, event.getElementDifference());
assertEquals(fqn, event.getFqn());
assertEquals("value", cache.get(fqn, key));
assertNull(region.takeLastEventNode());
}
public void testRemoveNode() throws Throwable
{
Fqn fqn = Fqn.fromString("/a/b/c");
cache.put(fqn, "a", "b");
cache.put(fqn, "b", "c");
MethodCall mc = MethodCallFactory.create(MethodDeclarations.removeDataMethodLocal, new Object[]{
null, fqn, Boolean.FALSE});
interceptor.invoke(mc);
assertEquals(0, cache.get(fqn).numAttributes());
Region region = regionManager.getRegion(fqn.toString());
EvictedEventNode event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.removeNodeMethodLocal, new Object[]{
null, fqn, Boolean.FALSE
});
interceptor.invoke(mc);
assertNull(cache.get(fqn));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
}
public void testRemoveElement() throws Throwable
{
Fqn fqn = Fqn.fromString("/a/b/c");
cache.put(fqn, "a", "b");
cache.put(fqn, "b", "c");
MethodCall mc = MethodCallFactory.create(MethodDeclarations.removeKeyMethodLocal,
new Object[]{null, fqn, "a", Boolean.FALSE});
interceptor.invoke(mc);
assertNull(cache.get(fqn, "a"));
Region region = regionManager.getRegion(fqn.toString());
EvictedEventNode event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_ELEMENT_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(1, event.getElementDifference());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.removeKeyMethodLocal,
new Object[]{null, fqn, "b", Boolean.FALSE});
interceptor.invoke(mc);
assertNull(cache.get(fqn, "b"));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_ELEMENT_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(1, event.getElementDifference());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.removeKeyMethodLocal,
new Object[]{null, fqn, "b", Boolean.FALSE});
interceptor.invoke(mc);
event = region.takeLastEventNode();
assertNull(event);
}
public void testMixedEvent() throws Throwable
{
Map data = new HashMap();
for (int i = 0; i < 100; i++)
{
Integer in = new Integer(i);
data.put(in, in);
}
// this region is node granularity
Fqn fqn = Fqn.fromString("/a/b/c");
MethodCall mc = MethodCallFactory.create(MethodDeclarations.putDataMethodLocal, new Object[]{null, fqn, data, Boolean.FALSE});
interceptor.invoke(mc);
Region region = regionManager.getRegion(fqn.toString());
EvictedEventNode event = region.takeLastEventNode();
assertEquals(EvictedEventNode.ADD_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(100, event.getElementDifference());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal,
new Object[]{fqn});
interceptor.invoke(mc);
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.removeNodeMethodLocal, new Object[]{
null, fqn, Boolean.FALSE
});
interceptor.invoke(mc);
assertNull(cache.get(fqn));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
Object key = "key";
Object value = "value";
mc = MethodCallFactory.create(MethodDeclarations.putFailFastKeyValueMethodLocal,
new Object[]{null, fqn, key, value, Boolean.FALSE, new Long(1000)});
interceptor.invoke(mc);
assertEquals("value", cache.get(fqn, key));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.ADD_ELEMENT_EVENT, event.getEvent());
assertEquals(1, event.getElementDifference());
assertEquals(fqn, event.getFqn());
assertEquals("value", cache.get(fqn, key));
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.getKeyValueMethodLocal, new Object[]{fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
region = regionManager.getRegion(fqn.toString());
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.VISIT_NODE_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertNull(region.takeLastEventNode());
mc = MethodCallFactory.create(MethodDeclarations.removeKeyMethodLocal,
new Object[]{null, fqn, key, Boolean.FALSE});
interceptor.invoke(mc);
assertNull(cache.get(fqn, key));
event = region.takeLastEventNode();
assertEquals(EvictedEventNode.REMOVE_ELEMENT_EVENT, event.getEvent());
assertEquals(fqn, event.getFqn());
assertEquals(1, event.getElementDifference());
assertNull(region.takeLastEventNode());
}
}