/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.cache.lucene.test; import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.REGION_NAME; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import org.apache.geode.cache.AttributesFactory; import org.apache.geode.cache.Cache; import org.apache.geode.cache.EntryOperation; import org.apache.geode.cache.FixedPartitionAttributes; import org.apache.geode.cache.FixedPartitionResolver; import org.apache.geode.cache.PartitionAttributesFactory; import org.apache.geode.cache.Region; import org.apache.geode.cache.asyncqueue.AsyncEventQueue; import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl; import org.apache.geode.cache.lucene.LuceneIndex; import org.apache.geode.cache.lucene.LuceneQuery; import org.apache.geode.cache.lucene.LuceneQueryException; import org.apache.geode.cache.lucene.PageableLuceneQueryResults; import org.apache.geode.cache.lucene.LuceneService; import org.apache.geode.cache.lucene.LuceneServiceProvider; import org.apache.geode.cache.lucene.internal.LuceneIndexForPartitionedRegion; import org.apache.geode.cache.lucene.internal.LuceneServiceImpl; import org.apache.geode.cache.persistence.PartitionOfflineException; import org.apache.geode.internal.cache.ForceReattemptException; import org.apache.geode.internal.cache.LocalRegion; import org.apache.geode.internal.cache.wan.AbstractGatewaySender; import org.apache.geode.pdx.JSONFormatter; import org.apache.geode.pdx.PdxInstance; import org.apache.geode.test.dunit.IgnoredException; import org.apache.geode.test.dunit.VM; public class LuceneTestUtilities { public static final String INDEX_NAME = "index"; public static final String REGION_NAME = "region"; public static final String DEFAULT_FIELD = "text"; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_FIELDS = "Cannot create Lucene index index on region /region with fields [field1, field2] because another member defines the same index with fields [field1]."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_FIELDS_2 = "Cannot create Lucene index index on region /region with fields [field1] because another member defines the same index with fields [field1, field2]."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS = "Cannot create Lucene index index on region /region with analyzer StandardAnalyzer on field field2 because another member defines the same index with analyzer KeywordAnalyzer on that field."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS_1 = "Cannot create Lucene index index on region /region with analyzer StandardAnalyzer on field field1 because another member defines the same index with analyzer KeywordAnalyzer on that field."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS_2 = "Cannot create Lucene index index on region /region with analyzer KeywordAnalyzer on field field1 because another member defines the same index with analyzer StandardAnalyzer on that field."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_ANALYZERS_3 = "Cannot create Lucene index index on region /region with analyzer KeywordAnalyzer on field field2 because another member defines the same index with analyzer StandardAnalyzer on that field."; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_NAMES = "Cannot create Region /region with [index2#_region] async event ids because another cache has the same region defined with [index1#_region] async event ids"; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_1 = "Cannot create Region /region with [] async event ids because another cache has the same region defined with [index#_region] async event ids"; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_2 = "Cannot create Region /region with [index#_region, index2#_region] async event ids because another cache has the same region defined with [index#_region] async event ids"; public static final String CANNOT_CREATE_LUCENE_INDEX_DIFFERENT_INDEXES_3 = "Cannot create Region /region with [index#_region] async event ids because another cache has the same region defined with [] async event ids"; public static String Quarter1 = "Q1"; public static String Quarter2 = "Q2"; public static String Quarter3 = "Q3"; public static String Quarter4 = "Q4"; public static void initDataStoreForFixedPR(final Cache cache) throws Exception { List<FixedPartitionAttributes> fpaList = new ArrayList<FixedPartitionAttributes>(); int vmNum = VM.getCurrentVMNum(); if (vmNum % 2 == 0) { FixedPartitionAttributes fpa1 = FixedPartitionAttributes.createFixedPartition(Quarter1, true); FixedPartitionAttributes fpa2 = FixedPartitionAttributes.createFixedPartition(Quarter2, false); fpaList.clear(); fpaList.add(fpa1); fpaList.add(fpa2); } else { FixedPartitionAttributes fpa1 = FixedPartitionAttributes.createFixedPartition(Quarter1, false); FixedPartitionAttributes fpa2 = FixedPartitionAttributes.createFixedPartition(Quarter2, true); fpaList.clear(); fpaList.add(fpa1); fpaList.add(fpa2); } createFixedPartitionedRegion(cache, REGION_NAME, fpaList, 40); } public static void createFixedPartitionedRegion(final Cache cache, String regionName, List<FixedPartitionAttributes> fpaList, int localMaxMemory) { List<String> allPartitions = new ArrayList(); if (fpaList != null) { for (FixedPartitionAttributes fpa : fpaList) { allPartitions.add(fpa.getPartitionName()); } } else { allPartitions.add("Q1"); allPartitions.add("Q2"); } AttributesFactory fact = new AttributesFactory(); PartitionAttributesFactory pfact = new PartitionAttributesFactory(); pfact.setTotalNumBuckets(16); pfact.setRedundantCopies(1); pfact.setLocalMaxMemory(localMaxMemory); if (fpaList != null) { for (FixedPartitionAttributes fpa : fpaList) { pfact.addFixedPartitionAttributes(fpa); } } pfact.setPartitionResolver(new MyFixedPartitionResolver(allPartitions)); fact.setPartitionAttributes(pfact.create()); Region r = cache.createRegionFactory(fact.create()).create(regionName); assertNotNull(r); } static class MyFixedPartitionResolver implements FixedPartitionResolver { private final List<String> allPartitions; public MyFixedPartitionResolver(final List<String> allPartitions) { this.allPartitions = allPartitions; } @Override public String getPartitionName(final EntryOperation opDetails, @Deprecated final Set targetPartitions) { int hash = Math.abs(opDetails.getKey().hashCode() % allPartitions.size()); return allPartitions.get(hash); } @Override public Object getRoutingObject(final EntryOperation opDetails) { return opDetails.getKey(); } @Override public String getName() { return getClass().getName(); } @Override public void close() { } } public static void verifyInternalRegions(LuceneService luceneService, Cache cache, Consumer<LocalRegion> verify) { // Get index LuceneIndexForPartitionedRegion index = (LuceneIndexForPartitionedRegion) luceneService.getIndex(INDEX_NAME, REGION_NAME); // Verify the meta regions exist and are internal LocalRegion chunkRegion = (LocalRegion) cache.getRegion(index.createChunkRegionName()); LocalRegion fileRegion = (LocalRegion) cache.getRegion(index.createFileRegionName()); verify.accept(chunkRegion); verify.accept(fileRegion); } public static AsyncEventQueue getIndexQueue(Cache cache) { String aeqId = LuceneServiceImpl.getUniqueIndexName(INDEX_NAME, REGION_NAME); return cache.getAsyncEventQueue(aeqId); } public static void createIndex(Cache cache, String... fieldNames) { LuceneServiceProvider.get(cache).createIndex(INDEX_NAME, REGION_NAME, fieldNames); } public static void verifyIndexFinishFlushing(Cache cache, String indexName, String regionName) throws InterruptedException { LuceneService luceneService = LuceneServiceProvider.get(cache); LuceneIndex index = luceneService.getIndex(indexName, regionName); boolean flushed = index.waitUntilFlushed(60000, TimeUnit.MILLISECONDS); assertTrue(flushed); } /** * Verify that a query returns the expected list of keys. Ordering is ignored. */ public static <K> void verifyQueryKeys(LuceneQuery<K, Object> query, K... expectedKeys) throws LuceneQueryException { Set<K> expectedKeySet = new HashSet<>(Arrays.asList(expectedKeys)); Set<K> actualKeySet = new HashSet<>(query.findKeys()); assertEquals(expectedKeySet, actualKeySet); } /** * Verify that a query returns the expected map of key-value. Ordering is ignored. */ public static <K> void verifyQueryKeyAndValues(LuceneQuery<K, Object> query, HashMap expectedResults) throws LuceneQueryException { HashMap actualResults = new HashMap<>(); final PageableLuceneQueryResults<K, Object> results = query.findPages(); while (results.hasNext()) { results.next().stream().forEach(struct -> { Object value = struct.getValue(); actualResults.put(struct.getKey(), value); }); } assertEquals(expectedResults, actualResults); } public static void pauseSender(final Cache cache) { final AsyncEventQueueImpl queue = (AsyncEventQueueImpl) getIndexQueue(cache); queue.getSender().pause(); AbstractGatewaySender sender = (AbstractGatewaySender) queue.getSender(); sender.getEventProcessor().waitForDispatcherToPause(); } public static void resumeSender(final Cache cache) { final AsyncEventQueueImpl queue = (AsyncEventQueueImpl) getIndexQueue(cache); queue.getSender().resume(); } }