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.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.context.Flag;
import org.infinispan.statetransfer.CommitManager;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.xsite.AbstractXSiteTest;
import org.infinispan.xsite.XSiteAdminOperations;
import org.testng.annotations.Test;
/**
* Tests the {@link org.infinispan.xsite.BackupReceiver} for the local caches.
*
* @author Pedro Ruivo
* @since 7.1
*/
@Test(groups = "xsite", testName = "xsite.statetransfer.LocalCacheStateTransferTest")
public class LocalCacheStateTransferTest extends AbstractXSiteTest {
private static final String LON = "LON";
private static final String NYC = "NYC";
public void testStateTransferWithClusterIdle() throws InterruptedException {
takeSiteOffline(LON, NYC);
assertOffline(LON, NYC);
assertNoStateTransferInReceivingSite(NYC);
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, 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, 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 all data is visible NYC
assertInSite(NYC, 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)));
}
}
});
assertNoStateTransferInReceivingSite(NYC);
assertNoStateTransferInSendingSite(LON);
}
@Override
protected void createSites() {
createSite(LON, 1, globalConfigurationBuilderForSite(LON), configurationBuilderForSite(NYC));
createSite(NYC, 1, globalConfigurationBuilderForSite(NYC), TestCacheManagerFactory.getDefaultCacheConfiguration(false));
}
private GlobalConfigurationBuilder globalConfigurationBuilderForSite(String siteName) {
GlobalConfigurationBuilder builder = GlobalConfigurationBuilder.defaultClusteredBuilder();
builder.site().localSite(siteName);
return builder;
}
private ConfigurationBuilder configurationBuilderForSite(String backupSiteName) {
ConfigurationBuilder builder = getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC);
builder.sites().addBackup().site(backupSiteName)
.stateTransfer().chunkSize(1);
return builder;
}
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) {
Cache<?, ?> cache = cache(siteName, 0);
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) {
Cache<?, ?> cache = cache(siteName, 0);
assertTrue(extractComponent(cache, XSiteStateProvider.class).getCurrentStateSending().isEmpty());
}
private Object key(int index) {
return "key-" + index;
}
private Object value(int index) {
return "value-" + index;
}
}