org.terracotta.modules.ehcache.store.TerracottaClusteredInstanceFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
/*
* All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
*/
package org.terracotta.modules.ehcache.store;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.cluster.CacheCluster;
import net.sf.ehcache.config.CacheWriterConfiguration;
import net.sf.ehcache.config.Configuration;
import net.sf.ehcache.config.TerracottaClientConfiguration;
import net.sf.ehcache.event.CacheEventListener;
import net.sf.ehcache.management.event.ManagementEventSink;
import net.sf.ehcache.store.Store;
import net.sf.ehcache.store.TerracottaStore;
import net.sf.ehcache.terracotta.ClusteredInstanceFactory;
import net.sf.ehcache.transaction.SoftLockManager;
import net.sf.ehcache.transaction.TransactionIDFactory;
import net.sf.ehcache.util.ProductInfo;
import net.sf.ehcache.writer.writebehind.WriteBehind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terracotta.modules.ehcache.ToolkitInstanceFactory;
import org.terracotta.modules.ehcache.ToolkitInstanceFactoryImpl;
import org.terracotta.modules.ehcache.async.AsyncConfig;
import org.terracotta.modules.ehcache.async.AsyncCoordinator;
import org.terracotta.modules.ehcache.async.AsyncCoordinatorFactory;
import org.terracotta.modules.ehcache.async.AsyncCoordinatorFactoryImpl;
import org.terracotta.modules.ehcache.event.ClusteredEventReplicatorFactory;
import org.terracotta.modules.ehcache.event.FireRejoinOperatorEventClusterListener;
import org.terracotta.modules.ehcache.event.TerracottaTopologyImpl;
import org.terracotta.modules.ehcache.management.ClusteredManagementEventSink;
import org.terracotta.modules.ehcache.store.nonstop.NonStopStoreWrapper;
import org.terracotta.modules.ehcache.transaction.ClusteredTransactionIDFactory;
import org.terracotta.modules.ehcache.transaction.SoftLockManagerProvider;
import org.terracotta.modules.ehcache.writebehind.AsyncWriteBehind;
import org.terracotta.modules.ehcache.writebehind.WriteBehindAsyncConfig;
import org.terracotta.toolkit.Toolkit;
import org.terracotta.toolkit.ToolkitFeatureTypeInternal;
import org.terracotta.toolkit.internal.ToolkitInternal;
import org.terracotta.toolkit.internal.feature.ManagementInternalFeature;
import org.terracotta.toolkit.internal.feature.NonStopInternalFeature;
import com.terracotta.entity.ehcache.EhcacheEntitiesNaming;
import java.util.concurrent.Callable;
public class TerracottaClusteredInstanceFactory implements ClusteredInstanceFactory {
public static final Logger LOGGER = LoggerFactory
.getLogger(TerracottaClusteredInstanceFactory.class);
public static final String DEFAULT_CACHE_MANAGER_NAME = "__DEFAULT__";
protected final ToolkitInstanceFactory toolkitInstanceFactory;
// private final fields
protected final CacheCluster topology;
private final ClusteredEventReplicatorFactory clusteredEventReplicatorFactory;
private final SoftLockManagerProvider softLockManagerProvider;
private final AsyncCoordinatorFactory asyncCoordinatorFactory;
private final TerracottaStoreInitializationService initializationService;
public TerracottaClusteredInstanceFactory(TerracottaClientConfiguration terracottaClientConfiguration,
ClassLoader loader) {
toolkitInstanceFactory = createToolkitInstanceFactory(terracottaClientConfiguration, loader);
initializationService = new TerracottaStoreInitializationService(toolkitInstanceFactory.getToolkit().getClusterInfo());
topology = createTopology(toolkitInstanceFactory);
clusteredEventReplicatorFactory = new ClusteredEventReplicatorFactory(toolkitInstanceFactory);
softLockManagerProvider = new SoftLockManagerProvider(toolkitInstanceFactory);
asyncCoordinatorFactory = createAsyncCoordinatorFactory();
logEhcacheBuildInfo();
}
private static CacheCluster createTopology(ToolkitInstanceFactory factory) {
TerracottaTopologyImpl cacheCluster = new TerracottaTopologyImpl(factory.getToolkit().getClusterInfo());
try {
cacheCluster.addTopologyListener(new FireRejoinOperatorEventClusterListener(factory));
} catch (Exception e) {
LOGGER.warn("Unable to register: " + FireRejoinOperatorEventClusterListener.class.getName(), e);
}
return cacheCluster;
}
private void logEhcacheBuildInfo() {
final ProductInfo ehcacheCoreProductInfo = new ProductInfo();
// ToolkitLogger logger = ((ToolkitInternal) toolkitInstanceFactory.getToolkit())
// .getLogger(TerracottaClusteredInstanceFactory.class.getName());
LOGGER.info(ehcacheCoreProductInfo.toString());
}
protected ToolkitInstanceFactory createToolkitInstanceFactory(TerracottaClientConfiguration terracottaClientConfiguration,
ClassLoader loader) {
return new ToolkitInstanceFactoryImpl(terracottaClientConfiguration, loader);
}
protected AsyncCoordinatorFactory createAsyncCoordinatorFactory() {
return new AsyncCoordinatorFactoryImpl(toolkitInstanceFactory);
}
@Override
public final Store createStore(Ehcache cache) {
return new ClusteredSafeStore(newStore(cache));
}
protected ClusteredStore newStore(final Ehcache cache) {
return new ClusteredStore(toolkitInstanceFactory, cache, topology);
}
@Override
public final TerracottaStore createNonStopStore(Callable store,
Ehcache cache) {
return new NonStopStoreWrapper(store, toolkitInstanceFactory, cache, initializationService);
}
@Override
public CacheCluster getTopology() {
return topology;
}
@Override
public WriteBehind createWriteBehind(Ehcache cache) {
final CacheWriterConfiguration config = cache.getCacheConfiguration().getCacheWriterConfiguration();
final AsyncConfig asyncConfig = new WriteBehindAsyncConfig(config.getMinWriteDelay() * 1000,
config.getMaxWriteDelay() * 1000,
config.getWriteBatching(), config.getWriteBatchSize(),
cache.getCacheConfiguration()
.getTerracottaConfiguration().isSynchronousWrites(),
config.getRetryAttempts(),
config.getRetryAttemptDelaySeconds() * 1000,
config.getRateLimitPerSecond(),
config.getWriteBehindMaxQueueSize());
final AsyncCoordinator asyncCoordinator = asyncCoordinatorFactory.getOrCreateAsyncCoordinator(cache, asyncConfig);
return new AsyncWriteBehind(asyncCoordinator, config.getWriteBehindConcurrency());
}
@Override
public synchronized CacheEventListener createEventReplicator(Ehcache cache) {
return clusteredEventReplicatorFactory.getOrCreateClusteredEventReplicator(cache);
}
/**
* This is used by SampledMBeanRegistrationProvider to generate a JMX MBean ObjectName containing the client's uuid so
* that it can be associated with the correct connection when tunneled to the L2.
*/
@Override
public String getUUID() {
return ((ToolkitInternal) toolkitInstanceFactory.getToolkit()).getClientUUID();
}
@Override
public void enableNonStopForCurrentThread(boolean enable) {
NonStopInternalFeature nonStopInternalFeature = ((ToolkitInternal)toolkitInstanceFactory.getToolkit()).getFeature(ToolkitFeatureTypeInternal.NONSTOP);
if (nonStopInternalFeature != null) {
nonStopInternalFeature.enableForCurrentThread(enable);
}
}
@Override
public void shutdown() {
toolkitInstanceFactory.shutdown();
initializationService.shutdown();
}
@Override
public TransactionIDFactory createTransactionIDFactory(String uuid, String cacheManagerName) {
return new ClusteredTransactionIDFactory(uuid, cacheManagerName, toolkitInstanceFactory, topology);
}
@Override
public SoftLockManager getOrCreateSoftLockManager(Ehcache cache) {
return softLockManagerProvider.getOrCreateClusteredSoftLockFactory(cache);
}
@Override
public boolean destroyCache(final String cacheManagerName, final String cacheName) {
boolean destroyed = toolkitInstanceFactory.destroy(cacheManagerName, cacheName);
destroyed |= asyncCoordinatorFactory.destroy(cacheManagerName, cacheName);
return destroyed;
}
@Override
public void linkClusteredCacheManager(String cacheManagerName, Configuration configuration) {
toolkitInstanceFactory.linkClusteredCacheManager(cacheManagerName, configuration);
}
@Override
public void unlinkCache(String cacheName) {
try {
toolkitInstanceFactory.unlinkCache(cacheName);
} catch (RuntimeException e) {
if(e.getClass().getSimpleName().equals("TCNotRunningException")) {
LOGGER.info("Terracotta client already shutdown", e);
} else {
throw e;
}
}
}
@Override
public ManagementEventSink createEventSink() {
Toolkit toolkit = toolkitInstanceFactory.getToolkit();
ToolkitInternal toolkitInternal = (ToolkitInternal)toolkit;
ManagementInternalFeature feature = toolkitInternal.getFeature(ToolkitFeatureTypeInternal.MANAGEMENT);
return new ClusteredManagementEventSink(feature);
}
public static String getToolkitMapNameForCache(String cacheManagerName, String cacheName) {
return EhcacheEntitiesNaming.getToolkitCacheNameFor(cacheManagerName, cacheName);
}
@Override
public void waitForOrchestrator(String cacheManagerName) {
toolkitInstanceFactory.waitForOrchestrator(cacheManagerName);
}
}