/*
* 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.Cache;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.Region;
import org.jboss.cache.config.BuddyReplicationConfig;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
import org.jboss.cache.factories.XmlConfigurationParser;
import org.jboss.cache.misc.TestingUtil;
import org.jboss.cache.util.CachePrinter;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.HashMap;
import java.util.Map;
/**
* Tests handling of the buddy backup region during region
* activation and inactivation
*
* @author Brian Stansberry
*/
@Test
public class BuddyBackupActivationInactivationTest extends BuddyReplicationTestsBase
{
public static final Fqn<String> A = Fqn.fromString("/a");
public static final Fqn<String> A_B = Fqn.fromString("/a/b");
public static final String JOE = "JOE";
protected Map<String, Cache> caches;
private ClassLoader orig_TCL;
public void testBuddyBackupActivation() throws Exception
{
CacheSPI cache1 = createCache("cache1", true, true, true);
CacheSPI cache2 = createCache("cache2", true, true, true);
Fqn A = Fqn.fromString("/a");
TestingUtil.blockUntilViewsReceived(VIEW_BLOCK_TIMEOUT, cache1, cache2);
// create the regions on the two caches first
Region c1 = cache1.getRegionManager().getRegion(A, Region.Type.MARSHALLING, true);
Region c2 = cache2.getRegionManager().getRegion(A, Region.Type.MARSHALLING, true);
assertFalse(c1.isActive());
assertFalse(c2.isActive());
c1.activate();
cache1.put(A_B, "name", JOE);
TestingUtil.sleepThread(getSleepTimeout());
System.out.println("Cache dump BEFORE activation");
System.out.println("cache1 " + CachePrinter.printCacheDetails(cache1));
System.out.println("cache2 " + CachePrinter.printCacheDetails(cache2));
c2.activate();
System.out.println("Cache dump AFTER activation");
System.out.println("cache1 " + CachePrinter.printCacheDetails(cache1));
System.out.println("cache2 " + CachePrinter.printCacheDetails(cache2));
Fqn fqn = BuddyManager.getBackupFqn(cache1.getLocalAddress(), A_B);
assertEquals("State transferred with activation", JOE, cache2.get(fqn, "name"));
}
public void testReplToInactiveRegion() throws Exception
{
CacheSPI cache1 = createCache("cache1", true, true, true);
CacheSPI cache2 = createCache("cache2", true, true, true);
TestingUtil.blockUntilViewsReceived(VIEW_BLOCK_TIMEOUT, cache1, cache2);
Fqn backupFqn = BuddyManager.getBackupFqn(cache1.getLocalAddress(), A_B);
Fqn<String> A = Fqn.fromString("/a");
Region regionA = cache1.getRegion(A, true);
regionA.registerContextClassLoader(getClass().getClassLoader());
regionA.activate();
// Activate the buddy backup subtree in the recipient so any
// repl message doesn't get rejected due to that tree being inactive
cache2.getRegionManager().activate(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
cache2.getRegionManager().deactivate(A);
cache1.put(A_B, "name", JOE);
TestingUtil.sleepThread(getSleepTimeout());
assertNull("Should be no replication to inactive region", cache2.get(A_B, "name"));
assertNull("Should be no replication to inactive backup region", cache2.get(backupFqn, "name"));
}
public void testBuddyBackupInactivation() throws Exception
{
CacheSPI cache1 = createCache("cache1", true, true, true);
Fqn<String> A = Fqn.fromString("/a");
Region regionA = cache1.getRegion(A, true);
regionA.registerContextClassLoader(getClass().getClassLoader());
regionA.activate();
Fqn<String> fqn = new Fqn<String>(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, "test");
fqn = new Fqn<String>(fqn, A_B);
cache1.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
cache1.put(fqn, "name", JOE);
assertEquals("Put should have been OK", JOE, cache1.get(fqn, "name"));
regionA.deactivate();
assertNull("Inactivation should have cleared region", cache1.get(fqn, "name"));
}
protected CacheSPI<?, ?> createCache(String cacheID,
boolean sync,
boolean useMarshalling,
boolean startCache)
throws Exception
{
if (caches.get(cacheID) != null)
{
throw new IllegalStateException(cacheID + " already created");
}
CacheMode mode = sync ? CacheMode.REPL_SYNC : CacheMode.REPL_ASYNC;
Configuration c = UnitTestCacheConfigurationFactory.createConfiguration(mode);
CacheSPI<?, ?> cache = (CacheSPI<?, ?>) new DefaultCacheFactory().createCache(c, false);
cache.getConfiguration().setClusterName("TestCluster");
if (useMarshalling)
{
cache.getConfiguration().setUseRegionBasedMarshalling(true);
cache.getConfiguration().setInactiveOnStartup(true);
}
cache.getConfiguration().setBuddyReplicationConfig(getBuddyConfig());
// Put the cache in the map before starting, so if it fails in
// start it can still be destroyed later
caches.put(cacheID, cache);
if (startCache)
{
cache.create();
cache.start();
}
return cache;
}
@BeforeMethod(alwaysRun = true)
protected void setUp() throws Exception
{
caches = new HashMap<String, Cache>();
// Save the TCL in case a test changes it
orig_TCL = Thread.currentThread().getContextClassLoader();
}
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
super.tearDown();
// Restore the TCL in case a test changed it
Thread.currentThread().setContextClassLoader(orig_TCL);
for (String cacheID : caches.keySet())
{
stopCache(caches.get(cacheID));
}
}
protected void stopCache(Cache cache)
{
if (cache != null)
{
try
{
cache.stop();
cache.destroy();
}
catch (Exception e)
{
System.out.println("Exception stopping cache " + e.getMessage());
e.printStackTrace(System.out);
}
}
}
private BuddyReplicationConfig getBuddyConfig() throws Exception
{
// TODO just build the object; skip the legacy XML business
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
Element config = doc.createElement("config");
doc.appendChild(config);
Element replEnabled = doc.createElement("buddyReplicationEnabled");
replEnabled.appendChild(doc.createTextNode("true"));
config.appendChild(replEnabled);
Element gravDisabled = doc.createElement("autoDataGravitation");
gravDisabled.appendChild(doc.createTextNode("false"));
config.appendChild(gravDisabled);
return XmlConfigurationParser.parseBuddyReplicationConfig(config);
}
}