package org.infinispan.manager; import static org.infinispan.test.Exceptions.expectException; import static org.infinispan.test.TestingUtil.k; import static org.infinispan.test.TestingUtil.killCacheManagers; import static org.infinispan.test.TestingUtil.v; import static org.infinispan.test.TestingUtil.withCacheManager; import static org.infinispan.test.TestingUtil.withCacheManagers; import static org.infinispan.test.fwk.TestCacheManagerFactory.createCacheManager; import static org.infinispan.test.fwk.TestCacheManagerFactory.createClusteredCacheManager; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import java.lang.reflect.Method; import java.util.Set; import java.util.UUID; import org.infinispan.Cache; import org.infinispan.IllegalLifecycleStateException; import org.infinispan.commons.CacheConfigurationException; import org.infinispan.commons.CacheException; import org.infinispan.commons.configuration.BuiltBy; import org.infinispan.commons.configuration.ConfigurationFor; import org.infinispan.commons.configuration.attributes.AttributeSet; import org.infinispan.configuration.cache.AbstractStoreConfiguration; import org.infinispan.configuration.cache.AbstractStoreConfigurationBuilder; import org.infinispan.configuration.cache.AsyncStoreConfiguration; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.cache.InterceptorConfiguration; import org.infinispan.configuration.cache.PersistenceConfigurationBuilder; import org.infinispan.configuration.cache.SingletonStoreConfiguration; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.container.DataContainer; import org.infinispan.eviction.EvictionStrategy; import org.infinispan.interceptors.base.BaseCustomInterceptor; import org.infinispan.lifecycle.ComponentStatus; import org.infinispan.marshall.core.MarshalledEntry; import org.infinispan.persistence.dummy.DummyInMemoryStore; import org.infinispan.persistence.dummy.DummyInMemoryStoreConfigurationBuilder; import org.infinispan.persistence.spi.ExternalStore; import org.infinispan.persistence.spi.InitializationContext; import org.infinispan.test.AbstractInfinispanTest; import org.infinispan.test.CacheManagerCallable; import org.infinispan.test.MultiCacheManagerCallable; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.testng.annotations.Test; /** * @author Manik Surtani * @since 4.0 */ @Test(groups = {"functional", "smoke"}, testName = "manager.CacheManagerTest") public class CacheManagerTest extends AbstractInfinispanTest { public void testDefaultCache() { EmbeddedCacheManager cm = createCacheManager(false); try { assertEquals(ComponentStatus.RUNNING, cm.getCache().getStatus()); assertTrue(cm.getCache().getName().equals(CacheContainer.DEFAULT_CACHE_NAME)); expectException(IllegalArgumentException.class, () -> cm.defineConfiguration(CacheContainer.DEFAULT_CACHE_NAME, new ConfigurationBuilder().build())); } finally { TestingUtil.killCacheManagers(cm); } } public void testUnstartedCachemanager() { withCacheManager(new CacheManagerCallable(createCacheManager(false)){ @Override public void call() { assertTrue(cm.getStatus().equals(ComponentStatus.INSTANTIATED)); assertFalse(cm.getStatus().allowInvocations()); Cache<Object, Object> cache = cm.getCache(); cache.put("k","v"); assertTrue(cache.get("k").equals("v")); } }); } @Test(expectedExceptions = CacheConfigurationException.class) public void testClashingNames() { EmbeddedCacheManager cm = createCacheManager(false); try { ConfigurationBuilder c = new ConfigurationBuilder(); cm.defineConfiguration("aCache", c.build()); cm.defineConfiguration("aCache", c.build()); } finally { TestingUtil.killCacheManagers(cm); } } public void testStartAndStop() { EmbeddedCacheManager cm = createCacheManager(false); try { cm.defineConfiguration("cache1", new ConfigurationBuilder().build()); cm.defineConfiguration("cache2", new ConfigurationBuilder().build()); cm.defineConfiguration("cache3", new ConfigurationBuilder().build()); Cache<?, ?> c1 = cm.getCache("cache1"); Cache<?, ?> c2 = cm.getCache("cache2"); Cache<?, ?> c3 = cm.getCache("cache3"); assertEquals(ComponentStatus.RUNNING, c1.getStatus()); assertEquals(ComponentStatus.RUNNING, c2.getStatus()); assertEquals(ComponentStatus.RUNNING, c3.getStatus()); cm.stop(); assertEquals(ComponentStatus.TERMINATED, c1.getStatus()); assertEquals(ComponentStatus.TERMINATED, c2.getStatus()); assertEquals(ComponentStatus.TERMINATED, c3.getStatus()); } finally { TestingUtil.killCacheManagers(cm); } } public void testDefiningConfigurationValidation() { EmbeddedCacheManager cm = createCacheManager(false); expectException(NullPointerException.class, () -> cm.defineConfiguration("cache1", null)); expectException(NullPointerException.class, () -> cm.defineConfiguration(null, null)); expectException(NullPointerException.class, () -> cm.defineConfiguration(null, new ConfigurationBuilder().build())); } public void testDefiningConfigurationOverridingBooleans() { EmbeddedCacheManager cm = createCacheManager(false); ConfigurationBuilder c = new ConfigurationBuilder(); c.storeAsBinary().enable(); Configuration lazy = cm.defineConfiguration("storeAsBinary", c.build()); assertTrue(lazy.storeAsBinary().enabled()); c = new ConfigurationBuilder().read(lazy); c.eviction().strategy(EvictionStrategy.LRU).maxEntries(1); Configuration lazyLru = cm.defineConfiguration("lazyDeserializationWithLRU", c.build()); assertTrue(lazy.storeAsBinary().enabled()); assertEquals(EvictionStrategy.LRU, lazyLru.eviction().strategy()); } public void testDefineConfigurationTwice() { EmbeddedCacheManager cm = createCacheManager(false); try { Configuration override = new ConfigurationBuilder().invocationBatching().enable().build(); assertTrue(override.invocationBatching().enabled()); assertTrue(cm.defineConfiguration("test1", override).invocationBatching().enabled()); ConfigurationBuilder cb = new ConfigurationBuilder(); cb.read(override); Configuration config = cb.build(); assertTrue(config.invocationBatching().enabled()); assertTrue(cm.defineConfiguration("test2", config).invocationBatching().enabled()); } finally { cm.stop(); } } @Test(expectedExceptions = CacheConfigurationException.class, expectedExceptionsMessageRegExp = "ISPN000436:.*") public void testMissingDefaultConfiguration() { GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder(); gcb.globalJmxStatistics().jmxDomain("infinispan-" + UUID.randomUUID()); EmbeddedCacheManager cm = new DefaultCacheManager(gcb.build()); try { cm.getCache("someCache"); } finally { cm.stop(); } } public void testGetCacheNames() { EmbeddedCacheManager cm = createCacheManager(false); try { cm.defineConfiguration("one", new ConfigurationBuilder().build()); cm.defineConfiguration("two", new ConfigurationBuilder().build()); cm.defineConfiguration("three", new ConfigurationBuilder().build()); cm.getCache("three"); Set<String> cacheNames = cm.getCacheNames(); assertEquals(3, cacheNames.size()); assertTrue(cacheNames.contains("one")); assertTrue(cacheNames.contains("two")); assertTrue(cacheNames.contains("three")); } finally { cm.stop(); } } public void testCacheStopTwice() { EmbeddedCacheManager localCacheManager = createCacheManager(false); try { Cache<String, String> cache = localCacheManager.getCache(); cache.put("k", "v"); cache.stop(); cache.stop(); } finally { TestingUtil.killCacheManagers(localCacheManager); } } public void testCacheManagerStopTwice() { EmbeddedCacheManager localCacheManager = createCacheManager(false); try { Cache<String, String> cache = localCacheManager.getCache(); cache.put("k", "v"); localCacheManager.stop(); localCacheManager.stop(); } finally { TestingUtil.killCacheManagers(localCacheManager); } } @Test(expectedExceptions = IllegalLifecycleStateException.class) public void testCacheStopManagerStopFollowedByGetCache() { EmbeddedCacheManager localCacheManager = createCacheManager(false); try { Cache<String, String> cache = localCacheManager.getCache(); cache.put("k", "v"); cache.stop(); localCacheManager.stop(); localCacheManager.getCache(); } finally { TestingUtil.killCacheManagers(localCacheManager); } } @Test(expectedExceptions = IllegalLifecycleStateException.class) public void testCacheStopManagerStopFollowedByCacheOp() { EmbeddedCacheManager localCacheManager = createCacheManager(false); try { Cache<String, String> cache = localCacheManager.getCache(); cache.put("k", "v"); cache.stop(); localCacheManager.stop(); cache.put("k", "v2"); } finally { TestingUtil.killCacheManagers(localCacheManager); } } public void testRemoveNonExistentCache(Method m) { EmbeddedCacheManager manager = getManagerWithStore(m, false, false); try { manager.getCache("cache"); // An attempt to remove a non-existing cache should be a no-op manager.removeCache("does-not-exist"); } finally { manager.stop(); } } public void testRemoveCacheLocal(Method m) { EmbeddedCacheManager manager = getManagerWithStore(m, false, false); try { Cache<String, String> cache = manager.getCache("cache"); cache.put(k(m, 1), v(m, 1)); cache.put(k(m, 2), v(m, 2)); cache.put(k(m, 3), v(m, 3)); DummyInMemoryStore store = getDummyStore(cache); DataContainer data = getDataContainer(cache); assertFalse(store.isEmpty()); assertTrue(0 != data.size()); manager.removeCache("cache"); assertEquals(0, DummyInMemoryStore.getStoreDataSize(store.getStoreName())); assertEquals(0, data.size()); // Try removing the cache again, it should be a no-op manager.removeCache("cache"); assertEquals(0, DummyInMemoryStore.getStoreDataSize(store.getStoreName())); assertEquals(0, data.size()); } finally { manager.stop(); } } @Test(expectedExceptions = CacheException.class) public void testStartCachesFailed() { EmbeddedCacheManager cacheManager = null; try { cacheManager = createCacheManager(); cacheManager.defineConfiguration("correct-cache-1", cacheManager.getDefaultCacheConfiguration()); cacheManager.defineConfiguration("correct-cache-2", cacheManager.getDefaultCacheConfiguration()); cacheManager.defineConfiguration("correct-cache-3", cacheManager.getDefaultCacheConfiguration()); ConfigurationBuilder incorrectBuilder = new ConfigurationBuilder(); incorrectBuilder.customInterceptors().addInterceptor().position(InterceptorConfiguration.Position.FIRST) .interceptor(new BaseCustomInterceptor() { @Override protected void start() { throw new IllegalStateException(); } }); cacheManager.defineConfiguration("incorrect", incorrectBuilder.build()); cacheManager.startCaches("correct-cache-1", "correct-cache-2", "correct-cache-3", "incorrect"); } finally { if (cacheManager != null) { killCacheManagers(cacheManager); } } } public void testCacheManagerRestartReusingConfigurations() { withCacheManagers(new MultiCacheManagerCallable( TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false), TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) { @Override public void call() { EmbeddedCacheManager cm1 = cms[0]; EmbeddedCacheManager cm2 = cms[1]; Cache<Object, Object> c1 = cm1.getCache(); cm2.getCache(); GlobalConfiguration globalCfg = cm1.getCacheManagerConfiguration(); Configuration cfg = c1.getCacheConfiguration(); cm1.stop(); withCacheManager(new CacheManagerCallable( new DefaultCacheManager(globalCfg, cfg)) { @Override public void call() { Cache<Object, Object> c = cm.getCache(); c.put(1, "v1"); assertEquals("v1", c.get(1)); } }); } }); } public void testRemoveCacheClusteredLocalStores(Method m) throws Exception { doTestRemoveCacheClustered(m, false); } public void testRemoveCacheClusteredSharedStores(Method m) throws Exception { doTestRemoveCacheClustered(m, true); } public void testExceptionOnCacheManagerStop() { ConfigurationBuilder c = new ConfigurationBuilder(); c.persistence().addStore(UnreliableCacheStoreConfigurationBuilder.class); EmbeddedCacheManager cm = TestCacheManagerFactory.createCacheManager(c); try { assertEquals(ComponentStatus.RUNNING, cm.getStatus()); Cache<Integer, String> cache = cm.getCache(); cache.put(1, "v1"); } finally { killCacheManagers(cm); assertEquals(ComponentStatus.TERMINATED, cm.getStatus()); } } public void testGetCacheWithTemplateAlreadyDefinedConfiguration() { withCacheManager(new CacheManagerCallable(createClusteredCacheManager()) { @Override public void call() { ConfigurationBuilder builder = new ConfigurationBuilder(); CacheMode cacheMode = CacheMode.DIST_ASYNC; // DIST_ASYNC isn't default so it should stay applied builder.clustering().cacheMode(cacheMode); String distCacheName = "dist-cache"; cm.defineConfiguration(distCacheName, builder.build()); String templateName = "template"; cm.defineConfiguration(templateName, new ConfigurationBuilder().template(true).build()); Cache cache = cm.getCache(distCacheName, templateName); assertEquals(cacheMode, cache.getCacheConfiguration().clustering().cacheMode()); } }); } public void testDefineConfigurationWithOverrideAndTemplate() { withCacheManager(new CacheManagerCallable(createClusteredCacheManager()) { @Override public void call() { // DIST_ASYNC isn't default so it should stay applied CacheMode cacheMode = CacheMode.DIST_ASYNC; String templateName = "dist-cache-template"; cm.defineConfiguration(templateName, new ConfigurationBuilder().clustering().cacheMode(cacheMode).template(true).build()); CacheMode overrideCacheMode = CacheMode.REPL_ASYNC; Configuration overrideConfiguration = new ConfigurationBuilder().clustering().cacheMode(overrideCacheMode).build(); String ourCacheName = "my-cache"; cm.defineConfiguration(ourCacheName, templateName, overrideConfiguration); Cache cache = cm.getCache(ourCacheName); // We expect the override to take precedence assertEquals(overrideCacheMode, cache.getCacheConfiguration().clustering().cacheMode()); } }); } private EmbeddedCacheManager getManagerWithStore(Method m, boolean isClustered, boolean isStoreShared) { return getManagerWithStore(m, isClustered, isStoreShared, "store-"); } private EmbeddedCacheManager getManagerWithStore(Method m, boolean isClustered, boolean isStoreShared, String storePrefix) { String storeName = storePrefix + m.getName(); ConfigurationBuilder c = new ConfigurationBuilder(); c .persistence() .addStore(DummyInMemoryStoreConfigurationBuilder.class).storeName(storeName).shared(isStoreShared) .clustering() .cacheMode(isClustered ? CacheMode.REPL_SYNC : CacheMode.LOCAL); GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder().clusteredDefault(); gcb.globalJmxStatistics().allowDuplicateDomains(true); EmbeddedCacheManager cm = TestCacheManagerFactory.createClusteredCacheManager(gcb, c); cm.defineConfiguration("cache", c.build()); return cm; } private void doTestRemoveCacheClustered(final Method m, final boolean isStoreShared) { withCacheManagers(new MultiCacheManagerCallable( getManagerWithStore(m, true, isStoreShared, "store1-"), getManagerWithStore(m, true, isStoreShared, "store2-")) { @Override public void call() { EmbeddedCacheManager manager1 = cms[0]; EmbeddedCacheManager manager2 = cms[0]; Cache<String, String> cache1 = manager1.getCache("cache", true); Cache<String, String> cache2 = manager2.getCache("cache", true); assertTrue(cache1 != null); assertTrue(cache2 != null); assertTrue(manager1.cacheExists("cache")); assertTrue(manager2.cacheExists("cache")); cache1.put(k(m, 1), v(m, 1)); cache1.put(k(m, 2), v(m, 2)); cache1.put(k(m, 3), v(m, 3)); cache2.put(k(m, 4), v(m, 4)); cache2.put(k(m, 5), v(m, 5)); DummyInMemoryStore store1 = getDummyStore(cache1); DataContainer data1 = getDataContainer(cache1); DummyInMemoryStore store2 = getDummyStore(cache2); DataContainer data2 = getDataContainer(cache2); assertFalse(store1.isEmpty()); assertEquals(5, data1.size()); assertFalse(store2.isEmpty()); assertEquals(5, data2.size()); manager1.removeCache("cache"); assertFalse(manager1.cacheExists("cache")); assertFalse(manager2.cacheExists("cache")); assertNull(manager1.getCache("cache", false)); assertNull(manager2.getCache("cache", false)); assertEquals(0, DummyInMemoryStore.getStoreDataSize(store1.getStoreName())); assertEquals(0, data1.size()); assertEquals(0, DummyInMemoryStore.getStoreDataSize(store2.getStoreName())); assertEquals(0, data2.size()); } }); } private DummyInMemoryStore getDummyStore(Cache<String, String> cache1) { return (DummyInMemoryStore) TestingUtil.getFirstLoader(cache1); } private DataContainer getDataContainer(Cache<String, String> cache) { return TestingUtil.extractComponent(cache, DataContainer.class); } public static class UnreliableCacheStore implements ExternalStore { @Override public void init(InitializationContext ctx) {} @Override public void write(MarshalledEntry entry) {} @Override public boolean delete(Object key) { return false; } @Override public MarshalledEntry load(Object key) { return null; } @Override public boolean contains(Object key) { return false; } @Override public void start() {} @Override public void stop() { throw new IllegalStateException("Test"); } } @ConfigurationFor(UnreliableCacheStore.class) @BuiltBy(UnreliableCacheStoreConfigurationBuilder.class) public static class UnreliableCacheStoreConfiguration extends AbstractStoreConfiguration { public UnreliableCacheStoreConfiguration(AttributeSet attributes, AsyncStoreConfiguration async, SingletonStoreConfiguration singletonStore) { super(attributes, async, singletonStore); } } public static class UnreliableCacheStoreConfigurationBuilder extends AbstractStoreConfigurationBuilder<UnreliableCacheStoreConfiguration, UnreliableCacheStoreConfigurationBuilder> { public UnreliableCacheStoreConfigurationBuilder(PersistenceConfigurationBuilder builder) { super(builder, UnreliableCacheStoreConfiguration.attributeDefinitionSet()); } @Override public UnreliableCacheStoreConfiguration create() { return new UnreliableCacheStoreConfiguration(attributes.protect(), async.create(), singleton().create()); } @Override public UnreliableCacheStoreConfigurationBuilder self() { return this; } } }