|
@@ -33,6 +33,7 @@ import org.apache.lucene.store.IOContext;
|
|
|
import org.apache.lucene.util.Constants;
|
|
|
import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
|
|
|
+import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
|
|
|
import org.elasticsearch.action.admin.indices.stats.CommonStats;
|
|
|
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
|
|
|
import org.elasticsearch.action.admin.indices.stats.ShardStats;
|
|
@@ -57,11 +58,13 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
import org.elasticsearch.common.lease.Releasable;
|
|
|
import org.elasticsearch.common.lease.Releasables;
|
|
|
+import org.elasticsearch.common.lucene.uid.Versions;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
|
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
|
|
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
import org.elasticsearch.env.NodeEnvironment;
|
|
|
+import org.elasticsearch.index.VersionType;
|
|
|
import org.elasticsearch.index.engine.Engine;
|
|
|
import org.elasticsearch.index.engine.EngineException;
|
|
|
import org.elasticsearch.index.fielddata.FieldDataStats;
|
|
@@ -73,6 +76,7 @@ import org.elasticsearch.index.mapper.ParsedDocument;
|
|
|
import org.elasticsearch.index.mapper.SeqNoFieldMapper;
|
|
|
import org.elasticsearch.index.mapper.Uid;
|
|
|
import org.elasticsearch.index.mapper.UidFieldMapper;
|
|
|
+import org.elasticsearch.index.seqno.SequenceNumbersService;
|
|
|
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus;
|
|
|
import org.elasticsearch.index.store.Store;
|
|
|
import org.elasticsearch.index.translog.Translog;
|
|
@@ -112,13 +116,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
import java.util.function.BiConsumer;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.IntStream;
|
|
|
|
|
|
import static java.util.Collections.emptyMap;
|
|
|
import static java.util.Collections.emptySet;
|
|
|
import static org.elasticsearch.common.lucene.Lucene.cleanLuceneIndex;
|
|
|
-import static org.elasticsearch.common.lucene.Lucene.readScoreDoc;
|
|
|
import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS;
|
|
|
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
|
|
+import static org.elasticsearch.index.engine.Engine.Operation.Origin.PRIMARY;
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
import static org.hamcrest.Matchers.equalTo;
|
|
|
import static org.hamcrest.Matchers.greaterThan;
|
|
@@ -1357,6 +1363,91 @@ public class IndexShardTests extends IndexShardTestCase {
|
|
|
closeShards(sourceShard, targetShard);
|
|
|
}
|
|
|
|
|
|
+ public void testDocStats() throws IOException {
|
|
|
+ IndexShard indexShard = null;
|
|
|
+ try {
|
|
|
+ indexShard = newStartedShard();
|
|
|
+ final long numDocs = randomIntBetween(2, 32); // at least two documents so we have docs to delete
|
|
|
+ final long numDocsToDelete = randomIntBetween(1, Math.toIntExact(numDocs));
|
|
|
+ for (int i = 0; i < numDocs; i++) {
|
|
|
+ final String id = Integer.toString(i);
|
|
|
+ final ParsedDocument doc =
|
|
|
+ testParsedDocument(id, id, "test", null, new ParseContext.Document(), new BytesArray("{}"), null);
|
|
|
+ final Engine.Index index =
|
|
|
+ new Engine.Index(
|
|
|
+ new Term("_uid", id),
|
|
|
+ doc,
|
|
|
+ SequenceNumbersService.UNASSIGNED_SEQ_NO,
|
|
|
+ 0,
|
|
|
+ Versions.MATCH_ANY,
|
|
|
+ VersionType.INTERNAL,
|
|
|
+ PRIMARY,
|
|
|
+ System.nanoTime(),
|
|
|
+ -1,
|
|
|
+ false);
|
|
|
+ final Engine.IndexResult result = indexShard.index(index);
|
|
|
+ assertThat(result.getVersion(), equalTo(1L));
|
|
|
+ }
|
|
|
+
|
|
|
+ indexShard.refresh("test");
|
|
|
+ {
|
|
|
+ final DocsStats docsStats = indexShard.docStats();
|
|
|
+ assertThat(docsStats.getCount(), equalTo(numDocs));
|
|
|
+ assertThat(docsStats.getDeleted(), equalTo(0L));
|
|
|
+ }
|
|
|
+
|
|
|
+ final List<Integer> ids = randomSubsetOf(
|
|
|
+ Math.toIntExact(numDocsToDelete),
|
|
|
+ IntStream.range(0, Math.toIntExact(numDocs)).boxed().collect(Collectors.toList()));
|
|
|
+ for (final Integer i : ids) {
|
|
|
+ final String id = Integer.toString(i);
|
|
|
+ final ParsedDocument doc = testParsedDocument(id, id, "test", null, new ParseContext.Document(), new BytesArray("{}"), null);
|
|
|
+ final Engine.Index index =
|
|
|
+ new Engine.Index(
|
|
|
+ new Term("_uid", id),
|
|
|
+ doc,
|
|
|
+ SequenceNumbersService.UNASSIGNED_SEQ_NO,
|
|
|
+ 0,
|
|
|
+ Versions.MATCH_ANY,
|
|
|
+ VersionType.INTERNAL,
|
|
|
+ PRIMARY,
|
|
|
+ System.nanoTime(),
|
|
|
+ -1,
|
|
|
+ false);
|
|
|
+ final Engine.IndexResult result = indexShard.index(index);
|
|
|
+ assertThat(result.getVersion(), equalTo(2L));
|
|
|
+ }
|
|
|
+
|
|
|
+ // flush the buffered deletes
|
|
|
+ final FlushRequest flushRequest = new FlushRequest();
|
|
|
+ flushRequest.force(false);
|
|
|
+ flushRequest.waitIfOngoing(false);
|
|
|
+ indexShard.flush(flushRequest);
|
|
|
+
|
|
|
+ indexShard.refresh("test");
|
|
|
+ {
|
|
|
+ final DocsStats docStats = indexShard.docStats();
|
|
|
+ assertThat(docStats.getCount(), equalTo(numDocs));
|
|
|
+ assertThat(docStats.getDeleted(), equalTo(numDocsToDelete));
|
|
|
+ }
|
|
|
+
|
|
|
+ // merge them away
|
|
|
+ final ForceMergeRequest forceMergeRequest = new ForceMergeRequest();
|
|
|
+ forceMergeRequest.onlyExpungeDeletes(randomBoolean());
|
|
|
+ forceMergeRequest.maxNumSegments(1);
|
|
|
+ indexShard.forceMerge(forceMergeRequest);
|
|
|
+
|
|
|
+ indexShard.refresh("test");
|
|
|
+ {
|
|
|
+ final DocsStats docStats = indexShard.docStats();
|
|
|
+ assertThat(docStats.getCount(), equalTo(numDocs));
|
|
|
+ assertThat(docStats.getDeleted(), equalTo(0L));
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ closeShards(indexShard);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/** A dummy repository for testing which just needs restore overridden */
|
|
|
private abstract static class RestoreOnlyRepository extends AbstractLifecycleComponent implements Repository {
|
|
|
private final String indexName;
|