package org.infinispan.query.backend; import static org.infinispan.test.fwk.TestCacheManagerFactory.createClusteredCacheManager; import static org.testng.Assert.assertTrue; import static org.testng.AssertJUnit.assertEquals; import java.util.List; import java.util.function.Function; import java.util.stream.IntStream; import org.apache.lucene.search.MatchAllDocsQuery; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.cache.Index; import org.infinispan.lifecycle.ComponentStatus; import org.infinispan.manager.CacheContainer; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.query.CacheQuery; import org.infinispan.query.Search; import org.infinispan.query.test.AnotherGrassEater; import org.infinispan.query.test.Person; import org.infinispan.test.AbstractInfinispanTest; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.transaction.TransactionMode; import org.infinispan.util.CyclicDependencyException; import org.infinispan.util.DependencyGraph; import org.testng.annotations.Test; /** * Tests for cache stop order when storing indexes on infinispan * * @author gustavonalle * @since 7.0 */ @Test(groups = "functional", testName = "query.backend.IndexCacheStopTest") public class IndexCacheStopTest extends AbstractInfinispanTest { private static final int CACHE_SIZE = 10; @Test public void testIndexingOnDefaultCache() { EmbeddedCacheManager cacheManager = createClusteredCacheManager(getIndexedConfig()); startAndIndexData(null, cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingOnNamedCache() { EmbeddedCacheManager cacheManager = createClusteredCacheManager(getIndexedConfig()); cacheManager.defineConfiguration("custom", cacheManager.getDefaultCacheConfiguration()); startAndIndexData("custom", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingOnMultipleCaches() { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); cacheManager.defineConfiguration("cache1", getIndexedConfig().build()); cacheManager.defineConfiguration("cache2", getIndexedConfigWithCustomCaches("lockCache", "metadataCache", "dataCache").build()); startAndIndexData("cache1", cacheManager); startAndIndexData("cache2", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingWithInfinispanIndexManager() { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); cacheManager.defineConfiguration("cache", getIndexedConfigWithInfinispanIndexManager().build()); startAndIndexData("cache", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingWithCustomLock() throws CyclicDependencyException { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); DependencyGraph<String> graph = TestingUtil.extractField(cacheManager, "cacheDependencyGraph"); cacheManager.defineConfiguration("cache", getIndexedConfigWithCustomLock().build()); startAndIndexData("cache", cacheManager); cacheManager.stop(); List<String> cacheOrder = graph.topologicalSort(); assertTrue(cacheOrder.indexOf("cache") < cacheOrder.indexOf("LuceneIndexesData")); assertTrue(cacheOrder.indexOf("cache") < cacheOrder.indexOf("LuceneIndexesMetadata")); assertTrue(cacheOrder.indexOf("cache") < cacheOrder.indexOf("LuceneIndexesLocking")); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingOnCacheItself() throws CyclicDependencyException { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); cacheManager.defineConfiguration("single", getIndexedConfigWithCustomCaches("single", "single", "single").build()); startAndIndexData("single", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingMultipleDirectoriesOnSameCache() throws CyclicDependencyException { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); cacheManager.defineConfiguration("cacheA", getIndexedConfigWithCustomCaches("single", "single", "single").build()); cacheManager.defineConfiguration("cacheB", getIndexedConfigWithCustomCaches("single", "single", "single").build()); startAndIndexData("cacheA", cacheManager); startAndIndexOtherEntityData("cacheB", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testIndexingHierarchically() throws CyclicDependencyException { EmbeddedCacheManager cacheManager = createClusteredCacheManager(); cacheManager.defineConfiguration("cacheC", getIndexedConfigWithCustomCaches("cacheB", "cacheB", "cacheB").build()); cacheManager.defineConfiguration("cacheB", getIndexedConfigWithCustomCaches("cacheA", "cacheA", "cacheA").build()); cacheManager.defineConfiguration("cacheA", getIndexedConfig().build()); startAndIndexData("cacheA", cacheManager); startAndIndexData("cacheB", cacheManager); startAndIndexData("cacheC", cacheManager); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } @Test public void testStartAndStopWithEmptyCache() throws CyclicDependencyException { EmbeddedCacheManager cacheManager = createClusteredCacheManager(getIndexedConfig()); cacheManager.getCache(); cacheManager.stop(); assertEquals(cacheManager.getStatus(), ComponentStatus.TERMINATED); } private void startAndIndexData(String cacheName, CacheContainer cacheContainer) { startAndIndexEntityData(cacheName, cacheContainer, i -> new Person("name" + i, "blurb" + i, i), Person.class); } private void startAndIndexOtherEntityData(String cacheName, CacheContainer cacheContainer) { startAndIndexEntityData(cacheName, cacheContainer, i -> new AnotherGrassEater("name" + i, "blurb" + i), AnotherGrassEater.class); } private <T> void startAndIndexEntityData(String cacheName, CacheContainer cacheContainer, Function<Integer, T> provider, Class<T> type) { Cache<Integer, T> cache; if (cacheName == null) { cache = cacheContainer.getCache(); } else { cache = cacheContainer.getCache(cacheName); } populateData(cache, provider); assertIndexPopulated(cache, type); } private <T> void assertIndexPopulated(Cache<Integer, T> cache, Class<T> clazz) { CacheQuery<T> query = Search.getSearchManager(cache).getQuery(new MatchAllDocsQuery(), clazz); assertEquals(query.list().size(), CACHE_SIZE); } private <T> void populateData(Cache<Integer, T> cache, Function<Integer, T> provider) { IntStream.range(0, CACHE_SIZE).forEach(i -> cache.put(i, provider.apply(i))); } private ConfigurationBuilder getBaseConfig() { ConfigurationBuilder cfg = TestCacheManagerFactory.getDefaultCacheConfiguration(true); cfg.clustering().cacheMode(CacheMode.DIST_SYNC) .transaction().transactionMode(TransactionMode.TRANSACTIONAL).recovery().disable() .locking() .lockAcquisitionTimeout(10000); return cfg; } private ConfigurationBuilder getIndexedConfig() { ConfigurationBuilder cfg = getBaseConfig(); cfg.indexing().index(Index.ALL) .addIndexedEntity(Person.class) .addIndexedEntity(AnotherGrassEater.class) .addProperty("default.directory_provider", "infinispan") .addProperty("lucene_version", "LUCENE_CURRENT"); return cfg; } private ConfigurationBuilder getIndexedConfigWithCustomCaches(String lockCache, String metadataCache, String dataCache) { ConfigurationBuilder cfg = getIndexedConfig(); cfg.indexing().index(Index.ALL) .addProperty("default.locking_cachename", lockCache) .addProperty("default.data_cachename", dataCache) .addProperty("default.metadata_cachename", metadataCache) .addProperty("lucene_version", "LUCENE_CURRENT"); return cfg; } private ConfigurationBuilder getIndexedConfigWithInfinispanIndexManager() { ConfigurationBuilder cfg = getIndexedConfig(); cfg.indexing().index(Index.ALL) .addProperty("default.indexmanager", "org.infinispan.query.indexmanager.InfinispanIndexManager") .addProperty("lucene_version", "LUCENE_CURRENT"); return cfg; } private ConfigurationBuilder getIndexedConfigWithCustomLock() { ConfigurationBuilder cfg = getIndexedConfig(); cfg.indexing().index(Index.ALL) .addProperty("default.locking_strategy", "none") .addProperty("lucene_version", "LUCENE_CURRENT"); return cfg; } }