This is an automated email from the ASF dual-hosted git repository. ladyvader pushed a commit to branch feature/GEODE-3930 in repository https://gitbox.apache.org/repos/asf/geode.git
commit 779c89a52cd0e0f210b3dcda6a1419776d0ed072 Author: Dan Smith <[email protected]> AuthorDate: Wed Nov 1 17:09:57 2017 -0700 GEODE-3930: Create lucene index on an existing region - This is currently just an internal method to create the index on an existing region. It does not actually index the existing data in the region. - Adding a parameter to LuceneIndexFactoryImpl.create to allow creation on an existing region. --- .../geode/internal/cache/AbstractRegion.java | 8 +- .../geode/internal/cache/InternalRegion.java | 3 + .../apache/geode/internal/cache/LocalRegion.java | 16 ++- .../geode/internal/cache/PartitionedRegion.java | 12 ++- .../internal/cache/AbstractRegionJUnitTest.java | 5 + .../lucene/internal/LuceneIndexFactoryImpl.java | 19 ++-- .../cache/lucene/internal/LuceneIndexImpl.java | 2 + .../lucene/internal/LuceneRegionListener.java | 23 +---- .../cache/lucene/internal/LuceneServiceImpl.java | 71 ++++++++++++-- .../lucene/internal/xml/LuceneIndexCreation.java | 9 +- .../cache/lucene/LuceneIndexCreationDUnitTest.java | 109 ++++++++++++++++++++- .../lucene/LuceneIndexCreationIntegrationTest.java | 39 ++++++++ .../internal/LuceneIndexFactoryImplJUnitTest.java | 4 +- .../internal/LuceneServiceImplJUnitTest.java | 5 +- 14 files changed, 269 insertions(+), 56 deletions(-) diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java index 542157e..3ffc7e1 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegion.java @@ -869,8 +869,14 @@ public abstract class AbstractRegion implements InternalRegion, AttributesMutato @Override public void addAsyncEventQueueId(String asyncEventQueueId) { + addAsyncEventQueueId(asyncEventQueueId, false); + } + + public void addAsyncEventQueueId(String asyncEventQueueId, boolean isInternal) { getAsyncEventQueueIds().add(asyncEventQueueId); - getVisibleAsyncEventQueueIds().add(asyncEventQueueId); + if (!isInternal) { + getVisibleAsyncEventQueueIds().add(asyncEventQueueId); + } setAllGatewaySenderIds(); } diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java index 1b7c1b0..9dcd82b 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/InternalRegion.java @@ -110,4 +110,7 @@ public interface InternalRegion<K, V> void invokeInvalidateCallbacks(final EnumListenerEvent eventType, final EntryEventImpl event, final boolean callDispatchListenerEvent); + + void addCacheServiceProfile(CacheServiceProfile profile); + } diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java index 16e4cef..bed336a 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java @@ -217,6 +217,7 @@ import org.apache.geode.internal.offheap.annotations.Released; import org.apache.geode.internal.offheap.annotations.Retained; import org.apache.geode.internal.offheap.annotations.Unretained; import org.apache.geode.internal.sequencelog.EntryLogger; +import org.apache.geode.internal.util.concurrent.CopyOnWriteHashMap; import org.apache.geode.internal.util.concurrent.FutureResult; import org.apache.geode.internal.util.concurrent.StoppableCountDownLatch; import org.apache.geode.internal.util.concurrent.StoppableReadWriteLock; @@ -542,7 +543,8 @@ public class LocalRegion extends AbstractRegion implements InternalRegion, Loade return this.stopper; } - Map<String, CacheServiceProfile> cacheServiceProfiles; + private final CopyOnWriteHashMap<String, CacheServiceProfile> cacheServiceProfiles = + new CopyOnWriteHashMap<>(); private static String calcFullPath(String regionName, LocalRegion parentRegion) { StringBuilder buf = null; @@ -635,9 +637,9 @@ public class LocalRegion extends AbstractRegion implements InternalRegion, Loade this.isUsedForParallelGatewaySenderQueue = internalRegionArgs.isUsedForParallelGatewaySenderQueue(); this.serialGatewaySender = internalRegionArgs.getSerialGatewaySender(); - this.cacheServiceProfiles = - internalRegionArgs.getCacheServiceProfiles() == null ? Collections.emptyMap() - : Collections.unmodifiableMap(internalRegionArgs.getCacheServiceProfiles()); + if (internalRegionArgs.getCacheServiceProfiles() != null) { + this.cacheServiceProfiles.putAll(internalRegionArgs.getCacheServiceProfiles()); + } if (!isUsedForMetaRegion && !isUsedForPartitionedRegionAdmin && !isUsedForPartitionedRegionBucket && !isUsedForSerialGatewaySenderQueue @@ -10400,7 +10402,11 @@ public class LocalRegion extends AbstractRegion implements InternalRegion, Loade } Map<String, CacheServiceProfile> getCacheServiceProfiles() { - return Collections.unmodifiableMap(this.cacheServiceProfiles); + return this.cacheServiceProfiles.getSnapshot(); + } + + public void addCacheServiceProfile(CacheServiceProfile profile) { + this.cacheServiceProfiles.put(profile.getId(), profile); } @Override diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java index 1dfd34f..6e0c0cd 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java @@ -1218,7 +1218,11 @@ public class PartitionedRegion extends LocalRegion } public void addAsyncEventQueueId(String asyncEventQueueId) { - super.addAsyncEventQueueId(asyncEventQueueId); + addAsyncEventQueueId(asyncEventQueueId, false); + } + + public void addAsyncEventQueueId(String asyncEventQueueId, boolean isInternal) { + super.addAsyncEventQueueId(asyncEventQueueId, isInternal); new UpdateAttributesProcessor(this).distribute(); ((PartitionedRegion) this).distributeUpdatedProfileOnSenderCreation(); GatewaySender sender = getCache() @@ -4966,10 +4970,8 @@ public class PartitionedRegion extends LocalRegion fillInProfile((PartitionProfile) profile); - if (cacheServiceProfiles != null) { - for (CacheServiceProfile csp : cacheServiceProfiles.values()) { - profile.addCacheServiceProfile(csp); - } + for (CacheServiceProfile csp : getCacheServiceProfiles().values()) { + profile.addCacheServiceProfile(csp); } profile.isOffHeap = getOffHeap(); diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionJUnitTest.java index da5c7b0..de50c2c 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionJUnitTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionJUnitTest.java @@ -657,5 +657,10 @@ public class AbstractRegionJUnitTest { public boolean supportsConcurrencyChecks() { throw new UnsupportedOperationException(); } + + @Override + public void addCacheServiceProfile(CacheServiceProfile profile) { + throw new UnsupportedOperationException(); + } } } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImpl.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImpl.java index 1e37d11..45d4fe1 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImpl.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImpl.java @@ -23,7 +23,7 @@ import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.geode.cache.lucene.LuceneIndexFactory; import org.apache.geode.cache.lucene.LuceneSerializer; -public class LuceneIndexFactoryImpl implements org.apache.geode.cache.lucene.LuceneIndexFactory { +public class LuceneIndexFactoryImpl implements LuceneIndexFactory { private final LuceneServiceImpl service; private final Map<String, Analyzer> fields = new LinkedHashMap<String, Analyzer>(); private LuceneSerializer serializer; @@ -34,12 +34,12 @@ public class LuceneIndexFactoryImpl implements org.apache.geode.cache.lucene.Luc } @Override - public LuceneIndexFactory addField(final String name) { + public LuceneIndexFactoryImpl addField(final String name) { return addField(name, new StandardAnalyzer()); } @Override - public LuceneIndexFactory setFields(final String... fields) { + public LuceneIndexFactoryImpl setFields(final String... fields) { this.fields.clear(); for (String field : fields) { addField(field); @@ -48,13 +48,13 @@ public class LuceneIndexFactoryImpl implements org.apache.geode.cache.lucene.Luc } @Override - public LuceneIndexFactory addField(final String name, final Analyzer analyzer) { + public LuceneIndexFactoryImpl addField(final String name, final Analyzer analyzer) { fields.put(name, analyzer); return this; } @Override - public LuceneIndexFactory setFields(final Map<String, Analyzer> fieldMap) { + public LuceneIndexFactoryImpl setFields(final Map<String, Analyzer> fieldMap) { this.fields.clear(); this.fields.putAll(fieldMap); return this; @@ -62,11 +62,16 @@ public class LuceneIndexFactoryImpl implements org.apache.geode.cache.lucene.Luc @Override public void create(final String indexName, final String regionPath) { - service.createIndex(indexName, regionPath, fields, serializer); + this.create(indexName, regionPath, false); + } + + public void create(final String indexName, final String regionPath, + boolean allowOnExistingRegion) { + service.createIndex(indexName, regionPath, fields, serializer, allowOnExistingRegion); } @Override - public LuceneIndexFactory setLuceneSerializer(LuceneSerializer luceneSerializer) { + public LuceneIndexFactoryImpl setLuceneSerializer(LuceneSerializer luceneSerializer) { this.serializer = luceneSerializer; return this; } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexImpl.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexImpl.java index 62c82df..fd4d060 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexImpl.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneIndexImpl.java @@ -24,6 +24,8 @@ import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.geode.InternalGemFireError; import org.apache.geode.cache.Cache; import org.apache.geode.cache.DataPolicy; +import org.apache.geode.cache.EvictionAlgorithm; +import org.apache.geode.cache.EvictionAttributes; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.asyncqueue.AsyncEventQueue; diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneRegionListener.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneRegionListener.java index df9dca0..bec0dd2 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneRegionListener.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneRegionListener.java @@ -20,8 +20,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.lucene.analysis.Analyzer; import org.apache.geode.cache.AttributesFactory; -import org.apache.geode.cache.EvictionAlgorithm; -import org.apache.geode.cache.EvictionAttributes; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl; @@ -83,21 +81,7 @@ public class LuceneRegionListener implements RegionListener { if (path.equals(this.regionPath) && this.beforeCreateInvoked.compareAndSet(false, true)) { - if (!attrs.getDataPolicy().withPartitioning()) { - // replicated region - throw new UnsupportedOperationException( - "Lucene indexes on replicated regions are not supported"); - } - - // For now we cannot support eviction with local destroy. - // Eviction with overflow to disk still needs to be supported - EvictionAttributes evictionAttributes = attrs.getEvictionAttributes(); - EvictionAlgorithm evictionAlgorithm = evictionAttributes.getAlgorithm(); - if (evictionAlgorithm != EvictionAlgorithm.NONE - && evictionAttributes.getAction().isLocalDestroy()) { - throw new UnsupportedOperationException( - "Lucene indexes on regions with eviction and action local destroy are not supported"); - } + LuceneServiceImpl.validateRegionAttributes(attrs); String aeqId = LuceneServiceImpl.getUniqueIndexName(this.indexName, this.regionPath); if (!attrs.getAsyncEventQueueIds().contains(aeqId)) { @@ -124,11 +108,6 @@ public class LuceneRegionListener implements RegionListener { if (region.getFullPath().equals(this.regionPath) && this.afterCreateInvoked.compareAndSet(false, true)) { this.service.afterDataRegionCreated(this.luceneIndex); - String aeqId = LuceneServiceImpl.getUniqueIndexName(this.indexName, this.regionPath); - AsyncEventQueueImpl aeq = (AsyncEventQueueImpl) cache.getAsyncEventQueue(aeqId); - AbstractPartitionedRepositoryManager repositoryManager = - (AbstractPartitionedRepositoryManager) luceneIndex.getRepositoryManager(); - repositoryManager.allowRepositoryComputation(); } } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneServiceImpl.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneServiceImpl.java index ec043cc..1434300 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneServiceImpl.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/LuceneServiceImpl.java @@ -32,7 +32,10 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper; import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; +import org.apache.geode.cache.EvictionAlgorithm; +import org.apache.geode.cache.EvictionAttributes; import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionAttributes; import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl; @@ -63,6 +66,8 @@ import org.apache.geode.internal.DSFIDFactory; import org.apache.geode.internal.DataSerializableFixedID; import org.apache.geode.internal.cache.CacheService; import org.apache.geode.internal.cache.InternalCache; +import org.apache.geode.internal.cache.InternalRegion; +import org.apache.geode.internal.cache.PartitionedRegion; import org.apache.geode.internal.cache.RegionListener; import org.apache.geode.internal.cache.extension.Extensible; import org.apache.geode.internal.cache.xmlcache.XmlGenerator; @@ -202,20 +207,21 @@ public class LuceneServiceImpl implements InternalLuceneService { } public void createIndex(String indexName, String regionPath, Map<String, Analyzer> fieldAnalyzers, - LuceneSerializer serializer) { + LuceneSerializer serializer, boolean allowOnExistingRegion) { if (fieldAnalyzers == null || fieldAnalyzers.isEmpty()) { throw new IllegalArgumentException("At least one field must be indexed"); } Analyzer analyzer = new PerFieldAnalyzerWrapper(new StandardAnalyzer(), fieldAnalyzers); Set<String> fieldsSet = fieldAnalyzers.keySet(); - String[] fields = (String[]) fieldsSet.toArray(new String[fieldsSet.size()]); + String[] fields = fieldsSet.toArray(new String[fieldsSet.size()]); - createIndex(indexName, regionPath, analyzer, fieldAnalyzers, serializer, fields); + createIndex(indexName, regionPath, analyzer, fieldAnalyzers, serializer, allowOnExistingRegion, + fields); } public void createIndex(final String indexName, String regionPath, final Analyzer analyzer, final Map<String, Analyzer> fieldAnalyzers, final LuceneSerializer serializer, - final String... fields) { + boolean allowOnExistingRegion, final String... fields) { if (!regionPath.startsWith("/")) { regionPath = "/" + regionPath; @@ -224,14 +230,59 @@ public class LuceneServiceImpl implements InternalLuceneService { registerDefinedIndex(indexName, regionPath, new LuceneIndexCreationProfile(indexName, regionPath, fields, analyzer, fieldAnalyzers, serializer)); - Region region = cache.getRegion(regionPath); - if (region != null) { + PartitionedRegion region = (PartitionedRegion) cache.getRegion(regionPath); + + LuceneRegionListener regionListener = new LuceneRegionListener(this, cache, indexName, + regionPath, fields, analyzer, fieldAnalyzers, serializer); + if (region == null) { + cache.addRegionListener(regionListener); + return; + } + + if (!allowOnExistingRegion) { definedIndexMap.remove(LuceneServiceImpl.getUniqueIndexName(indexName, regionPath)); throw new IllegalStateException("The lucene index must be created before region"); } - cache.addRegionListener(new LuceneRegionListener(this, cache, indexName, regionPath, fields, + + createIndexOnExistingRegion(region, indexName, regionPath, fields, analyzer, fieldAnalyzers, + serializer); + + } + + private void createIndexOnExistingRegion(PartitionedRegion region, String indexName, + String regionPath, String[] fields, Analyzer analyzer, Map<String, Analyzer> fieldAnalyzers, + LuceneSerializer serializer) { + validateRegionAttributes(region.getAttributes()); + + String aeqId = LuceneServiceImpl.getUniqueIndexName(indexName, regionPath); + region.addAsyncEventQueueId(aeqId, true); + + region.addCacheServiceProfile(new LuceneIndexCreationProfile(indexName, regionPath, fields, analyzer, fieldAnalyzers, serializer)); + + LuceneIndexImpl luceneIndex = beforeDataRegionCreated(indexName, regionPath, + region.getAttributes(), analyzer, fieldAnalyzers, aeqId, serializer, fields); + + afterDataRegionCreated(luceneIndex); + } + + static void validateRegionAttributes(RegionAttributes attrs) { + if (!attrs.getDataPolicy().withPartitioning()) { + // replicated region + throw new UnsupportedOperationException( + "Lucene indexes on replicated regions are not supported"); + } + + // For now we cannot support eviction with local destroy. + // Eviction with overflow to disk still needs to be supported + EvictionAttributes evictionAttributes = attrs.getEvictionAttributes(); + EvictionAlgorithm evictionAlgorithm = evictionAttributes.getAlgorithm(); + if (evictionAlgorithm != EvictionAlgorithm.NONE + && evictionAttributes.getAction().isLocalDestroy()) { + throw new UnsupportedOperationException( + "Lucene indexes on regions with eviction and action local destroy are not supported"); + } } /** @@ -246,6 +297,12 @@ public class LuceneServiceImpl implements InternalLuceneService { this.managementListener.afterIndexCreated(index); } + String aeqId = LuceneServiceImpl.getUniqueIndexName(index.getName(), index.getRegionPath()); + AsyncEventQueueImpl aeq = (AsyncEventQueueImpl) cache.getAsyncEventQueue(aeqId); + AbstractPartitionedRepositoryManager repositoryManager = + (AbstractPartitionedRepositoryManager) index.getRepositoryManager(); + repositoryManager.allowRepositoryComputation(); + } public LuceneIndexImpl beforeDataRegionCreated(final String indexName, final String regionPath, diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/xml/LuceneIndexCreation.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/xml/LuceneIndexCreation.java index bf171a1..d781c05 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/xml/LuceneIndexCreation.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/xml/LuceneIndexCreation.java @@ -15,7 +15,11 @@ package org.apache.geode.cache.lucene.internal.xml; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import org.apache.logging.log4j.Logger; import org.apache.lucene.analysis.Analyzer; @@ -23,7 +27,6 @@ import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.geode.cache.Cache; -import org.apache.geode.cache.Declarable; import org.apache.geode.cache.Region; import org.apache.geode.cache.lucene.LuceneIndex; import org.apache.geode.cache.lucene.LuceneIndexExistsException; @@ -100,7 +103,7 @@ public class LuceneIndexCreation implements LuceneIndex, Extension<Region<?, ?>> : new PerFieldAnalyzerWrapper(new StandardAnalyzer(), this.fieldAnalyzers); try { service.createIndex(getName(), getRegionPath(), analyzer, this.fieldAnalyzers, - getLuceneSerializer(), getFieldNames()); + getLuceneSerializer(), false, getFieldNames()); } catch (LuceneIndexExistsException e) { logger .info(LocalizedStrings.LuceneIndexCreation_IGNORING_DUPLICATE_INDEX_CREATION_0_ON_REGION_1 diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationDUnitTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationDUnitTest.java index 9328ede..2f9eb57 100644 --- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationDUnitTest.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationDUnitTest.java @@ -15,26 +15,47 @@ package org.apache.geode.cache.lucene; import static junitparams.JUnitParamsRunner.$; -import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.*; -import static org.junit.Assert.*; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS_2; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_FIELDS; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_FIELDS_2; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_1; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_2; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_3; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_NAMES; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_SERIALIZER; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.INDEX_NAME; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.REGION_NAME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.core.KeywordAnalyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.hamcrest.Matchers; +import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; +import org.apache.geode.cache.Cache; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.lucene.internal.LuceneIndexFactoryImpl; import org.apache.geode.cache.lucene.internal.repository.serializer.HeterogeneousLuceneSerializer; import org.apache.geode.cache.lucene.test.LuceneTestUtilities; +import org.apache.geode.cache.lucene.test.TestObject; import org.apache.geode.internal.i18n.LocalizedStrings; import org.apache.geode.test.dunit.SerializableRunnableIF; import org.apache.geode.test.junit.categories.DistributedTest; @@ -44,6 +65,9 @@ import org.apache.geode.util.test.TestUtil; @RunWith(JUnitParamsRunner.class) public class LuceneIndexCreationDUnitTest extends LuceneDUnitTest { + @Rule + public transient ExpectedException expectedException = ExpectedException.none(); + private Object[] parametersForMultipleIndexCreates() { Integer[] numIndexes = {1, 2, 10}; RegionTestableType[] regionTestTypes = getListOfRegionTestTypes(); @@ -249,6 +273,67 @@ public class LuceneIndexCreationDUnitTest extends LuceneDUnitTest { dataStore2.invoke(() -> initDataStore(createIndex, regionType)); } + @Test + @Parameters({"PARTITION", "PARTITION_REDUNDANT"}) + public void creatingIndexAfterRegionAndStartingUpSecondMemberSucceeds( + RegionTestableType regionType) { + dataStore1.invoke(() -> { + regionType.createDataStore(getCache(), REGION_NAME); + createIndexAfterRegion("field1"); + }); + + dataStore2.invoke(() -> { + createIndexAfterRegion("field1"); + regionType.createDataStore(getCache(), REGION_NAME); + }); + dataStore1.invoke(() -> { + putEntryAndQuery(); + }); + } + + @Test() + @Parameters({"PARTITION", "PARTITION_REDUNDANT"}) + public void creatingIndexAfterRegionAndStartingUpSecondMemberWithoutIndexFails( + RegionTestableType regionType) { + dataStore1.invoke(() -> { + regionType.createDataStore(getCache(), REGION_NAME); + createIndexAfterRegion("field1"); + }); + + expectedException.expectCause(Matchers.instanceOf(IllegalStateException.class)); + dataStore2.invoke(() -> { + regionType.createDataStore(getCache(), REGION_NAME); + createIndexAfterRegion("field1"); + }); + + dataStore1.invoke(() -> { + putEntryAndQuery(); + }); + } + + @Test + @Parameters({"PARTITION", "PARTITION_REDUNDANT"}) + public void creatingIndexAfterRegionInTwoMembersSucceed(RegionTestableType regionType) { + dataStore1.invoke(() -> { + regionType.createDataStore(getCache(), REGION_NAME); + }); + + dataStore2.invoke(() -> { + regionType.createDataStore(getCache(), REGION_NAME); + }); + + dataStore1.invoke(() -> { + createIndexAfterRegion("field1"); + }); + + dataStore2.invoke(() -> { + createIndexAfterRegion("field1"); + }); + + dataStore1.invoke(() -> { + putEntryAndQuery(); + }); + } @Test @Parameters(method = "getXmlAndExceptionMessages") @@ -545,4 +630,24 @@ public class LuceneIndexCreationDUnitTest extends LuceneDUnitTest { protected void verifyAsyncEventQueues(final int expectedSize) { assertEquals(expectedSize, getCache().getAsyncEventQueues(false).size()); } + + private void createIndexAfterRegion(String... fields) { + LuceneService luceneService = LuceneServiceProvider.get(getCache()); + LuceneIndexFactoryImpl indexFactory = + (LuceneIndexFactoryImpl) luceneService.createIndexFactory(); + indexFactory.setFields(fields).create(INDEX_NAME, REGION_NAME, true); + } + + private void putEntryAndQuery() throws InterruptedException, LuceneQueryException { + Cache cache = getCache(); + Region region = cache.getRegion(REGION_NAME); + region.put("key1", new TestObject("field1Value", "field2Value")); + LuceneService luceneService = LuceneServiceProvider.get(cache); + luceneService.waitUntilFlushed(INDEX_NAME, REGION_NAME, 1, TimeUnit.MINUTES); + LuceneQuery<Object, Object> query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, + REGION_NAME, "field1:field1Value", "field1"); + assertEquals(Collections.singletonList("key1"), query.findKeys()); + } + + } diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationIntegrationTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationIntegrationTest.java index 00b96e0..8d88875 100644 --- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationIntegrationTest.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/LuceneIndexCreationIntegrationTest.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -50,6 +51,7 @@ import org.apache.geode.cache.Region; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.cache.lucene.internal.LuceneIndexCreationProfile; +import org.apache.geode.cache.lucene.internal.LuceneIndexFactoryImpl; import org.apache.geode.cache.lucene.internal.LuceneIndexImplFactory; import org.apache.geode.cache.lucene.internal.LuceneRawIndex; import org.apache.geode.cache.lucene.internal.LuceneRawIndexFactory; @@ -183,6 +185,43 @@ public class LuceneIndexCreationIntegrationTest extends LuceneIntegrationTest { createIndex("field1", "field2", "field3"); } + @Test() + public void canCreateLuceneIndexAfterRegionCreatedIfAllowFlagIsSet() + throws IOException, ParseException, InterruptedException, LuceneQueryException { + Region region = createRegion(); + LuceneService luceneService = LuceneServiceProvider.get(cache); + final LuceneIndexFactoryImpl indexFactory = + (LuceneIndexFactoryImpl) luceneService.createIndexFactory(); + indexFactory.setFields("field1", "field2").create(INDEX_NAME, REGION_NAME, true); + + LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); + assertNotNull(index); + + region.put("key1", new TestObject("hello", "world")); + luceneService.waitUntilFlushed(INDEX_NAME, REGION_NAME, 1, TimeUnit.MINUTES); + LuceneQuery<Object, Object> query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, + REGION_NAME, "field1:hello", "field1"); + + assertEquals(Collections.singletonList("key1"), query.findKeys()); + } + + + @Test() + public void creatingDuplicateLuceneIndexFails() + throws IOException, ParseException, InterruptedException, LuceneQueryException { + Region region = createRegion(); + LuceneService luceneService = LuceneServiceProvider.get(cache); + final LuceneIndexFactoryImpl indexFactory = + (LuceneIndexFactoryImpl) luceneService.createIndexFactory(); + indexFactory.setFields("field1", "field2").create(INDEX_NAME, REGION_NAME, true); + + LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); + assertNotNull(index); + + expectedException.expect(LuceneIndexExistsException.class); + indexFactory.setFields("field1", "field2").create(INDEX_NAME, REGION_NAME, true); + } + @Test public void cannotCreateLuceneIndexForReplicateRegion() throws IOException, ParseException { try { diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImplJUnitTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImplJUnitTest.java index 67759db..bafb60a 100644 --- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImplJUnitTest.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneIndexFactoryImplJUnitTest.java @@ -14,7 +14,6 @@ */ package org.apache.geode.cache.lucene.internal; -import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -37,7 +36,8 @@ public class LuceneIndexFactoryImplJUnitTest { LuceneIndexFactory factory = new LuceneIndexFactoryImpl(service); factory.setLuceneSerializer(serializer); factory.create("index", "region"); - Mockito.verify(service).createIndex(eq("index"), eq("region"), any(), eq(serializer)); + Mockito.verify(service).createIndex(eq("index"), eq("region"), any(), eq(serializer), + eq(false)); } } diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneServiceImplJUnitTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneServiceImplJUnitTest.java index 57186c3..23c23cc 100644 --- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneServiceImplJUnitTest.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/internal/LuceneServiceImplJUnitTest.java @@ -63,7 +63,8 @@ public class LuceneServiceImplJUnitTest { factory.setLuceneSerializer(serializer); factory.setFields("field1", "field2"); factory.create("index", "region"); - Mockito.verify(service).createIndex(eq("index"), eq("region"), any(), eq(serializer)); + Mockito.verify(service).createIndex(eq("index"), eq("region"), any(), eq(serializer), + eq(false)); } @Test @@ -75,7 +76,7 @@ public class LuceneServiceImplJUnitTest { @Test public void shouldThrowIllegalArgumentExceptionIfFieldsMapIsMissing() { thrown.expect(IllegalArgumentException.class); - service.createIndex("index", "region", Collections.emptyMap(), null); + service.createIndex("index", "region", Collections.emptyMap(), null, false); } @Test -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
