package org.ehcache.management.registry;
import org.ehcache.Cache;
import org.ehcache.Status;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.core.events.CacheManagerListener;
import org.ehcache.core.spi.service.CacheManagerProviderService;
import org.ehcache.core.spi.service.ExecutionService;
import org.ehcache.core.spi.service.StatisticsService;
import org.ehcache.core.spi.store.InternalCacheManager;
import org.ehcache.core.spi.time.TimeSourceService;
import org.ehcache.management.ManagementRegistryService;
import org.ehcache.management.ManagementRegistryServiceConfiguration;
import org.ehcache.management.cluster.Clustering;
import org.ehcache.management.cluster.ClusteringManagementService;
import org.ehcache.management.cluster.DefaultClusteringManagementServiceConfiguration;
import org.ehcache.management.providers.CacheBinding;
import org.ehcache.management.providers.EhcacheStatisticCollectorProvider;
import org.ehcache.management.providers.actions.EhcacheActionProvider;
import org.ehcache.management.providers.settings.EhcacheSettingsProvider;
import org.ehcache.management.providers.statistics.EhcacheStatisticsProvider;
import org.ehcache.spi.service.OptionalServiceDependencies;
import org.ehcache.spi.service.Service;
import org.ehcache.spi.service.ServiceDependencies;
import org.ehcache.spi.service.ServiceProvider;
import org.terracotta.management.model.context.ContextContainer;
import org.terracotta.management.registry.DefaultManagementRegistry;
import org.terracotta.statistics.StatisticsManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
@ServiceDependencies({CacheManagerProviderService.class, StatisticsService.class, TimeSourceService.class, ExecutionService.class})
@OptionalServiceDependencies({
"org.ehcache.clustered.client.service.EntityService",
"org.ehcache.clustered.client.service.ClusteringService"})
public class DefaultManagementRegistryService extends DefaultManagementRegistry implements ManagementRegistryService, CacheManagerListener {
private final ManagementRegistryServiceConfiguration configuration;
private volatile InternalCacheManager cacheManager;
private volatile ClusteringManagementService clusteringManagementService;
private volatile boolean clusteringManagementServiceAutoStarted;
public DefaultManagementRegistryService() {
this(new DefaultManagementRegistryConfiguration());
}
public DefaultManagementRegistryService(ManagementRegistryServiceConfiguration configuration) {
super(null);
this.configuration = configuration == null ? new DefaultManagementRegistryConfiguration() : configuration;
}
@Override
public void start(final ServiceProvider<Service> serviceProvider) {
this.cacheManager = serviceProvider.getService(CacheManagerProviderService.class).getCacheManager();
StatisticsService statisticsService = serviceProvider.getService(StatisticsService.class);
TimeSourceService timeSourceService = serviceProvider.getService(TimeSourceService.class);
addManagementProvider(new EhcacheActionProvider(getConfiguration()));
addManagementProvider(new EhcacheStatisticsProvider(getConfiguration(), statisticsService, timeSourceService.getTimeSource()));
addManagementProvider(new EhcacheStatisticCollectorProvider(getConfiguration()));
addManagementProvider(new EhcacheSettingsProvider(getConfiguration(), cacheManager));
this.cacheManager.registerListener(this);
this.clusteringManagementService = serviceProvider.getService(ClusteringManagementService.class);
if (this.clusteringManagementService == null && Clustering.isAvailable(serviceProvider)) {
this.clusteringManagementService = Clustering.newClusteringManagementService(new DefaultClusteringManagementServiceConfiguration());
this.clusteringManagementService.start(serviceProvider);
this.clusteringManagementServiceAutoStarted = true;
} else {
this.clusteringManagementServiceAutoStarted = false;
}
}
@Override
public void stop() {
if (this.clusteringManagementService != null && this.clusteringManagementServiceAutoStarted) {
this.clusteringManagementService.stop();
}
this.clusteringManagementService = null;
super.close();
}
@Override
public void cacheAdded(String alias, Cache<?, ?> cache) {
StatisticsManager.associate(cache).withParent(cacheManager);
register(new CacheBinding(alias, cache));
}
@Override
public void cacheRemoved(String alias, Cache<?, ?> cache) {
unregister(new CacheBinding(alias, cache));
StatisticsManager.dissociate(cache).fromParent(cacheManager);
}
@Override
public void stateTransition(Status from, Status to) {
switch (to) {
case AVAILABLE:
register(cacheManager);
for (Map.Entry<String, CacheConfiguration<?, ?>> entry : cacheManager.getRuntimeConfiguration().getCacheConfigurations().entrySet()) {
String alias = entry.getKey();
CacheConfiguration<?, ?> configuration = entry.getValue();
Cache<?, ?> cache = cacheManager.getCache(alias, configuration.getKeyType(), configuration.getValueType());
cacheAdded(alias, cache);
}
break;
case UNINITIALIZED:
this.cacheManager.deregisterListener(this);
break;
case MAINTENANCE:
break;
default:
throw new AssertionError("Unsupported state: " + to);
}
}
@Override
public ManagementRegistryServiceConfiguration getConfiguration() {
return configuration;
}
@Override
public ContextContainer getContextContainer() {
Collection<ContextContainer> cacheCtx = new ArrayList<>();
for (String cacheName : this.cacheManager.getRuntimeConfiguration().getCacheConfigurations().keySet()) {
cacheCtx.add(new ContextContainer("cacheName", cacheName));
}
return new ContextContainer("cacheManagerName", getConfiguration().getContext().get("cacheManagerName"), cacheCtx);
}
}