|
@@ -11,6 +11,7 @@ import org.apache.lucene.analysis.Analyzer;
|
|
|
import org.apache.lucene.analysis.standard.StandardTokenizer;
|
|
|
import org.apache.lucene.index.DirectoryReader;
|
|
|
import org.apache.lucene.index.FieldInvertState;
|
|
|
+import org.apache.lucene.index.IndexCommit;
|
|
|
import org.apache.lucene.index.Term;
|
|
|
import org.apache.lucene.search.CollectionStatistics;
|
|
|
import org.apache.lucene.search.QueryCachingPolicy;
|
|
@@ -23,13 +24,17 @@ import org.apache.lucene.store.FilterDirectory;
|
|
|
import org.apache.lucene.tests.index.AssertingDirectoryReader;
|
|
|
import org.apache.lucene.util.SetOnce.AlreadySetException;
|
|
|
import org.elasticsearch.Version;
|
|
|
+import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
|
|
+import org.elasticsearch.action.support.PlainActionFuture;
|
|
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
|
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
|
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
|
|
+import org.elasticsearch.cluster.node.DiscoveryNodeRole;
|
|
|
import org.elasticsearch.cluster.routing.RecoverySource;
|
|
|
import org.elasticsearch.cluster.routing.ShardRouting;
|
|
|
import org.elasticsearch.cluster.routing.UnassignedInfo;
|
|
|
import org.elasticsearch.cluster.service.ClusterService;
|
|
|
+import org.elasticsearch.common.UUIDs;
|
|
|
import org.elasticsearch.common.breaker.CircuitBreaker;
|
|
|
import org.elasticsearch.common.settings.Setting;
|
|
|
import org.elasticsearch.common.settings.Setting.Property;
|
|
@@ -51,12 +56,15 @@ import org.elasticsearch.index.cache.query.IndexQueryCache;
|
|
|
import org.elasticsearch.index.cache.query.QueryCache;
|
|
|
import org.elasticsearch.index.engine.Engine;
|
|
|
import org.elasticsearch.index.engine.EngineTestCase;
|
|
|
+import org.elasticsearch.index.engine.InternalEngine;
|
|
|
import org.elasticsearch.index.engine.InternalEngineFactory;
|
|
|
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
|
|
import org.elasticsearch.index.mapper.MapperRegistry;
|
|
|
import org.elasticsearch.index.mapper.ParsedDocument;
|
|
|
import org.elasticsearch.index.mapper.Uid;
|
|
|
+import org.elasticsearch.index.seqno.RetentionLeaseSyncer;
|
|
|
import org.elasticsearch.index.shard.IndexEventListener;
|
|
|
+import org.elasticsearch.index.shard.IndexShard;
|
|
|
import org.elasticsearch.index.shard.IndexingOperationListener;
|
|
|
import org.elasticsearch.index.shard.SearchOperationListener;
|
|
|
import org.elasticsearch.index.shard.ShardId;
|
|
@@ -84,24 +92,31 @@ import org.elasticsearch.threadpool.TestThreadPool;
|
|
|
import org.elasticsearch.threadpool.ThreadPool;
|
|
|
import org.hamcrest.Matchers;
|
|
|
|
|
|
+import java.io.Closeable;
|
|
|
import java.io.IOException;
|
|
|
import java.nio.file.Path;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
+import java.util.concurrent.ExecutionException;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
|
import static java.util.Collections.emptyMap;
|
|
|
import static java.util.Collections.singletonMap;
|
|
|
import static org.elasticsearch.index.IndexService.IndexCreationContext.CREATE_INDEX;
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.empty;
|
|
|
+import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.hasToString;
|
|
|
import static org.hamcrest.Matchers.instanceOf;
|
|
|
import static org.hamcrest.Matchers.is;
|
|
|
import static org.hamcrest.Matchers.notNullValue;
|
|
|
+import static org.hamcrest.Matchers.nullValue;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
|
|
|
public class IndexModuleTests extends ESTestCase {
|
|
@@ -415,6 +430,7 @@ public class IndexModuleTests extends ESTestCase {
|
|
|
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.setReaderWrapper(null)).getMessage());
|
|
|
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.forceQueryCacheProvider(null)).getMessage());
|
|
|
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.setDirectoryWrapper(null)).getMessage());
|
|
|
+ assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.setIndexCommitListener(null)).getMessage());
|
|
|
}
|
|
|
|
|
|
public void testSetupUnknownSimilarity() {
|
|
@@ -610,6 +626,94 @@ public class IndexModuleTests extends ESTestCase {
|
|
|
indexService.close("closing", false);
|
|
|
}
|
|
|
|
|
|
+ public void testIndexCommitListenerIsBound() throws IOException, ExecutionException, InterruptedException {
|
|
|
+ IndexModule module = new IndexModule(
|
|
|
+ indexSettings,
|
|
|
+ emptyAnalysisRegistry,
|
|
|
+ InternalEngine::new,
|
|
|
+ Collections.emptyMap(),
|
|
|
+ () -> true,
|
|
|
+ indexNameExpressionResolver,
|
|
|
+ Collections.emptyMap()
|
|
|
+ );
|
|
|
+
|
|
|
+ final AtomicReference<Engine.IndexCommitRef> lastAcquiredCommit = new AtomicReference<>();
|
|
|
+ final AtomicReference<IndexCommit> lastDeletedCommit = new AtomicReference<>();
|
|
|
+
|
|
|
+ module.setIndexCommitListener(new Engine.IndexCommitListener() {
|
|
|
+ @Override
|
|
|
+ public void onNewCommit(ShardId shardId, Engine.IndexCommitRef indexCommitRef) {
|
|
|
+ lastAcquiredCommit.set(indexCommitRef);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onIndexCommitDelete(ShardId shardId, IndexCommit deletedCommit) {
|
|
|
+ lastDeletedCommit.set(deletedCommit);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ final List<Closeable> closeables = new ArrayList<>();
|
|
|
+ try {
|
|
|
+ ShardId shardId = new ShardId("index", UUIDs.randomBase64UUID(random()), 0);
|
|
|
+ ShardRouting shardRouting = ShardRouting.newUnassigned(
|
|
|
+ shardId,
|
|
|
+ true,
|
|
|
+ RecoverySource.EmptyStoreRecoverySource.INSTANCE,
|
|
|
+ new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, null)
|
|
|
+ ).initialize("_node_id", null, -1);
|
|
|
+
|
|
|
+ IndexService indexService = newIndexService(module);
|
|
|
+ closeables.add(() -> indexService.close("close index service at end of test", false));
|
|
|
+
|
|
|
+ IndexShard indexShard = indexService.createShard(shardRouting, s -> {}, RetentionLeaseSyncer.EMPTY);
|
|
|
+ closeables.add(() -> indexShard.close("close shard at end of test", true));
|
|
|
+ indexShard.markAsRecovering(
|
|
|
+ "test",
|
|
|
+ new RecoveryState(
|
|
|
+ shardRouting,
|
|
|
+ new DiscoveryNode(
|
|
|
+ "_node_id",
|
|
|
+ "_node_id",
|
|
|
+ buildNewFakeTransportAddress(),
|
|
|
+ Collections.emptyMap(),
|
|
|
+ DiscoveryNodeRole.roles(),
|
|
|
+ Version.CURRENT
|
|
|
+ ),
|
|
|
+ null
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+ final PlainActionFuture<Boolean> recoveryFuture = PlainActionFuture.newFuture();
|
|
|
+ indexShard.recoverFromStore(recoveryFuture);
|
|
|
+ recoveryFuture.get();
|
|
|
+
|
|
|
+ Engine.IndexCommitRef lastCommitRef = lastAcquiredCommit.get();
|
|
|
+ assertThat(lastCommitRef, notNullValue());
|
|
|
+ IndexCommit lastCommit = lastCommitRef.getIndexCommit();
|
|
|
+ assertThat(lastCommit.getGeneration(), equalTo(2L));
|
|
|
+ IndexCommit lastDeleted = lastDeletedCommit.get();
|
|
|
+ assertThat(lastDeleted, nullValue());
|
|
|
+
|
|
|
+ lastCommitRef.close();
|
|
|
+
|
|
|
+ indexShard.flush(new FlushRequest("index").force(true));
|
|
|
+
|
|
|
+ lastDeleted = lastDeletedCommit.get();
|
|
|
+ assertThat(lastDeleted.getGeneration(), equalTo(lastCommit.getGeneration()));
|
|
|
+ assertThat(lastDeleted.getSegmentsFileName(), equalTo(lastCommit.getSegmentsFileName()));
|
|
|
+ assertThat(lastDeleted.isDeleted(), equalTo(true));
|
|
|
+
|
|
|
+ lastCommitRef = lastAcquiredCommit.get();
|
|
|
+ assertThat(lastCommitRef, notNullValue());
|
|
|
+ lastCommit = lastCommitRef.getIndexCommit();
|
|
|
+ assertThat(lastCommit.getGeneration(), equalTo(3L));
|
|
|
+
|
|
|
+ lastCommitRef.close();
|
|
|
+ } finally {
|
|
|
+ IOUtils.close(closeables);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private ShardRouting createInitializedShardRouting() {
|
|
|
ShardRouting shard = ShardRouting.newUnassigned(
|
|
|
new ShardId("test", "_na_", 0),
|