package org.jboss.as.clustering.infinispan.cs.factory; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.infinispan.configuration.cache.PersistenceConfigurationBuilder; import org.infinispan.configuration.cache.StoreConfiguration; import org.infinispan.configuration.cache.StoreConfigurationBuilder; import org.infinispan.persistence.factory.CacheStoreFactory; import org.jboss.as.clustering.infinispan.InfinispanLogger; import org.jboss.as.clustering.infinispan.cs.configuration.DeployedStoreConfiguration; /** * Cache Store factory designed for deployed instances. * * @author Sebastian Laskawiec * @since 7.2 */ public class DeployedCacheStoreFactory implements CacheStoreFactory { private static final int TIMEOUT_SECONDS = 60; private ConcurrentHashMap<String, CompletableFuture<DeployedCacheStoreMetadata>> deployedCacheStores = new ConcurrentHashMap<>(); @Override public <T> T createInstance(StoreConfiguration cfg) { if (cfg instanceof DeployedStoreConfiguration) { DeployedStoreConfiguration deployedConfiguration = (DeployedStoreConfiguration) cfg; DeployedCacheStoreMetadata deployedCacheStoreMetadata = null; try { InfinispanLogger.ROOT_LOGGER.debug(String.format("Waiting for deployment of Custom Cache Store (%s).", deployedConfiguration.getCustomStoreClassName())); deployedCacheStoreMetadata = getPromise(deployedConfiguration.getCustomStoreClassName()).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); return (T) deployedCacheStoreMetadata.getLoaderWriterRawInstance(); } catch (InterruptedException | ExecutionException e) { throw new IllegalStateException("An error occurred while processing the deployment", e); } catch (TimeoutException e) { InfinispanLogger.ROOT_LOGGER.loadingCustomCacheStoreTimeout(deployedConfiguration.getCustomStoreClassName()); } } return null; } @Override public StoreConfiguration processConfiguration(StoreConfiguration storeConfiguration) { if (storeConfiguration instanceof DeployedStoreConfiguration) { DeployedStoreConfiguration deployedConfiguration = (DeployedStoreConfiguration) storeConfiguration; PersistenceConfigurationBuilder replacedBuilder = deployedConfiguration.getPersistenceConfigurationBuilder(); try { DeployedCacheStoreMetadata deployedCacheStoreMetadata = getPromise(deployedConfiguration.getCustomStoreClassName()).get(TIMEOUT_SECONDS, TimeUnit.SECONDS); StoreConfigurationBuilder replacedStoreBuilder = replacedBuilder.addStore(deployedCacheStoreMetadata.getStoreBuilderClass()); replacedStoreBuilder.fetchPersistentState(deployedConfiguration.fetchPersistentState()); replacedStoreBuilder.ignoreModifications(deployedConfiguration.ignoreModifications()); replacedStoreBuilder.preload(deployedConfiguration.preload()); replacedStoreBuilder.purgeOnStartup(deployedConfiguration.purgeOnStartup()); replacedStoreBuilder.shared(deployedConfiguration.shared()); replacedStoreBuilder.withProperties(deployedConfiguration.properties()); return (StoreConfiguration) replacedStoreBuilder.create(); } catch (InterruptedException | ExecutionException e) { throw new IllegalStateException("An error occurred while processing the deployment", e); } catch (TimeoutException e) { InfinispanLogger.ROOT_LOGGER.loadingCustomCacheStoreTimeout(deployedConfiguration.getCustomStoreClassName()); } } return null; } public void addInstance(Object instance) { DeployedCacheStoreMetadata deployedCacheStoreMetadata = DeployedCacheStoreMetadata.fromDeployedStoreInstance(instance); getPromise(deployedCacheStoreMetadata.getDeployedCacheClassName()).complete(deployedCacheStoreMetadata); } public void removeInstance(Object instance) { deployedCacheStores.remove(instance.getClass().getName()); } private CompletableFuture<DeployedCacheStoreMetadata> getPromise(String key) { return deployedCacheStores.computeIfAbsent(key, mappedKey -> new CompletableFuture<>()); } }