package org.infinispan.test.fwk;
import static org.infinispan.test.fwk.JGroupsConfigBuilder.getJGroupsConfig;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLStreamException;
import org.infinispan.commons.executors.BlockingThreadPoolExecutorFactory;
import org.infinispan.commons.marshall.Marshaller;
import org.infinispan.commons.util.FileLookupFactory;
import org.infinispan.commons.util.LegacyKeySupportSystemProperties;
import org.infinispan.commons.util.Util;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.Index;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
import org.infinispan.configuration.parsing.ParserRegistry;
import org.infinispan.jmx.MBeanServerLookup;
import org.infinispan.jmx.PerThreadMBeanServerLookup;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
import org.infinispan.transaction.TransactionMode;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* CacheManagers in unit tests should be created with this factory, in order to avoid resource clashes. See
* http://community.jboss.org/wiki/ParallelTestSuite for more details.
*
* @author Mircea.Markus@jboss.com
* @author Galder ZamarreƱo
*/
public class TestCacheManagerFactory {
public static final int ASYNC_EXEC_MAX_THREADS = 4;
public static final int ASYNC_EXEC_QUEUE_SIZE = 10000;
public static final int REMOTE_EXEC_MAX_THREADS = 6;
public static final int REMOTE_EXEC_QUEUE_SIZE = 0;
public static final int STATE_TRANSFER_EXEC_MAX_THREADS = 4;
public static final int STATE_TRANSFER_EXEC_QUEUE_SIZE = 0;
public static final int TRANSPORT_EXEC_MAX_THREADS = 6;
public static final int TRANSPORT_EXEC_QUEUE_SIZE = 10000;
public static final int KEEP_ALIVE = 30000;
public static final String MARSHALLER = LegacyKeySupportSystemProperties.getProperty("infinispan.test.marshaller.class", "infinispan.marshaller.class");
private static final Log log = LogFactory.getLog(TestCacheManagerFactory.class);
/**
* Note this method does not amend the global configuration to reduce overall resource footprint. It is therefore
* suggested to use {@link org.infinispan.test.fwk.TestCacheManagerFactory#createClusteredCacheManager(org.infinispan.configuration.cache.ConfigurationBuilder, TransportFlags)}
* instead when this is needed
* @param start Whether to start this cache container
* @param gc The global configuration builder to use
* @param c The default configuration to use
* @param keepJmxDomain Whether or not the provided jmx domain should be used or if a unique one is generated
* @return The resultant cache manager that is created
*/
public static EmbeddedCacheManager newDefaultCacheManager(boolean start, GlobalConfigurationBuilder gc, ConfigurationBuilder c, boolean keepJmxDomain) {
if (!keepJmxDomain) {
gc.globalJmxStatistics().jmxDomain("infinispan-" + UUID.randomUUID());
}
return newDefaultCacheManager(start, gc, c);
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, ConfigurationBuilderHolder holder, boolean keepJmxDomain) {
if (!keepJmxDomain) {
holder.getGlobalConfigurationBuilder().globalJmxStatistics().jmxDomain(
"infinispan-" + UUID.randomUUID());
}
return newDefaultCacheManager(start, holder);
}
public static EmbeddedCacheManager fromXml(String xmlFile) throws IOException {
return fromXml(xmlFile, false);
}
public static EmbeddedCacheManager fromXml(String xmlFile, boolean keepJmxDomainName) throws IOException {
InputStream is = FileLookupFactory.newInstance().lookupFileStrict(
xmlFile, Thread.currentThread().getContextClassLoader());
return fromStream(is, keepJmxDomainName);
}
public static EmbeddedCacheManager fromXml(String xmlFile, boolean keepJmxDomainName, boolean defaultParserOnly) throws IOException {
InputStream is = FileLookupFactory.newInstance().lookupFileStrict(
xmlFile, Thread.currentThread().getContextClassLoader());
return fromStream(is, keepJmxDomainName, defaultParserOnly, true);
}
public static EmbeddedCacheManager fromXml(String xmlFile, boolean keepJmxDomainName, boolean defaultParserOnly, boolean start) throws IOException {
InputStream is = FileLookupFactory.newInstance().lookupFileStrict(
xmlFile, Thread.currentThread().getContextClassLoader());
return fromStream(is, keepJmxDomainName, defaultParserOnly, start);
}
public static EmbeddedCacheManager fromStream(InputStream is) throws IOException {
return fromStream(is, false);
}
public static EmbeddedCacheManager fromStream(InputStream is, boolean keepJmxDomainName) throws IOException {
return fromStream(is, keepJmxDomainName, true);
}
public static EmbeddedCacheManager fromStream(InputStream is, boolean keepJmxDomainName, boolean defaultParsersOnly) throws IOException {
return fromStream(is, keepJmxDomainName, defaultParsersOnly, true);
}
public static EmbeddedCacheManager fromStream(InputStream is, boolean keepJmxDomainName, boolean defaultParsersOnly, boolean start) throws IOException {
ParserRegistry parserRegistry = new ParserRegistry(Thread.currentThread().getContextClassLoader(), defaultParsersOnly);
ConfigurationBuilderHolder holder = parserRegistry.parse(is);
return createClusteredCacheManager(start, holder, keepJmxDomainName);
}
public static EmbeddedCacheManager fromString(String config) throws IOException {
return fromStream(new ByteArrayInputStream(config.getBytes()));
}
private static void markAsTransactional(boolean transactional, ConfigurationBuilder builder) {
if (!transactional) {
builder.transaction().transactionMode(TransactionMode.NON_TRANSACTIONAL);
} else {
builder.transaction()
.transactionMode(TransactionMode.TRANSACTIONAL);
//Skip this step in OSGi. This operation requires internal packages of Arjuna. These are not exported from the Arjuna
//bundle in OSGi
if (!Util.isOSGiContext()) {
// Set volatile stores just in case...
JBossTransactionsUtils.setVolatileStores();
//automatically change default TM lookup to the desired one but only outside OSGi. In OSGi we need to use GenericTransactionManagerLookup
builder.transaction().transactionManagerLookup(Util.getInstance(TransactionSetup.getManagerLookup(), TestCacheManagerFactory.class.getClassLoader()));
}
}
}
private static void updateTransactionSupport(boolean transactional, ConfigurationBuilder builder) {
if (transactional) amendJTA(builder);
}
private static void amendJTA(ConfigurationBuilder builder) {
if (builder.transaction().transactionMode() == TransactionMode.TRANSACTIONAL && builder.transaction().transactionManagerLookup() == null) {
builder.transaction().transactionManagerLookup(Util.getInstance(TransactionSetup.getManagerLookup(), TestCacheManagerFactory.class.getClassLoader()));
}
}
/**
* Creates an cache manager that does support clustering.
*/
public static EmbeddedCacheManager createClusteredCacheManager() {
return createClusteredCacheManager(new ConfigurationBuilder(), new TransportFlags());
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilder defaultCacheConfig, TransportFlags flags) {
return createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), defaultCacheConfig, flags);
}
public static EmbeddedCacheManager createClusteredCacheManager(GlobalConfigurationBuilder gcb, ConfigurationBuilder defaultCacheConfig) {
return createClusteredCacheManager(gcb, defaultCacheConfig, new TransportFlags());
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilder defaultCacheConfig) {
return createClusteredCacheManager(GlobalConfigurationBuilder.defaultClusteredBuilder(), defaultCacheConfig);
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilderHolder holder) {
return createClusteredCacheManager(holder, false);
}
public static EmbeddedCacheManager createClusteredCacheManager(ConfigurationBuilderHolder holder, boolean keepJmxDomainName) {
return createClusteredCacheManager(true, holder, keepJmxDomainName);
}
public static EmbeddedCacheManager createClusteredCacheManager(boolean start, ConfigurationBuilderHolder holder, boolean keepJmxDomainName) {
TransportFlags flags = new TransportFlags();
amendGlobalConfiguration(holder.getGlobalConfigurationBuilder(), flags);
for (ConfigurationBuilder builder : holder.getNamedConfigurationBuilders().values())
amendJTA(builder);
return newDefaultCacheManager(start, holder, keepJmxDomainName);
}
public static EmbeddedCacheManager createClusteredCacheManager(GlobalConfigurationBuilder gcb, ConfigurationBuilder defaultCacheConfig, TransportFlags flags) {
return createClusteredCacheManager(gcb, defaultCacheConfig, flags, false);
}
public static EmbeddedCacheManager createClusteredCacheManager(GlobalConfigurationBuilder gcb,
ConfigurationBuilder defaultCacheConfig,
TransportFlags flags,
boolean keepJmxDomainName) {
amendGlobalConfiguration(gcb, flags);
amendJTA(defaultCacheConfig);
return newDefaultCacheManager(true, gcb, defaultCacheConfig, keepJmxDomainName);
}
public static EmbeddedCacheManager createClusteredCacheManager(boolean start, GlobalConfigurationBuilder gcb,
ConfigurationBuilder defaultCacheConfig,
TransportFlags flags,
boolean keepJmxDomainName) {
amendGlobalConfiguration(gcb, flags);
amendJTA(defaultCacheConfig);
return newDefaultCacheManager(start, gcb, defaultCacheConfig, keepJmxDomainName);
}
public static void amendGlobalConfiguration(GlobalConfigurationBuilder gcb, TransportFlags flags) {
amendMarshaller(gcb);
minimizeThreads(gcb);
amendTransport(gcb, flags);
}
public static EmbeddedCacheManager createCacheManager(ConfigurationBuilder builder) {
return createCacheManager(new GlobalConfigurationBuilder().nonClusteredDefault(), builder);
}
public static EmbeddedCacheManager createCacheManager() {
return createCacheManager(new ConfigurationBuilder());
}
public static EmbeddedCacheManager createCacheManager(boolean start) {
return newDefaultCacheManager(start, new GlobalConfigurationBuilder().nonClusteredDefault(), new ConfigurationBuilder(), false);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfigurationBuilder globalBuilder, ConfigurationBuilder builder) {
if (globalBuilder.transport().build().transport().transport() != null) {
throw new IllegalArgumentException("Use TestCacheManagerFactory.createClusteredCacheManager(...) for clustered cache managers");
}
return newDefaultCacheManager(true, globalBuilder, builder, false);
}
public static EmbeddedCacheManager createCacheManager(GlobalConfigurationBuilder globalBuilder, ConfigurationBuilder builder, boolean keepJmxDomain) {
if (globalBuilder.transport().build().transport().transport() != null) {
throw new IllegalArgumentException("Use TestCacheManagerFactory.createClusteredCacheManager(...) for clustered cache managers");
}
return newDefaultCacheManager(true, globalBuilder, builder, keepJmxDomain);
}
public static EmbeddedCacheManager createCacheManager(CacheMode mode, boolean indexing) {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder
.clustering()
.cacheMode(mode)
.indexing()
.index(indexing ? Index.ALL : Index.NONE)
.addProperty("lucene_version", "LUCENE_CURRENT")
;
if (mode.isClustered()) {
return createClusteredCacheManager(builder);
}
else {
return createCacheManager(builder);
}
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain) {
return createCacheManagerEnforceJmxDomain(jmxDomain, true, true);
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(String jmxDomain) {
return createClusteredCacheManagerEnforceJmxDomain(jmxDomain, true, false, new ConfigurationBuilder());
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(String jmxDomain, boolean allowDuplicateDomains) {
return createClusteredCacheManagerEnforceJmxDomain(jmxDomain, true, allowDuplicateDomains, new ConfigurationBuilder());
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(String cacheManagerName, String jmxDomain, boolean allowDuplicateDomains) {
return createClusteredCacheManagerEnforceJmxDomain(cacheManagerName, jmxDomain, true, allowDuplicateDomains, new ConfigurationBuilder(), new PerThreadMBeanServerLookup());
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(String jmxDomain, ConfigurationBuilder builder) {
return createClusteredCacheManagerEnforceJmxDomain(jmxDomain, true, false, builder);
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(
String jmxDomain, boolean exposeGlobalJmx, boolean allowDuplicateDomains, ConfigurationBuilder builder) {
return createClusteredCacheManagerEnforceJmxDomain(null, jmxDomain,
exposeGlobalJmx, allowDuplicateDomains, builder, new PerThreadMBeanServerLookup());
}
public static EmbeddedCacheManager createClusteredCacheManagerEnforceJmxDomain(
String cacheManagerName, String jmxDomain, boolean exposeGlobalJmx, boolean allowDuplicateDomains, ConfigurationBuilder builder,
MBeanServerLookup mBeanServerLookup) {
GlobalConfigurationBuilder globalBuilder = GlobalConfigurationBuilder.defaultClusteredBuilder();
amendGlobalConfiguration(globalBuilder, new TransportFlags());
globalBuilder.globalJmxStatistics()
.jmxDomain(jmxDomain)
.mBeanServerLookup(mBeanServerLookup)
.allowDuplicateDomains(allowDuplicateDomains)
.enabled(exposeGlobalJmx);
if (cacheManagerName != null) {
globalBuilder.globalJmxStatistics().cacheManagerName(cacheManagerName);
}
return createClusteredCacheManager(globalBuilder, builder, new TransportFlags(), true);
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain, boolean exposeGlobalJmx, boolean exposeCacheJmx) {
return createCacheManagerEnforceJmxDomain(jmxDomain, null, exposeGlobalJmx, exposeCacheJmx);
}
/**
* @see #createCacheManagerEnforceJmxDomain(String)
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(String jmxDomain, String cacheManagerName, boolean exposeGlobalJmx, boolean exposeCacheJmx) {
GlobalConfigurationBuilder globalConfiguration = new GlobalConfigurationBuilder();
globalConfiguration
.globalJmxStatistics()
.jmxDomain(jmxDomain)
.mBeanServerLookup(new PerThreadMBeanServerLookup())
.enabled(exposeGlobalJmx);
if (cacheManagerName != null)
globalConfiguration.globalJmxStatistics().cacheManagerName(cacheManagerName);
ConfigurationBuilder configuration = new ConfigurationBuilder();
configuration.jmxStatistics().enabled(exposeCacheJmx);
return createCacheManager(globalConfiguration, configuration, true);
}
public static ConfigurationBuilder getDefaultCacheConfiguration(boolean transactional) {
return getDefaultCacheConfiguration(transactional, false);
}
public static ConfigurationBuilder getDefaultCacheConfiguration(boolean transactional, boolean useCustomTxLookup) {
ConfigurationBuilder builder = new ConfigurationBuilder();
markAsTransactional(transactional, builder);
//don't changed the tx lookup.
if (useCustomTxLookup) updateTransactionSupport(transactional, builder);
return builder;
}
public static void amendTransport(GlobalConfigurationBuilder cfg) {
amendTransport(cfg, new TransportFlags());
}
private static void amendTransport(GlobalConfigurationBuilder builder, TransportFlags flags) {
org.infinispan.configuration.global.GlobalConfiguration gc = builder.build();
if (gc.transport().transport() != null) { //this is local
String testName = TestResourceTracker.getCurrentTestName();
String nextCacheName = TestResourceTracker.getNextNodeName();
// Remove any configuration file that might have been set.
builder.transport().removeProperty(JGroupsTransport.CONFIGURATION_FILE);
builder
.transport()
.addProperty(JGroupsTransport.CONFIGURATION_STRING, getJGroupsConfig(testName, flags))
.nodeName(nextCacheName);
}
}
public static void minimizeThreads(GlobalConfigurationBuilder builder) {
BlockingThreadPoolExecutorFactory executorFactory;
executorFactory = new BlockingThreadPoolExecutorFactory(ASYNC_EXEC_MAX_THREADS,
ASYNC_EXEC_MAX_THREADS, ASYNC_EXEC_QUEUE_SIZE, KEEP_ALIVE);
builder.asyncThreadPool().threadPoolFactory(executorFactory);
executorFactory = new BlockingThreadPoolExecutorFactory(STATE_TRANSFER_EXEC_MAX_THREADS,
STATE_TRANSFER_EXEC_MAX_THREADS, STATE_TRANSFER_EXEC_QUEUE_SIZE, KEEP_ALIVE);
builder.stateTransferThreadPool().threadPoolFactory(executorFactory);
executorFactory = new BlockingThreadPoolExecutorFactory(REMOTE_EXEC_MAX_THREADS,
REMOTE_EXEC_MAX_THREADS, REMOTE_EXEC_QUEUE_SIZE, KEEP_ALIVE);
builder.transport().remoteCommandThreadPool().threadPoolFactory(executorFactory);
executorFactory = new BlockingThreadPoolExecutorFactory(
TRANSPORT_EXEC_MAX_THREADS, TRANSPORT_EXEC_MAX_THREADS, TRANSPORT_EXEC_QUEUE_SIZE, KEEP_ALIVE);
builder.transport().transportThreadPool().threadPoolFactory(executorFactory);
}
public static void amendMarshaller(GlobalConfigurationBuilder builder) {
if (MARSHALLER != null) {
try {
Marshaller marshaller = Util.getInstanceStrict(MARSHALLER, Thread.currentThread().getContextClassLoader());
builder.serialization().marshaller(marshaller);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
// No-op, stick to GlobalConfiguration default.
}
}
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, GlobalConfigurationBuilder gc, ConfigurationBuilder c) {
GlobalConfiguration globalConfiguration = gc.build();
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(globalConfiguration, c.build(globalConfiguration), start);
TestResourceTracker.addResource(new TestResourceTracker.CacheManagerCleaner(defaultCacheManager));
return defaultCacheManager;
}
private static DefaultCacheManager newDefaultCacheManager(boolean start, ConfigurationBuilderHolder holder) {
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(holder, start);
TestResourceTracker.addResource(new TestResourceTracker.CacheManagerCleaner(defaultCacheManager));
return defaultCacheManager;
}
public static ConfigurationBuilderHolder buildAggregateHolder(String... xmls)
throws XMLStreamException, FactoryConfigurationError {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
ParserRegistry registry = new ParserRegistry(cl);
ConfigurationBuilderHolder holder = new ConfigurationBuilderHolder(cl);
for (String xml : xmls) {
registry.parse(new ByteArrayInputStream(xml.getBytes()), holder);
}
return holder;
}
}