package org.infinispan.xsite.statetransfer;
import static org.infinispan.test.TestingUtil.extractComponent;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.concurrent.TimeUnit;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.context.Flag;
import org.infinispan.statetransfer.CommitManager;
import org.infinispan.xsite.AbstractTwoSitesTest;
import org.infinispan.xsite.XSiteAdminOperations;
import org.testng.annotations.Test;
/**
* Simple test for the state transfer with different cache names.
*
* @author Pedro Ruivo
* @since 7.0
*/
@Test(groups = "xsite", testName = "xsite.statetransfer.BackupForStateTransferTest")
public class BackupForStateTransferTest extends AbstractTwoSitesTest {
private static final String LON_BACKUP_CACHE_NAME = "lonBackup";
public BackupForStateTransferTest() {
super();
this.implicitBackupCache = false;
}
public void testStateTransferWithClusterIdle() throws InterruptedException {
takeSiteOffline(LON, NYC);
assertOffline(LON, NYC);
assertNoStateTransferInReceivingSite(NYC, LON_BACKUP_CACHE_NAME);
assertNoStateTransferInSendingSite(LON);
//NYC is offline... lets put some initial data in
//we have 2 nodes in each site and the primary owner sends the state. Lets try to have more key than the chunk
//size in order to each site to send more than one chunk.
final int amountOfData = chunkSize(LON) * 4;
for (int i = 0; i < amountOfData; ++i) {
cache(LON, 0).put(key(i), value(0));
}
//check if NYC is empty (LON backup cache)
assertInSite(NYC, LON_BACKUP_CACHE_NAME, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
assertTrue(cache.isEmpty());
}
});
//check if NYC is empty (default cache)
assertInSite(NYC, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
assertTrue(cache.isEmpty());
}
});
startStateTransfer(LON, NYC);
eventually(new Condition() {
@Override
public boolean isSatisfied() throws Exception {
return extractComponent(cache(LON, 0), XSiteAdminOperations.class).getRunningStateTransfer().isEmpty();
}
}, TimeUnit.SECONDS.toMillis(30));
assertOnline(LON, NYC);
//check if all data is visible (LON backup cache)
assertInSite(NYC, LON_BACKUP_CACHE_NAME, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
for (int i = 0; i < amountOfData; ++i) {
assertEquals(value(0), cache.get(key(i)));
}
}
});
//check if NYC is empty (default cache)
assertInSite(NYC, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
assertTrue(cache.isEmpty());
}
});
assertNoStateTransferInReceivingSite(NYC, LON_BACKUP_CACHE_NAME);
assertNoStateTransferInSendingSite(LON);
}
@Override
protected ConfigurationBuilder getNycActiveConfig() {
return getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false);
}
@Override
protected ConfigurationBuilder getLonActiveConfig() {
return getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false);
}
private void startStateTransfer(String fromSite, String toSite) {
XSiteAdminOperations operations = extractComponent(cache(fromSite, 0), XSiteAdminOperations.class);
assertEquals(XSiteAdminOperations.SUCCESS, operations.pushState(toSite));
}
private void takeSiteOffline(String localSite, String remoteSite) {
XSiteAdminOperations operations = extractComponent(cache(localSite, 0), XSiteAdminOperations.class);
assertEquals(XSiteAdminOperations.SUCCESS, operations.takeSiteOffline(remoteSite));
}
private void assertOffline(String localSite, String remoteSite) {
XSiteAdminOperations operations = extractComponent(cache(localSite, 0), XSiteAdminOperations.class);
assertEquals(XSiteAdminOperations.OFFLINE, operations.siteStatus(remoteSite));
}
private void assertOnline(String localSite, String remoteSite) {
XSiteAdminOperations operations = extractComponent(cache(localSite, 0), XSiteAdminOperations.class);
assertEquals(XSiteAdminOperations.ONLINE, operations.siteStatus(remoteSite));
}
private int chunkSize(String site) {
return cache(site, 0).getCacheConfiguration().sites().allBackups().get(0).stateTransfer().chunkSize();
}
private void assertNoStateTransferInReceivingSite(String siteName, String cacheName) {
assertInSite(siteName, cacheName, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
CommitManager commitManager = extractComponent(cache, CommitManager.class);
assertFalse(commitManager.isTracking(Flag.PUT_FOR_STATE_TRANSFER));
assertFalse(commitManager.isTracking(Flag.PUT_FOR_X_SITE_STATE_TRANSFER));
assertTrue(commitManager.isEmpty());
}
});
}
private void assertNoStateTransferInSendingSite(String siteName) {
assertInSite(siteName, new AssertCondition<Object, Object>() {
@Override
public void assertInCache(Cache<Object, Object> cache) {
assertTrue(extractComponent(cache, XSiteStateProvider.class).getCurrentStateSending().isEmpty());
}
});
}
private Object key(int index) {
return "key-" + index;
}
private Object value(int index) {
return "value-" + index;
}
}