package org.jboss.cache.buddyreplication;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
import org.jboss.cache.Cache;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.util.TestingUtil;
import org.jboss.cache.util.CachePrinter;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import org.testng.annotations.*;
import java.util.List;
import java.util.ArrayList;
/**
* @author Mircea.Markus@jboss.com
*/
@Test(groups = "functional", testName = "buddyreplication.Buddy2NodesNoBuddyPoolTest")
public class Buddy2NodesNoBuddyPoolTest extends AbstractNodeBasedBuddyTest
{
@BeforeClass
public void createCaches() throws Exception
{
caches = createCaches(2, false);
}
@AfterMethod
@Override
public void tearDown() throws Exception
{
if (caches.size() > 2 && caches.get(2) != null)
{
Cache cache = caches.get(2);
caches.remove(2);
cache.stop();
cache.destroy();
}
super.tearDown();
}
@Test(dependsOnMethods = "testBuddyJoin")
public void testAddingNewCaches() throws Exception
{
// get some data in there.
caches.get(0).put("/cache0", "k", "v");
caches.get(1).put("/cache1", "k", "v");
waitForBuddy(caches.get(0), caches.get(1), true);
waitForBuddy(caches.get(1), caches.get(0), true);
assert caches.get(0).peek(fqnTransformer.getBackupRoot(caches.get(0).getLocalAddress()), false) == null : "Should not have backup region for self";
assert caches.get(0).peek(fqnTransformer.getBackupRoot(caches.get(1).getLocalAddress()), false) != null : "Should have backup region for buddy";
assert caches.get(1).peek(fqnTransformer.getBackupRoot(caches.get(0).getLocalAddress()), false) != null : "Should have backup region for buddy";
assert caches.get(1).peek(fqnTransformer.getBackupRoot(caches.get(1).getLocalAddress()), false) == null : "Should not have backup region for self";
caches.add(createCache(1, null));
TestingUtil.blockUntilViewsReceived(60000, caches);
waitForBuddy(caches.get(0), caches.get(1), true);
waitForBuddy(caches.get(1), caches.get(2), true);
waitForBuddy(caches.get(2), caches.get(0), true);
assert caches.get(0).peek(fqnTransformer.getBackupRoot(caches.get(0).getLocalAddress()), false) == null : "Should not have backup region for self";
assert caches.get(0).peek(fqnTransformer.getBackupRoot(caches.get(1).getLocalAddress()), false) == null : "Should have backup region for non-buddy";
assert caches.get(0).peek(fqnTransformer.getBackupRoot(caches.get(2).getLocalAddress()), false) != null : "Should have backup region for buddy";
assert caches.get(1).peek(fqnTransformer.getBackupRoot(caches.get(0).getLocalAddress()), false) != null : "Should have backup region for buddy";
assert caches.get(1).peek(fqnTransformer.getBackupRoot(caches.get(1).getLocalAddress()), false) == null : "Should not have backup region for self";
assert caches.get(1).peek(fqnTransformer.getBackupRoot(caches.get(2).getLocalAddress()), false) == null : "Should not have backup region for non-buddy";
assert caches.get(2).peek(fqnTransformer.getBackupRoot(caches.get(0).getLocalAddress()), false) == null : "Should not have backup region for non-buddy";
assert caches.get(2).peek(fqnTransformer.getBackupRoot(caches.get(1).getLocalAddress()), false) != null : "Should have backup region for buddy";
assert caches.get(2).peek(fqnTransformer.getBackupRoot(caches.get(2).getLocalAddress()), false) == null : "Should not have backup region for self";
// ensure no state transfer has happened!!
assert caches.get(2).peek(Fqn.fromString("/cache0"), false) == null : "Unnecessary state should not have been transferred!";
assert caches.get(2).peek(Fqn.fromString("/cache1"), false) == null : "Unnecessary state should not have been transferred!";
// ensure backup state has been transferred.
assert caches.get(2).peek(fqnTransformer.getBackupFqn(caches.get(1).getLocalAddress(), Fqn.fromString("/cache1")), false) != null : "Backup state should have transferred!";
}
public void testBuddyJoin() throws Exception
{
String key = "key";
String value = "value";
Fqn fqn = Fqn.fromString("/test");
Fqn backupFqn = fqnTransformer.getBackupFqn(caches.get(1).getLocalAddress(), fqn);
assertNoStaleLocks(caches);
// put something in cache 1
caches.get(1).put(fqn, key, value);
assertNoStaleLocks(caches);
// this should be in neither of the other cachePool' "main" trees
assertEquals(value, caches.get(1).get(fqn, key));
assertFalse("Should be false", caches.get(0).exists(fqn));
// check the backup trees
assertEquals("Buddy should have data in backup tree", value, caches.get(0).get(backupFqn, key));
assertNoStaleLocks(caches);
// now add a new cache to the cluster
caches.add(createCache(1, null));
// allow this cache a few msecs to join
TestingUtil.blockUntilViewsReceived(3000, caches.get(0), caches.get(1), caches.get(2));
TestingUtil.sleepThread(2000); // allow buddy group reorg
List<CacheSPI<Object, Object>> dump = new ArrayList<CacheSPI<Object, Object>>(caches);
dump.add(caches.get(2));
// now cachePool.get(1)'s buddy should be cache2, not cache[0]
assertIsBuddy(caches.get(1), caches.get(2), true);
// this should still be the same
assertIsBuddy(caches.get(0), caches.get(1), true);
// and cache2's buddy should be cache[0]
assertIsBuddy(caches.get(2), caches.get(0), true);
// so now the backup data we saw on cache[0] should have been removed.
assertFalse("This backup data should have been removed", caches.get(0).exists(backupFqn));
// while cache2 should now posess this backup (due to a state transfer)
assertEquals("Backup state should have been transferred to this new cache instance", value, caches.get(2).get(backupFqn, key));
caches.get(1).removeNode(fqn);
assertNoStaleLocks(caches);
assertFalse("Should be null", caches.get(0).exists(fqn));
assertFalse("Should be null", caches.get(1).exists(fqn));
assertFalse("Should be null", caches.get(2).exists(fqn));
// check the backup trees
assertFalse("Should be null", caches.get(0).exists(backupFqn));
assertFalse("Should be null", caches.get(1).exists(backupFqn));
assertFalse("Should be null", caches.get(2).exists(backupFqn));
assertNoStaleLocks(caches);
}
/**
* Test for https://jira.jboss.org/jira/browse/JBCACHE-1549
*
* @throws Exception
*/
public void testStateTransferOnBuddyRestart() throws Exception
{
String key = "key";
String value = "value";
Fqn fqn = Fqn.fromString("/test");
Fqn backupFqn = fqnTransformer.getBackupFqn(caches.get(0).getLocalAddress(), fqn);
assertNoStaleLocks(caches);
// put something in cache 0
caches.get(0).put(fqn, key, value);
assertNoStaleLocks(caches);
// this should be in neither of the other cachePool' "main" trees
assertEquals(value, caches.get(0).get(fqn, key));
assertFalse("Should be false", caches.get(1).exists(fqn));
// check the backup trees
assertEquals("Buddy should have data in backup tree", value, caches.get(1).get(backupFqn, key));
assertNoStaleLocks(caches);
// now re-start cache 1
caches.get(1).stop();
TestingUtil.blockUntilViewsReceived(3000, caches.get(0));
caches.get(1).start();
// allow this cache a few msecs to join
TestingUtil.blockUntilViewsReceived(3000, caches.get(0), caches.get(1));
TestingUtil.sleepThread(2000); // allow buddy group reorg
// check the backup tree to confirm that original key/value was transferred
// This is the test that fails with JBCACHE-1549
assertEquals("Buddy should have data in backup tree", value, caches.get(1).get(backupFqn, key));
}
}