/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.buddyreplication;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.cache.config.Option;
import org.jboss.cache.eviction.LRUPolicy;
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.misc.TestingUtil;
import org.jboss.cache.xml.XmlHelper;
import java.io.File;
/**
* Tests use of the data gravitator alongside other cache loaders as well as data gravitator options such as removeOnFind.
*
* @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
*/
public class BuddyReplicationWithCacheLoaderTest extends BuddyReplicationTestsBase
{
protected Fqn fqn = Fqn.fromString("/test");
protected String key = "key";
protected String value = "value";
protected boolean passivation = false;
private CacheLoader[] getLoaders(TreeCache[] caches)
{
CacheLoader[] retVal = new CacheLoader[caches.length];
for (int i=0; i<retVal.length; i++)
{
retVal[i] = caches[i].getCacheLoader();
}
return retVal;
}
public void testWithDataGravitationDefault() throws Exception
{
dataGravitationDefaultTest(true);
}
public void testNoAutoDataGravitationDefault() throws Exception
{
dataGravitationDefaultTest(false);
}
private void dataGravitationDefaultTest(boolean autoGravitate) throws Exception
{
TreeCache[] caches = null;
try
{
// create 3 caches
caches = createCachesWithCacheLoader(3, autoGravitate, true, passivation);
TestingUtil.sleepThread(1000);
CacheLoader[] loaders = getLoaders(caches);
// cleanup
for (int i=0; i<3; i++) loaders[i].remove(Fqn.ROOT);
for (int i=0;i<3; i++) System.out.println(i + ": " + loaders[i].get(fqn));
// put stuff in cache0
caches[0].put(fqn, key, value);
// make sure there are no locks.
assertNoLocks(caches);
for (int i=0;i<3; i++) System.out.println(i + ": " + loaders[i].get(fqn));
dumpCacheContents(caches);
// request data from cache2
if (autoGravitate)
{
assertEquals(value, caches[2].get(fqn, key));
}
else
{
Option opt = new Option();
opt.setForceDataGravitation(true);
assertEquals(value, caches[2].get(fqn, key, opt));
}
assertNoLocks(caches);
for (int i=0;i<3; i++) System.out.println(i + ": " + loaders[i].get(fqn));
dumpCacheContents(caches);
// test that data does not exist in cache0
assertTrue("should not exist in cache0", !caches[0].exists(fqn));
// test that data does not exist in cache1
assertTrue("should not exist in cache1", !caches[1].exists(fqn));
// test that data does exist in cache2
assertTrue("should exist in cache2", caches[2].exists(fqn));
// test that data does not exist in loader0
assertTrue("should not exist in loader0", !loaders[0].exists(fqn));
// test that data does not exist in loader1
assertTrue("should not exist in loader1", !loaders[1].exists(fqn));
// test that data does exist in loader2
assertTrue("should exist in loader2", passivation ? !loaders[2].exists(fqn) : loaders[2].exists(fqn));
Fqn b1 = new Fqn( new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, BuddyManager.getGroupNameFromAddress(caches[0].getLocalAddress())), fqn.peekElements() );
Fqn b2 = new Fqn( new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, BuddyManager.getGroupNameFromAddress(caches[2].getLocalAddress())), fqn.peekElements() );
// test that bkup does exist in cache0
assertTrue("should not exist in cache0", !caches[0].exists(b1));
assertTrue("should exist in cache0", caches[0].exists(b2));
// test that bkup does not exist in cache1
assertTrue("should not exist in cache1", !caches[1].exists(b1));
assertTrue("should not exist in cache1", !caches[1].exists(b2));
// test that bkup does not exist in cache2
assertTrue("should not exist in cache2", !caches[2].exists(b1));
assertTrue("should not exist in cache2", !caches[2].exists(b2));
// test that bkup does exist in loader0
assertTrue("should not exist in loader0", !loaders[0].exists(b1));
assertTrue("should exist in loader0", passivation ? !loaders[0].exists(b2) : loaders[0].exists(b2));
// test that bkup does not exist in loader1
assertTrue("should not exist in loaders1", !loaders[1].exists(b1));
assertTrue("should not exist in loaders1", !loaders[1].exists(b2));
// test that bkup does not exist in loader2
assertTrue("should not exist in loaders2", !loaders[2].exists(b1));
assertTrue("should not exist in loaders2", !loaders[2].exists(b2));
}
finally
{
cleanup(caches);
}
}
public void testWithDataGravitationEviction() throws Exception
{
dataGravitationEvictionTest(true);
}
public void testNoAutoDataGravitationEviction() throws Exception
{
dataGravitationEvictionTest(false);
}
private void dataGravitationEvictionTest(boolean autoGravitate) throws Exception
{
TreeCache[] caches = null;
try
{
// create 3 caches
caches = createCachesWithCacheLoader(3, autoGravitate, false, passivation);
CacheLoader[] loaders = getLoaders(caches);
// put stuff in cache0
caches[0].put(fqn, key, value);
// request data from cache2
if (autoGravitate)
{
assertEquals(value, caches[2].get(fqn, key));
}
else
{
Option opt = new Option();
opt.setForceDataGravitation(true);
assertEquals(value, caches[2].get(fqn, key, opt));
}
// test that data does not exist in cache0
assertTrue("should not exist in cache0", !caches[0].exists(fqn));
// test that data does not exist in cache1
assertTrue("should not exist in cache1", !caches[1].exists(fqn));
// test that data does exist in cache2
assertTrue("should exist in cache2", caches[2].exists(fqn));
// test that data does exist in loader0
assertTrue("should exist in loader0", loaders[0].exists(fqn));
// test that data does not exist in loader1
assertTrue("should not exist in loader1", !loaders[1].exists(fqn));
// test that data does exist in loader2
assertTrue("should exist in loader2", passivation ? !loaders[2].exists(fqn) : loaders[2].exists(fqn));
Fqn b1 = new Fqn( new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, BuddyManager.getGroupNameFromAddress(caches[0].getLocalAddress())), fqn.peekElements() );
Fqn b2 = new Fqn( new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, BuddyManager.getGroupNameFromAddress(caches[2].getLocalAddress())), fqn.peekElements() );
// test that bkup does exist in cache0
assertTrue("should not exist in cache0", !caches[0].exists(b1));
assertTrue("should exist in cache0", caches[0].exists(b2));
// test that bkup does not exist in cache1
assertTrue("should not exist in cache1", !caches[1].exists(b1));
assertTrue("should not exist in cache1", !caches[1].exists(b2));
// test that bkup does not exist in cache2
assertTrue("should not exist in cache2", !caches[2].exists(b1));
assertTrue("should not exist in cache2", !caches[2].exists(b2));
// test that bkup does exist in loader0
assertTrue("should not exist in loader0", !loaders[0].exists(b1));
assertTrue("should exist in loader0", passivation ? !loaders[0].exists(b2) : loaders[0].exists(b2));
// test that bkup does not exist in loader1
assertTrue("should exist in loaders1", loaders[1].exists(b1));
assertTrue("should not exist in loaders1", !loaders[1].exists(b2));
// test that bkup does not exist in loader2
assertTrue("should not exist in loaders2", !loaders[2].exists(b1));
assertTrue("should not exist in loaders2", !loaders[2].exists(b2));
}
finally
{
cleanup(caches);
}
}
/**
* Tests whether nodes that have been evicted can successfully be
* gravitated.
*
* @throws Exception
*/
public void testLocalGravitationOfEvictedNodes() throws Exception
{
TreeCache[] caches = null;
String tmpLocation = System.getProperty("java.io.tmpdir", "/tmp");
tmpLocation = tmpLocation + File.separator + "JBossCacheBRWithCacheLoaderTest";
try
{
TreeCache cache1 = createCacheWithCacheLoader(tmpLocation + File.separator + "1", true, true, passivation, true, false);
configureEviction(cache1);
TreeCache cache0 = createCacheWithCacheLoader(tmpLocation + File.separator + "2", true, true, passivation, true, false);
configureEviction(cache0);
caches = new TreeCache[2];
caches[0] = cache0;
caches[1] = cache1;
cache0.start();
cache1.start();
TestingUtil.blockUntilViewsReceived(caches, VIEW_BLOCK_TIMEOUT * caches.length);
TestingUtil.sleepThread(getSleepTimeout());
Fqn foo = Fqn.fromString("/foo");
Fqn backupFoo = BuddyManager.getBackupFqn(cache0.getLocalAddress(), foo);
cache0.put(foo, "key", "value");
assertTrue("Data should exist in data owner", cache0.exists(foo));
assertTrue("Buddy should have data", cache1.exists(backupFoo));
// Sleep long enough for eviction to run twice plus a bit
TestingUtil.sleepThread(3050);
// test that the data we're looking for has been evicted in both the data owner and the buddy.
assertFalse("Data should have evicted in data owner", cache0.exists(foo));
assertFalse("Buddy should have data evicted", cache1.exists(backupFoo));
// now test that this exists in both loaders.
assertNotNull("Should exist in data owner's cache loader", cache0.getCacheLoader().get(foo));
assertNotNull("Should exist in buddy's loader", cache1.getCacheLoader().get(backupFoo));
// a local gravitation should occur since cache1 has foo in it's backup tree.
assertEquals("Passivated value available from buddy", "value", cache1.get(foo, "key"));
}
finally
{
cleanup(caches);
TestingUtil.recursiveRemove(new File(tmpLocation));
}
}
/**
* Tests whether nodes that have been evicted can successfully be
* gravitated.
*
* @throws Exception
*/
public void testRemoteGravitationOfEvictedNodes() throws Exception
{
TreeCache[] caches = null;
String tmpLocation = System.getProperty("java.io.tmpdir", "/tmp");
tmpLocation = tmpLocation + File.separator + "JBossCacheBRWithCacheLoaderTest";
try
{
TreeCache cache0 = createCacheWithCacheLoader(tmpLocation + File.separator + "0", true, true, passivation, true, false);
configureEviction(cache0);
TreeCache cache1 = createCacheWithCacheLoader(tmpLocation + File.separator + "1", true, true, passivation, true, false);
configureEviction(cache1);
TreeCache cache2 = createCacheWithCacheLoader(tmpLocation + File.separator + "2", true, true, passivation, true, false);
configureEviction(cache2);
caches = new TreeCache[3];
caches[0] = cache0;
caches[1] = cache1;
caches[2] = cache2;
cache0.start();
cache1.start();
cache2.start();
TestingUtil.blockUntilViewsReceived(caches, 600000);
TestingUtil.sleepThread(getSleepTimeout());
assertTrue("Cache1 should be cache0's buddy!", cache0.getBuddyManager().getBuddyAddresses().contains(cache1.getLocalAddress()));
Fqn foo = Fqn.fromString("/foo");
Fqn backupFoo = BuddyManager.getBackupFqn(cache0.getLocalAddress(), foo);
cache0.put(foo, "key", "value");
// test that the data exists in both the data owner and the buddy
assertTrue("Data should exist in data owner", cache0.exists(foo));
assertTrue("Buddy should have data", cache1.exists(backupFoo));
// Sleep long enough for eviction to run twice plus a bit
TestingUtil.sleepThread(3050);
// test that the data we're looking for has been evicted in both the data owner and the buddy.
assertFalse("Data should have evicted in data owner", cache0.exists(foo));
assertFalse("Buddy should have data evicted", cache1.exists(backupFoo));
// now test that this exists in both loaders.
assertNotNull("Should exist in data owner's loader", cache0.getCacheLoader().get(foo));
assertNotNull("Should exist in buddy's loader", cache1.getCacheLoader().get(backupFoo));
// doing a get on cache2 will guarantee a remote data gravitation.
assertEquals("Passivated value available from buddy", "value", cache2.get(foo, "key"));
}
finally
{
cleanup(caches);
TestingUtil.recursiveRemove(new File(tmpLocation));
}
}
private void configureEviction(TreeCache cache) throws Exception
{
String evictionConfig = "<config>\n" +
" <attribute name=\"wakeUpIntervalSeconds\">1</attribute>\n" +
" <region name=\"/_default_\">\n" +
" <attribute name=\"maxNodes\">1</attribute>\n" +
" <attribute name=\"timeToLiveSeconds\">1</attribute>\n" +
" <attribute name=\"maxAgeSeconds\">2</attribute>\n" +
" </region>\n" +
" </config>";
cache.setEvictionPolicyClass(LRUPolicy.class.getName());
cache.setEvictionPolicyConfig(XmlHelper.stringToElement(evictionConfig));
}
}