package org.infinispan.registry.impl;
import java.lang.invoke.MethodHandles;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.infinispan.Cache;
import org.infinispan.commons.util.CollectionFactory;
import org.infinispan.commons.util.concurrent.ConcurrentHashSet;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Stop;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.registry.InternalCacheRegistry;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* InternalCacheRegistryImpl.
*
* @author Tristan Tarrant
* @since 7.2
*/
public class InternalCacheRegistryImpl implements InternalCacheRegistry {
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private EmbeddedCacheManager cacheManager;
private final ConcurrentMap<String, EnumSet<Flag>> internalCaches = CollectionFactory.makeBoundedConcurrentMap(10);
private final Set<String> privateCaches = new ConcurrentHashSet<>();
@Inject
public void init(EmbeddedCacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Stop(priority = 1)
public void stop() {
internalCaches.keySet().forEach(cacheName -> {
Cache<Object, Object> cache = cacheManager.getCache(cacheName, false);
if (cache != null)
cache.stop();
});
}
@Override
public void registerInternalCache(String name, Configuration configuration) {
registerInternalCache(name, configuration, EnumSet.noneOf(Flag.class));
}
// Synchronized to prevent users from registering the same configuration at the same time
@Override
public synchronized void registerInternalCache(String name, Configuration configuration, EnumSet<Flag> flags) {
boolean configPresent = cacheManager.getCacheConfiguration(name) != null;
// check if it already has been defined. Currently we don't support existing user-defined configuration.
if ((flags.contains(Flag.EXCLUSIVE) || !internalCaches.containsKey(name)) && configPresent) {
throw log.existingConfigForInternalCache(name);
}
// Don't redefine
if (configPresent) {
return;
}
ConfigurationBuilder builder = new ConfigurationBuilder().read(configuration);
builder.jmxStatistics().disable(); // Internal caches must not be included in stats counts
GlobalConfiguration globalConfiguration = cacheManager.getCacheManagerConfiguration();
if (flags.contains(Flag.PERSISTENT) && globalConfiguration.globalState().enabled()) {
builder.persistence().addSingleFileStore().location(globalConfiguration.globalState().persistentLocation()).purgeOnStartup(false).preload(true).fetchPersistentState(true);
}
SecurityActions.defineConfiguration(cacheManager, name, builder.build());
internalCaches.put(name, flags);
if (!flags.contains(Flag.USER)) {
privateCaches.add(name);
}
}
@Override
public synchronized void unregisterInternalCache(String name) {
if (isInternalCache(name)) {
Cache<Object, Object> cache = cacheManager.getCache(name, false);
if (cache != null)
cache.stop();
internalCaches.remove(name);
privateCaches.remove(name);
SecurityActions.undefineConfiguration(cacheManager, name);
}
}
@Override
public boolean isInternalCache(String name) {
return internalCaches.containsKey(name);
}
@Override
public boolean isPrivateCache(String name) {
return privateCaches.contains(name);
}
@Override
public Set<String> getInternalCacheNames() {
return internalCaches.keySet();
}
@Override
public void filterPrivateCaches(Set<String> names) {
names.removeAll(privateCaches);
}
@Override
public boolean internalCacheHasFlag(String name, Flag flag) {
EnumSet<Flag> flags = internalCaches.get(name);
return flags != null && flags.contains(flag);
}
}