/*
* JBoss, Home of Professional Open Source
* Copyright 2010 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.statetransfer;
import java.io.File;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import org.infinispan.Cache;
import org.infinispan.config.CacheLoaderManagerConfig;
import org.infinispan.config.Configuration;
import org.infinispan.loaders.file.FileCacheStoreConfig;
import org.infinispan.manager.CacheContainer;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.test.MultipleCacheManagersTest;
import org.infinispan.test.TestingUtil;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import static org.infinispan.statetransfer.StateTransferTestingUtil.*;
/**
* StateTransferFileCacheStoreFunctionalTest.
*
* @author Galder ZamarreƱo
* @since 4.0
*/
@Test(groups = "functional", testName = "statetransfer.StateTransferFileCacheLoaderFunctionalTest")
public class StateTransferFileCacheLoaderFunctionalTest extends MultipleCacheManagersTest {
static final Log log = LogFactory.getLog(StateTransferFileCacheLoaderFunctionalTest.class);
static String cacheName = "nbst-with-file-loader";
volatile int testCount = 0;
ThreadLocal<Boolean> sharedCacheLoader = new ThreadLocal<Boolean>() {
protected Boolean initialValue() {
return false;
}
};
String tmpDirectory1;
String tmpDirectory2;
String tmpDirectory3;
String tmpDirectory4;
Configuration config;
@BeforeTest
@Parameters({"basedir"})
protected void setUpTempDir(@Optional(value = "/tmp") String basedir) {
tmpDirectory1 = basedir + File.separator + TestingUtil.TEST_PATH + File.separator + "1" + File.separator + getClass().getSimpleName();
tmpDirectory2 = basedir + File.separator + TestingUtil.TEST_PATH + File.separator + "2" + File.separator + getClass().getSimpleName();
tmpDirectory3 = basedir + File.separator + TestingUtil.TEST_PATH + File.separator + "3" + File.separator + getClass().getSimpleName();
tmpDirectory4 = basedir + File.separator + TestingUtil.TEST_PATH + File.separator + "4" + File.separator + getClass().getSimpleName();
}
@AfterMethod(alwaysRun = true)
protected void clearTempDir() {
TestingUtil.recursiveFileRemove(tmpDirectory1);
new File(tmpDirectory1).mkdirs();
TestingUtil.recursiveFileRemove(tmpDirectory2);
new File(tmpDirectory2).mkdirs();
TestingUtil.recursiveFileRemove(tmpDirectory3);
new File(tmpDirectory3).mkdirs();
TestingUtil.recursiveFileRemove(tmpDirectory4);
new File(tmpDirectory4).mkdirs();
}
@Override
protected void createCacheManagers() throws Throwable {
// This impl only really sets up a configuration for use later.
config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
config.setSyncReplTimeout(30000);
config.setFetchInMemoryState(true);
config.setUseLockStriping(false); // reduces the odd chance of a key collision and deadlock
}
protected CacheContainer createCacheManager(String tmpDirectory) {
// increment the DIMCS store id
FileCacheStoreConfig cfg = new FileCacheStoreConfig();
cfg.setLocation(tmpDirectory);
cfg.setPurgeSynchronously(true); // for more accurate unit testing
cfg.setFetchPersistentState(true);
CacheLoaderManagerConfig clmc = new CacheLoaderManagerConfig();
clmc.addCacheLoaderConfig(cfg);
clmc.setShared(sharedCacheLoader.get());
config.setCacheLoaderManagerConfig(clmc);
EmbeddedCacheManager cm = addClusterEnabledCacheManager();
cm.defineConfiguration(cacheName, config.clone());
return cm;
}
public void testSharedLoader() throws Exception {
CacheContainer cm1 = null, cm2 = null;
try {
sharedCacheLoader.set(true);
cm1 = createCacheManager(tmpDirectory1);
Cache c1 = cm1.getCache(cacheName);
verifyNoDataOnLoader(c1);
verifyNoData(c1);
writeInitialData(c1);
// starting the second cache would initialize an in-memory state transfer but not a persistent one since the loader is shared
cm2 = createCacheManager(tmpDirectory2);
Cache c2 = cm2.getCache(cacheName);
TestingUtil.blockUntilViewsReceived(60000, c1, c2);
verifyInitialDataOnLoader(c1);
verifyInitialData(c1);
verifyNoDataOnLoader(c2);
verifyNoData(c2);
} finally {
if (cm1 != null) cm1.stop();
if (cm2 != null) cm2.stop();
sharedCacheLoader.set(false);
}
}
public void testInitialStateTransfer() throws Exception {
testCount++;
log.info("testInitialStateTransfer start - " + testCount);
CacheContainer cm1 = null, cm2 = null;
try {
Cache<Object, Object> cache1, cache2;
cm1 = createCacheManager(tmpDirectory1);
cache1 = cm1.getCache(cacheName);
writeInitialData(cache1);
cm2 = createCacheManager(tmpDirectory2);
cache2 = cm2.getCache(cacheName);
// Pause to give caches time to see each other
TestingUtil.blockUntilViewsReceived(60000, cache1, cache2);
verifyInitialData(cache2);
log.info("testInitialStateTransfer end - " + testCount);
} finally {
if (cm1 != null) cm1.stop();
if (cm2 != null) cm2.stop();
}
}
public void testInitialStateTransferInDifferentThread(Method m) throws Exception {
testCount++;
log.info(m.getName() + " start - " + testCount);
CacheContainer cm1 = null, cm2 = null, cm30 = null;
try {
Cache<Object, Object> cache1 = null, cache2 = null, cache3 = null;
cm1 = createCacheManager(tmpDirectory1);
cache1 = cm1.getCache(cacheName);
writeInitialData(cache1);
cm2 = createCacheManager(tmpDirectory2);
cache2 = cm2.getCache(cacheName);
cache1.put("delay", new StateTransferFunctionalTest.DelayTransfer());
// Pause to give caches time to see each other
TestingUtil.blockUntilViewsReceived(60000, cache1, cache2);
verifyInitialData(cache2);
final CacheContainer cm3 = createCacheManager(tmpDirectory3);
cm30 = cm3;
Future<Void> f1 = fork(new Callable<Void>() {
public Void call() throws Exception {
cm3.getCache(cacheName);
return null;
}
});
f1.get();
cache3 = cm3.getCache(cacheName);
TestingUtil.blockUntilViewsReceived(120000, cache1, cache2, cache3);
verifyInitialData(cache3);
log.info("testConcurrentStateTransfer end - " + testCount);
} finally {
if (cm1 != null) cm1.stop();
if (cm2 != null) cm2.stop();
if (cm30 != null) cm30.stop();
}
}
public void testConcurrentStateTransfer() throws Exception {
testCount++;
log.info("testConcurrentStateTransfer start - " + testCount);
CacheContainer cm1 = null, cm2 = null, cm30 = null, cm40 = null;
try {
Cache<Object, Object> cache1 = null, cache2 = null, cache3 = null, cache4 = null;
cm1 = createCacheManager(tmpDirectory1);
cache1 = cm1.getCache(cacheName);
writeInitialData(cache1);
cm2 = createCacheManager(tmpDirectory2);
cache2 = cm2.getCache(cacheName);
cache1.put("delay", new StateTransferFunctionalTest.DelayTransfer());
// Pause to give caches time to see each other
TestingUtil.blockUntilViewsReceived(60000, cache1, cache2);
verifyInitialData(cache2);
final CacheContainer cm3 = createCacheManager(tmpDirectory3);
final CacheContainer cm4 = createCacheManager(tmpDirectory4);
cm30 = cm3;
cm40 = cm4;
Future<Void> f1 = fork(new Callable<Void>() {
public Void call() throws Exception {
cm3.getCache(cacheName);
return null;
}
});
Future<Void> f2 = fork(new Callable<Void>() {
public Void call() throws Exception {
cm4.getCache(cacheName);
return null;
}
});
f1.get();
f2.get();
cache3 = cm3.getCache(cacheName);
cache4 = cm4.getCache(cacheName);
TestingUtil.blockUntilViewsReceived(120000, cache1, cache2, cache3, cache4);
verifyInitialData(cache3);
verifyInitialData(cache4);
log.info("testConcurrentStateTransfer end - " + testCount);
} finally {
if (cm1 != null) cm1.stop();
if (cm2 != null) cm2.stop();
if (cm30 != null) cm30.stop();
if (cm40 != null) cm40.stop();
}
}
}