From f713106827abeb1c6bf85ed7949570f6b1d73266 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 8 Dec 2016 16:08:15 -0500 Subject: [PATCH 1/5] Bump version to 5.1.2 This commit bumps the version to 5.1.2. Relates #22057 --- .../main/java/org/elasticsearch/Version.java | 4 ++++ .../test/resources/indices/bwc/index-5.1.1.zip | Bin 0 -> 123893 bytes .../test/resources/indices/bwc/repo-5.1.1.zip | Bin 0 -> 97629 bytes qa/vagrant/versions | 1 + 4 files changed, 5 insertions(+) create mode 100644 core/src/test/resources/indices/bwc/index-5.1.1.zip create mode 100644 core/src/test/resources/indices/bwc/repo-5.1.1.zip diff --git a/core/src/main/java/org/elasticsearch/Version.java b/core/src/main/java/org/elasticsearch/Version.java index 80d870e2dcc..236a8936ff8 100644 --- a/core/src/main/java/org/elasticsearch/Version.java +++ b/core/src/main/java/org/elasticsearch/Version.java @@ -102,6 +102,8 @@ public class Version { // no version constant for 5.1.0 due to inadvertent release public static final int V_5_1_1_ID_UNRELEASED = 5010199; public static final Version V_5_1_1_UNRELEASED = new Version(V_5_1_1_ID_UNRELEASED, org.apache.lucene.util.Version.LUCENE_6_3_0); + public static final int V_5_1_2_ID_UNRELEASED = 5010299; + public static final Version V_5_1_2_UNRELEASED = new Version(V_5_1_2_ID_UNRELEASED, org.apache.lucene.util.Version.LUCENE_6_3_0); public static final int V_5_2_0_ID_UNRELEASED = 5020099; public static final Version V_5_2_0_UNRELEASED = new Version(V_5_2_0_ID_UNRELEASED, org.apache.lucene.util.Version.LUCENE_6_3_0); public static final int V_6_0_0_alpha1_ID_UNRELEASED = 6000001; @@ -126,6 +128,8 @@ public class Version { return V_6_0_0_alpha1_UNRELEASED; case V_5_2_0_ID_UNRELEASED: return V_5_2_0_UNRELEASED; + case V_5_1_2_ID_UNRELEASED: + return V_5_1_2_UNRELEASED; case V_5_1_1_ID_UNRELEASED: return V_5_1_1_UNRELEASED; case V_5_0_3_ID_UNRELEASED: diff --git a/core/src/test/resources/indices/bwc/index-5.1.1.zip b/core/src/test/resources/indices/bwc/index-5.1.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..cd88ea5e8f196d591ade4ebf8a6acbf8d0f02be6 GIT binary patch literal 123893 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

s#{DFn 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̳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 z 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 W@nfGRBnSXXNdN%W4v3!$@c#gbbJJJ= literal 0 HcmV?d00001 diff --git a/core/src/test/resources/indices/bwc/repo-5.1.1.zip b/core/src/test/resources/indices/bwc/repo-5.1.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..3ddf4beb5aa76f45a37eadc52294340795a242f6 GIT binary patch literal 97629 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 literal 0 HcmV?d00001 diff --git a/qa/vagrant/versions b/qa/vagrant/versions index c04bbb7dd3b..7a5ba032951 100644 --- a/qa/vagrant/versions +++ b/qa/vagrant/versions @@ -1,3 +1,4 @@ 5.0.0 5.0.1 5.0.2 +5.1.1 From 4aae0178912309eba92e2ae8028facd636c8679a Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 8 Dec 2016 16:38:38 -0500 Subject: [PATCH 2/5] Skip IP range query REST test prior to 5.1.2 This commit adds a skip for the IP range query REST test on version prior to 5.1.2 due to a exclusive bug on the top end of the range. --- .../rest-api-spec/test/search.aggregation/40_range.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/40_range.yaml b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/40_range.yaml index f2f9d7ccf8e..c058721124f 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/40_range.yaml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/search.aggregation/40_range.yaml @@ -111,6 +111,9 @@ setup: --- "IP range": + - skip: + version: " - 5.1.1" + reason: IP range queries had an exclusive range bug prior to 5.1.2 - do: index: index: test From c9882dd1a0f3c513d4c39e99c8a928ec2a6bab18 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Thu, 8 Dec 2016 19:59:02 -0500 Subject: [PATCH 3/5] Avoid NPE in NodeService#stats if HTTP is disabled This commit adds safety against an NPE if HTTP stats are requested but HTTP is disabled on a node. Relates #22060 --- .../node/service/NodeService.java | 9 ++-- .../node/service/NodeServiceTests.java | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 core/src/test/java/org/elasticsearch/node/service/NodeServiceTests.java diff --git a/core/src/main/java/org/elasticsearch/node/service/NodeService.java b/core/src/main/java/org/elasticsearch/node/service/NodeService.java index cf1f70590c5..36a399321e1 100644 --- a/core/src/main/java/org/elasticsearch/node/service/NodeService.java +++ b/core/src/main/java/org/elasticsearch/node/service/NodeService.java @@ -19,9 +19,6 @@ package org.elasticsearch.node.service; -import java.io.Closeable; -import java.io.IOException; - import org.elasticsearch.Build; import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.node.info.NodeInfo; @@ -44,6 +41,9 @@ import org.elasticsearch.script.ScriptService; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; +import java.io.Closeable; +import java.io.IOException; + public class NodeService extends AbstractComponent implements Closeable { private final ThreadPool threadPool; @@ -111,7 +111,7 @@ public class NodeService extends AbstractComponent implements Closeable { threadPool ? this.threadPool.stats() : null, fs ? monitorService.fsService().stats() : null, transport ? transportService.stats() : null, - http ? httpServer.stats() : null, + http ? (httpServer == null ? null : httpServer.stats()) : null, circuitBreaker ? circuitBreakerService.stats() : null, script ? scriptService.stats() : null, discoveryStats ? discovery.stats() : null, @@ -127,4 +127,5 @@ public class NodeService extends AbstractComponent implements Closeable { public void close() throws IOException { indicesService.close(); } + } diff --git a/core/src/test/java/org/elasticsearch/node/service/NodeServiceTests.java b/core/src/test/java/org/elasticsearch/node/service/NodeServiceTests.java new file mode 100644 index 00000000000..e9097b81426 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/node/service/NodeServiceTests.java @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.node.service; + +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequest; +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; +import org.elasticsearch.common.network.NetworkModule; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.ESSingleNodeTestCase; + +import static org.hamcrest.Matchers.hasSize; + +public class NodeServiceTests extends ESSingleNodeTestCase { + + @Override + protected Settings nodeSettings() { + return Settings.builder().put(NetworkModule.HTTP_ENABLED.getKey(), false).build(); + } + + public void testHttpServerDisabled() { + // test for a bug where if HTTP stats were requested but HTTP was disabled, NodeService would hit a NullPointerException + NodesStatsResponse response = client().admin().cluster().nodesStats(new NodesStatsRequest().http(true)).actionGet(); + assertThat(response.getNodes(), hasSize(1)); + } + +} From ee22a477df841d2c7087674d5389b3adacc1701b Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Mon, 31 Oct 2016 16:21:38 -0600 Subject: [PATCH 4/5] Add internal _primary_term doc values field, fix _seq_no indexing This adds the `_primary_term` field internally to the mappings. This field is populated with the current shard's primary term. It is intended to be used for collision resolution when two document copies have the same sequence id, therefore, doc_values for the field are stored but the filed itself is not indexed. This also fixes the `_seq_no` field so that doc_values are retrievable (they were previously stored but irretrievable) and changes the `stats` implementation to more efficiently use the points API to retrieve the min/max instead of iterating on each doc_value value. Additionally, even though we intend to be able to search on the field, it was previously not searchable. This commit makes it searchable. There is no user-visible `_primary_term` field. Instead, the fields are updated by calling: ```java index.parsedDoc().updateSeqID(seqNum, primaryTerm); ``` This includes example methods in `Versions` and `Engine` for retrieving the sequence id values from the index (see `Engine.getSequenceID`) that are only used in unit tests. These will be extended/replaced by actual implementations once we make use of sequence numbers as a conflict resolution measure. Relates to #10708 Supercedes #21480 P.S. As a side effect of this commit, `SlowCompositeReaderWrapper` cannot be used for documents that contain `_seq_no` because it is a Point value and SCRW cannot wrap documents with points, so the tests have been updated to loop through the `LeafReaderContext`s now instead. --- .../action/delete/TransportDeleteAction.java | 4 +- .../action/index/TransportIndexAction.java | 1 - .../common/lucene/uid/Versions.java | 122 +++++++ .../elasticsearch/index/engine/Engine.java | 28 +- .../index/engine/InternalEngine.java | 10 + .../index/mapper/DocumentParser.java | 2 +- .../index/mapper/ParseContext.java | 24 +- .../index/mapper/ParsedDocument.java | 28 +- .../index/mapper/SeqNoFieldMapper.java | 298 ++++++++++++++++++ .../mapper/internal/SeqNoFieldMapper.java | 197 ------------ .../elasticsearch/index/shard/IndexShard.java | 27 +- .../shard/TranslogRecoveryPerformer.java | 7 +- .../index/translog/Translog.java | 29 +- .../elasticsearch/indices/IndicesModule.java | 2 +- .../index/IndexingSlowLogTests.java | 3 +- .../index/engine/InternalEngineTests.java | 249 +++++++++------ .../index/engine/ShadowEngineTests.java | 10 +- .../AbstractFieldDataImplTestCase.java | 184 ++++++----- .../fielddata/AbstractFieldDataTestCase.java | 37 +-- .../AbstractStringFieldDataTestCase.java | 57 ++-- .../fielddata/BinaryDVFieldDataTests.java | 39 +-- .../index/fielddata/FilterFieldDataTests.java | 49 +-- .../index/fielddata/GeoFieldDataTests.java | 64 ++-- .../fielddata/ParentChildFieldDataTests.java | 63 ++-- .../mapper/FieldNamesFieldMapperTests.java | 4 +- .../index/shard/IndexShardIT.java | 10 +- .../index/shard/IndexShardTests.java | 8 +- .../index/shard/RefreshListenersTests.java | 8 +- .../index/translog/TranslogTests.java | 9 +- .../PercolatorFieldMapperTests.java | 6 +- 30 files changed, 979 insertions(+), 600 deletions(-) create mode 100644 core/src/main/java/org/elasticsearch/index/mapper/SeqNoFieldMapper.java delete mode 100644 core/src/main/java/org/elasticsearch/index/mapper/internal/SeqNoFieldMapper.java diff --git a/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java b/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java index d0458362fdd..81f341090a5 100644 --- a/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java +++ b/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java @@ -156,8 +156,8 @@ public class TransportDeleteAction extends TransportWriteAction leaves = reader.leaves(); + if (leaves.isEmpty()) { + return SequenceNumbersService.UNASSIGNED_SEQ_NO; + } + + // iterate backwards to optimize for the frequently updated documents + // which are likely to be in the last segments + for (int i = leaves.size() - 1; i >= 0; i--) { + LeafReader leaf = leaves.get(i).reader(); + Bits liveDocs = leaf.getLiveDocs(); + + TermsEnum termsEnum = null; + SortedNumericDocValues dvField = null; + PostingsEnum docsEnum = null; + + final Fields fields = leaf.fields(); + if (fields != null) { + Terms terms = fields.terms(UidFieldMapper.NAME); + if (terms != null) { + termsEnum = terms.iterator(); + assert termsEnum != null; + dvField = leaf.getSortedNumericDocValues(SeqNoFieldMapper.NAME); + assert dvField != null; + + final BytesRef id = term.bytes(); + if (termsEnum.seekExact(id)) { + // there may be more than one matching docID, in the + // case of nested docs, so we want the last one: + docsEnum = termsEnum.postings(docsEnum, 0); + int docID = DocIdSetIterator.NO_MORE_DOCS; + for (int d = docsEnum.nextDoc(); d != DocIdSetIterator.NO_MORE_DOCS; d = docsEnum.nextDoc()) { + if (liveDocs != null && liveDocs.get(d) == false) { + continue; + } + docID = d; + } + + if (docID != DocIdSetIterator.NO_MORE_DOCS) { + dvField.setDocument(docID); + assert dvField.count() == 1 : "expected only a single value for _seq_no but got " + + dvField.count(); + return dvField.valueAt(0); + } + } + } + } + + } + return SequenceNumbersService.UNASSIGNED_SEQ_NO; + } + + /** + * Returns the primary term for the given uid term, returning {@code 0} if none is found. + */ + public static long loadPrimaryTerm(IndexReader reader, Term term) throws IOException { + assert term.field().equals(UidFieldMapper.NAME) : "can only load _primary_term by uid"; + List leaves = reader.leaves(); + if (leaves.isEmpty()) { + return 0; + } + + // iterate backwards to optimize for the frequently updated documents + // which are likely to be in the last segments + for (int i = leaves.size() - 1; i >= 0; i--) { + LeafReader leaf = leaves.get(i).reader(); + Bits liveDocs = leaf.getLiveDocs(); + + TermsEnum termsEnum = null; + NumericDocValues dvField = null; + PostingsEnum docsEnum = null; + + final Fields fields = leaf.fields(); + if (fields != null) { + Terms terms = fields.terms(UidFieldMapper.NAME); + if (terms != null) { + termsEnum = terms.iterator(); + assert termsEnum != null; + dvField = leaf.getNumericDocValues(SeqNoFieldMapper.PRIMARY_TERM_NAME); + assert dvField != null; + + final BytesRef id = term.bytes(); + if (termsEnum.seekExact(id)) { + // there may be more than one matching docID, in the + // case of nested docs, so we want the last one: + docsEnum = termsEnum.postings(docsEnum, 0); + int docID = DocIdSetIterator.NO_MORE_DOCS; + for (int d = docsEnum.nextDoc(); d != DocIdSetIterator.NO_MORE_DOCS; d = docsEnum.nextDoc()) { + if (liveDocs != null && liveDocs.get(d) == false) { + continue; + } + docID = d; + } + + if (docID != DocIdSetIterator.NO_MORE_DOCS) { + return dvField.get(docID); + } + } + } + } + + } + return 0; + } } diff --git a/core/src/main/java/org/elasticsearch/index/engine/Engine.java b/core/src/main/java/org/elasticsearch/index/engine/Engine.java index 20def3bd893..0f1c05e59ee 100644 --- a/core/src/main/java/org/elasticsearch/index/engine/Engine.java +++ b/core/src/main/java/org/elasticsearch/index/engine/Engine.java @@ -47,6 +47,7 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; @@ -925,13 +926,15 @@ public abstract class Engine implements Closeable { private final Term uid; private final long version; private final long seqNo; + private final long primaryTerm; private final VersionType versionType; private final Origin origin; private final long startTime; - public Operation(Term uid, long seqNo, long version, VersionType versionType, Origin origin, long startTime) { + public Operation(Term uid, long seqNo, long primaryTerm, long version, VersionType versionType, Origin origin, long startTime) { this.uid = uid; this.seqNo = seqNo; + this.primaryTerm = primaryTerm; this.version = version; this.versionType = versionType; this.origin = origin; @@ -965,6 +968,10 @@ public abstract class Engine implements Closeable { return seqNo; } + public long primaryTerm() { + return primaryTerm; + } + public abstract int estimatedSizeInBytes(); public VersionType versionType() { @@ -991,9 +998,9 @@ public abstract class Engine implements Closeable { private final long autoGeneratedIdTimestamp; private final boolean isRetry; - public Index(Term uid, ParsedDocument doc, long seqNo, long version, VersionType versionType, Origin origin, long startTime, - long autoGeneratedIdTimestamp, boolean isRetry) { - super(uid, seqNo, version, versionType, origin, startTime); + public Index(Term uid, ParsedDocument doc, long seqNo, long primaryTerm, long version, VersionType versionType, Origin origin, + long startTime, long autoGeneratedIdTimestamp, boolean isRetry) { + super(uid, seqNo, primaryTerm, version, versionType, origin, startTime); this.doc = doc; this.isRetry = isRetry; this.autoGeneratedIdTimestamp = autoGeneratedIdTimestamp; @@ -1004,7 +1011,8 @@ public abstract class Engine implements Closeable { } // TEST ONLY Index(Term uid, ParsedDocument doc, long version) { - this(uid, doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, version, VersionType.INTERNAL, Origin.PRIMARY, System.nanoTime(), -1, false); + this(uid, doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, version, VersionType.INTERNAL, + Origin.PRIMARY, System.nanoTime(), -1, false); } public ParsedDocument parsedDoc() { @@ -1071,18 +1079,20 @@ public abstract class Engine implements Closeable { private final String type; private final String id; - public Delete(String type, String id, Term uid, long seqNo, long version, VersionType versionType, Origin origin, long startTime) { - super(uid, seqNo, version, versionType, origin, startTime); + public Delete(String type, String id, Term uid, long seqNo, long primaryTerm, long version, VersionType versionType, + Origin origin, long startTime) { + super(uid, seqNo, primaryTerm, version, versionType, origin, startTime); this.type = type; this.id = id; } public Delete(String type, String id, Term uid) { - this(type, id, uid, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, Origin.PRIMARY, System.nanoTime()); + this(type, id, uid, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, Origin.PRIMARY, System.nanoTime()); } public Delete(Delete template, VersionType versionType) { - this(template.type(), template.id(), template.uid(), template.seqNo(), template.version(), versionType, template.origin(), template.startTime()); + this(template.type(), template.id(), template.uid(), template.seqNo(), template.primaryTerm(), template.version(), + versionType, template.origin(), template.startTime()); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/engine/InternalEngine.java b/core/src/main/java/org/elasticsearch/index/engine/InternalEngine.java index c142601a6df..98e8484b183 100644 --- a/core/src/main/java/org/elasticsearch/index/engine/InternalEngine.java +++ b/core/src/main/java/org/elasticsearch/index/engine/InternalEngine.java @@ -650,6 +650,16 @@ public class InternalEngine extends Engine { } updatedVersion = index.versionType().updateVersion(currentVersion, expectedVersion); index.parsedDoc().version().setLongValue(updatedVersion); + + // Update the document's sequence number and primary term, the + // sequence number here is derived here from either the sequence + // number service if this is on the primary, or the existing + // document's sequence number if this is on the replica. The + // primary term here has already been set, see + // IndexShard.prepareIndex where the Engine.Index operation is + // created + index.parsedDoc().updateSeqID(seqNo, index.primaryTerm()); + if (currentVersion == Versions.NOT_FOUND && forceUpdateDocument == false) { // document does not exists, we can optimize for create, but double check if assertions are running assert assertDocDoesNotExist(index, canOptimizeAddDocument == false); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index 324b34fef9c..72d021c0e3e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -148,7 +148,7 @@ final class DocumentParser { private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.InternalParseContext context, Mapping update) { return new ParsedDocument( context.version(), - context.seqNo(), + context.seqID(), context.sourceToParse().id(), context.sourceToParse().type(), source.routing(), diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java index 2f5f1135b13..ad21cce6674 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java @@ -29,6 +29,7 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.all.AllEntries; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import java.util.ArrayList; import java.util.Iterator; @@ -254,13 +255,13 @@ public abstract class ParseContext { } @Override - public Field seqNo() { - return in.seqNo(); + public SeqNoFieldMapper.SequenceID seqID() { + return in.seqID(); } @Override - public void seqNo(Field seqNo) { - in.seqNo(seqNo); + public void seqID(SeqNoFieldMapper.SequenceID seqID) { + in.seqID(seqID); } @Override @@ -310,7 +311,7 @@ public abstract class ParseContext { private Field version; - private Field seqNo; + private SeqNoFieldMapper.SequenceID seqID; private final AllEntries allEntries; @@ -404,16 +405,15 @@ public abstract class ParseContext { } @Override - public Field seqNo() { - return this.seqNo; + public SeqNoFieldMapper.SequenceID seqID() { + return this.seqID; } @Override - public void seqNo(Field seqNo) { - this.seqNo = seqNo; + public void seqID(SeqNoFieldMapper.SequenceID seqID) { + this.seqID = seqID; } - @Override public AllEntries allEntries() { return this.allEntries; @@ -540,9 +540,9 @@ public abstract class ParseContext { public abstract void version(Field version); - public abstract Field seqNo(); + public abstract SeqNoFieldMapper.SequenceID seqID(); - public abstract void seqNo(Field seqNo); + public abstract void seqID(SeqNoFieldMapper.SequenceID seqID); public final boolean includeInAll(Boolean includeInAll, FieldMapper mapper) { return includeInAll(includeInAll, mapper.fieldType().indexOptions() != IndexOptions.NONE); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ParsedDocument.java b/core/src/main/java/org/elasticsearch/index/mapper/ParsedDocument.java index eb42c3b9649..db8bdf9df7f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ParsedDocument.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ParsedDocument.java @@ -23,6 +23,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.index.mapper.ParseContext.Document; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import java.util.List; @@ -35,7 +36,7 @@ public class ParsedDocument { private final String id, type; private final BytesRef uid; - private final Field seqNo; + private final SeqNoFieldMapper.SequenceID seqID; private final String routing; @@ -47,17 +48,16 @@ public class ParsedDocument { private String parent; - public ParsedDocument( - Field version, - Field seqNo, - String id, - String type, - String routing, - List documents, - BytesReference source, - Mapping dynamicMappingsUpdate) { + public ParsedDocument(Field version, + SeqNoFieldMapper.SequenceID seqID, + String id, + String type, + String routing, + List documents, + BytesReference source, + Mapping dynamicMappingsUpdate) { this.version = version; - this.seqNo = seqNo; + this.seqID = seqID; this.id = id; this.type = type; this.uid = Uid.createUidAsBytes(type, id); @@ -83,8 +83,10 @@ public class ParsedDocument { return version; } - public Field seqNo() { - return seqNo; + public void updateSeqID(long sequenceNumber, long primaryTerm) { + this.seqID.seqNo.setLongValue(sequenceNumber); + this.seqID.seqNoDocValue.setLongValue(sequenceNumber); + this.seqID.primaryTerm.setLongValue(primaryTerm); } public String routing() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/SeqNoFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/SeqNoFieldMapper.java new file mode 100644 index 00000000000..5820519af7f --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/mapper/SeqNoFieldMapper.java @@ -0,0 +1,298 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.mapper; + +import org.apache.lucene.document.Field; +import org.apache.lucene.document.LongPoint; +import org.apache.lucene.document.NumericDocValuesField; +import org.apache.lucene.document.SortedNumericDocValuesField; +import org.apache.lucene.index.DocValuesType; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.LeafReader; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.PointValues; +import org.apache.lucene.search.BoostQuery; +import org.apache.lucene.search.MatchNoDocsQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.util.Bits; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.action.fieldstats.FieldStats; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.fielddata.IndexFieldData; +import org.elasticsearch.index.fielddata.IndexNumericFieldData.NumericType; +import org.elasticsearch.index.fielddata.plain.DocValuesIndexFieldData; +import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.Mapper; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MetadataFieldMapper; +import org.elasticsearch.index.mapper.ParseContext; +import org.elasticsearch.index.mapper.ParseContext.Document; +import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.index.query.QueryShardException; +import org.elasticsearch.index.seqno.SequenceNumbersService; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Mapper for the {@code _seq_no} field. + * + * We expect to use the seq# for sorting, during collision checking and for + * doing range searches. Therefore the {@code _seq_no} field is stored both + * as a numeric doc value and as numeric indexed field. + * + * This mapper also manages the primary term field, which has no ES named + * equivalent. The primary term is only used during collision after receiving + * identical seq# values for two document copies. The primary term is stored as + * a doc value field without being indexed, since it is only intended for use + * as a key-value lookup. + + */ +public class SeqNoFieldMapper extends MetadataFieldMapper { + + /** + * A sequence ID, which is made up of a sequence number (both the searchable + * and doc_value version of the field) and the primary term. + */ + public static class SequenceID { + + public final Field seqNo; + public final Field seqNoDocValue; + public final Field primaryTerm; + + public SequenceID(Field seqNo, Field seqNoDocValue, Field primaryTerm) { + Objects.requireNonNull(seqNo, "sequence number field cannot be null"); + Objects.requireNonNull(seqNoDocValue, "sequence number dv field cannot be null"); + Objects.requireNonNull(primaryTerm, "primary term field cannot be null"); + this.seqNo = seqNo; + this.seqNoDocValue = seqNoDocValue; + this.primaryTerm = primaryTerm; + } + + public static SequenceID emptySeqID() { + return new SequenceID(new LongPoint(NAME, SequenceNumbersService.UNASSIGNED_SEQ_NO), + new SortedNumericDocValuesField(NAME, SequenceNumbersService.UNASSIGNED_SEQ_NO), + new NumericDocValuesField(PRIMARY_TERM_NAME, 0)); + } + } + + public static final String NAME = "_seq_no"; + public static final String CONTENT_TYPE = "_seq_no"; + public static final String PRIMARY_TERM_NAME = "_primary_term"; + + public static class SeqNoDefaults { + public static final String NAME = SeqNoFieldMapper.NAME; + public static final MappedFieldType FIELD_TYPE = new SeqNoFieldType(); + + static { + FIELD_TYPE.setName(NAME); + FIELD_TYPE.setDocValuesType(DocValuesType.SORTED); + FIELD_TYPE.setHasDocValues(true); + FIELD_TYPE.freeze(); + } + } + + public static class Builder extends MetadataFieldMapper.Builder { + + public Builder() { + super(SeqNoDefaults.NAME, SeqNoDefaults.FIELD_TYPE, SeqNoDefaults.FIELD_TYPE); + } + + @Override + public SeqNoFieldMapper build(BuilderContext context) { + return new SeqNoFieldMapper(context.indexSettings()); + } + } + + public static class TypeParser implements MetadataFieldMapper.TypeParser { + @Override + public MetadataFieldMapper.Builder parse(String name, Map node, ParserContext parserContext) + throws MapperParsingException { + throw new MapperParsingException(NAME + " is not configurable"); + } + + @Override + public MetadataFieldMapper getDefault(Settings indexSettings, MappedFieldType fieldType, String typeName) { + return new SeqNoFieldMapper(indexSettings); + } + } + + static final class SeqNoFieldType extends MappedFieldType { + + public SeqNoFieldType() { + } + + protected SeqNoFieldType(SeqNoFieldType ref) { + super(ref); + } + + @Override + public MappedFieldType clone() { + return new SeqNoFieldType(this); + } + + @Override + public String typeName() { + return CONTENT_TYPE; + } + + private long parse(Object value) { + if (value instanceof Number) { + double doubleValue = ((Number) value).doubleValue(); + if (doubleValue < Long.MIN_VALUE || doubleValue > Long.MAX_VALUE) { + throw new IllegalArgumentException("Value [" + value + "] is out of range for a long"); + } + if (doubleValue % 1 != 0) { + throw new IllegalArgumentException("Value [" + value + "] has a decimal part"); + } + return ((Number) value).longValue(); + } + if (value instanceof BytesRef) { + value = ((BytesRef) value).utf8ToString(); + } + return Long.parseLong(value.toString()); + } + + @Override + public Query termQuery(Object value, @Nullable QueryShardContext context) { + long v = parse(value); + return LongPoint.newExactQuery(name(), v); + } + + @Override + public Query termsQuery(List values, @Nullable QueryShardContext context) { + long[] v = new long[values.size()]; + for (int i = 0; i < values.size(); ++i) { + v[i] = parse(values.get(i)); + } + return LongPoint.newSetQuery(name(), v); + } + + @Override + public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, + boolean includeUpper, QueryShardContext context) { + long l = Long.MIN_VALUE; + long u = Long.MAX_VALUE; + if (lowerTerm != null) { + l = parse(lowerTerm); + if (includeLower == false) { + if (l == Long.MAX_VALUE) { + return new MatchNoDocsQuery(); + } + ++l; + } + } + if (upperTerm != null) { + u = parse(upperTerm); + if (includeUpper == false) { + if (u == Long.MIN_VALUE) { + return new MatchNoDocsQuery(); + } + --u; + } + } + return LongPoint.newRangeQuery(name(), l, u); + } + + @Override + public IndexFieldData.Builder fielddataBuilder() { + failIfNoDocValues(); + return new DocValuesIndexFieldData.Builder().numericType(NumericType.LONG); + } + + @Override + public FieldStats stats(IndexReader reader) throws IOException { + String fieldName = name(); + long size = PointValues.size(reader, fieldName); + if (size == 0) { + return null; + } + int docCount = PointValues.getDocCount(reader, fieldName); + byte[] min = PointValues.getMinPackedValue(reader, fieldName); + byte[] max = PointValues.getMaxPackedValue(reader, fieldName); + return new FieldStats.Long(reader.maxDoc(),docCount, -1L, size, true, false, + LongPoint.decodeDimension(min, 0), LongPoint.decodeDimension(max, 0)); + } + + } + + public SeqNoFieldMapper(Settings indexSettings) { + super(NAME, SeqNoDefaults.FIELD_TYPE, SeqNoDefaults.FIELD_TYPE, indexSettings); + } + + @Override + public void preParse(ParseContext context) throws IOException { + super.parse(context); + } + + @Override + protected void parseCreateField(ParseContext context, List fields) throws IOException { + // see InternalEngine.innerIndex to see where the real version value is set + // also see ParsedDocument.updateSeqID (called by innerIndex) + SequenceID seqID = SequenceID.emptySeqID(); + context.seqID(seqID); + fields.add(seqID.seqNo); + fields.add(seqID.seqNoDocValue); + fields.add(seqID.primaryTerm); + } + + @Override + public Mapper parse(ParseContext context) throws IOException { + // fields are added in parseCreateField + return null; + } + + @Override + public void postParse(ParseContext context) throws IOException { + // In the case of nested docs, let's fill nested docs with seqNo=1 and + // primaryTerm=0 so that Lucene doesn't write a Bitset for documents + // that don't have the field. This is consistent with the default value + // for efficiency. + for (int i = 1; i < context.docs().size(); i++) { + final Document doc = context.docs().get(i); + doc.add(new LongPoint(NAME, 1)); + doc.add(new SortedNumericDocValuesField(NAME, 1L)); + doc.add(new NumericDocValuesField(PRIMARY_TERM_NAME, 0L)); + } + } + + @Override + protected String contentType() { + return CONTENT_TYPE; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return builder; + } + + @Override + protected void doMerge(Mapper mergeWith, boolean updateAllTypes) { + // nothing to do + } + +} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/SeqNoFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/SeqNoFieldMapper.java deleted file mode 100644 index d94e05ae358..00000000000 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/SeqNoFieldMapper.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.index.mapper.internal; - -import org.apache.lucene.document.Field; -import org.apache.lucene.document.NumericDocValuesField; -import org.apache.lucene.index.DocValuesType; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexableField; -import org.apache.lucene.index.LeafReader; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.index.NumericDocValues; -import org.apache.lucene.search.Query; -import org.apache.lucene.util.Bits; -import org.elasticsearch.action.fieldstats.FieldStats; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.Mapper; -import org.elasticsearch.index.mapper.MapperParsingException; -import org.elasticsearch.index.mapper.MetadataFieldMapper; -import org.elasticsearch.index.mapper.ParseContext; -import org.elasticsearch.index.mapper.ParseContext.Document; -import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.query.QueryShardException; -import org.elasticsearch.index.seqno.SequenceNumbersService; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** Mapper for the _seq_no field. */ -public class SeqNoFieldMapper extends MetadataFieldMapper { - - public static final String NAME = "_seq_no"; - public static final String CONTENT_TYPE = "_seq_no"; - - public static class Defaults { - - public static final String NAME = SeqNoFieldMapper.NAME; - public static final MappedFieldType FIELD_TYPE = new SeqNoFieldType(); - - static { - FIELD_TYPE.setName(NAME); - FIELD_TYPE.setDocValuesType(DocValuesType.NUMERIC); - FIELD_TYPE.setHasDocValues(true); - FIELD_TYPE.freeze(); - } - } - - public static class Builder extends MetadataFieldMapper.Builder { - - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE); - } - - @Override - public SeqNoFieldMapper build(BuilderContext context) { - return new SeqNoFieldMapper(context.indexSettings()); - } - } - - public static class TypeParser implements MetadataFieldMapper.TypeParser { - @Override - public MetadataFieldMapper.Builder parse(String name, Map node, ParserContext parserContext) - throws MapperParsingException { - throw new MapperParsingException(NAME + " is not configurable"); - } - - @Override - public MetadataFieldMapper getDefault(Settings indexSettings, MappedFieldType fieldType, String typeName) { - return new SeqNoFieldMapper(indexSettings); - } - } - - static final class SeqNoFieldType extends MappedFieldType { - - public SeqNoFieldType() { - } - - protected SeqNoFieldType(SeqNoFieldType ref) { - super(ref); - } - - @Override - public MappedFieldType clone() { - return new SeqNoFieldType(this); - } - - @Override - public String typeName() { - return CONTENT_TYPE; - } - - @Override - public Query termQuery(Object value, @Nullable QueryShardContext context) { - throw new QueryShardException(context, "SeqNoField field [" + name() + "] is not searchable"); - } - - @Override - public FieldStats stats(IndexReader reader) throws IOException { - // TODO: remove implementation when late-binding commits are possible - final List leaves = reader.leaves(); - if (leaves.isEmpty()) { - return null; - } - - long currentMin = Long.MAX_VALUE; - long currentMax = Long.MIN_VALUE; - boolean found = false; - for (int i = 0; i < leaves.size(); i++) { - final LeafReader leaf = leaves.get(i).reader(); - final NumericDocValues values = leaf.getNumericDocValues(name()); - if (values == null) continue; - final Bits bits = leaf.getLiveDocs(); - for (int docID = 0; docID < leaf.maxDoc(); docID++) { - if (bits == null || bits.get(docID)) { - found = true; - final long value = values.get(docID); - currentMin = Math.min(currentMin, value); - currentMax = Math.max(currentMax, value); - } - } - } - - return found ? new FieldStats.Long(reader.maxDoc(), 0, -1, -1, false, true, currentMin, currentMax) : null; - } - - } - - public SeqNoFieldMapper(Settings indexSettings) { - super(NAME, Defaults.FIELD_TYPE, Defaults.FIELD_TYPE, indexSettings); - } - - @Override - public void preParse(ParseContext context) throws IOException { - super.parse(context); - } - - @Override - protected void parseCreateField(ParseContext context, List fields) throws IOException { - // see InternalEngine.updateVersion to see where the real version value is set - final Field seqNo = new NumericDocValuesField(NAME, SequenceNumbersService.UNASSIGNED_SEQ_NO); - context.seqNo(seqNo); - fields.add(seqNo); - } - - @Override - public Mapper parse(ParseContext context) throws IOException { - // _seq_no added in pre-parse - return null; - } - - @Override - public void postParse(ParseContext context) throws IOException { - // In the case of nested docs, let's fill nested docs with seqNo=1 so that Lucene doesn't write a Bitset for documents - // that don't have the field. This is consistent with the default value for efficiency. - for (int i = 1; i < context.docs().size(); i++) { - final Document doc = context.docs().get(i); - doc.add(new NumericDocValuesField(NAME, 1L)); - } - } - - @Override - protected String contentType() { - return CONTENT_TYPE; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder; - } - - @Override - protected void doMerge(Mapper mergeWith, boolean updateAllTypes) { - // nothing to do - } - -} diff --git a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java index 613fec5523c..ff8a41fcb94 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -510,7 +510,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl boolean isRetry) { try { verifyPrimary(); - return prepareIndex(docMapper(source.type()), source, SequenceNumbersService.UNASSIGNED_SEQ_NO, version, versionType, + return prepareIndex(docMapper(source.type()), source, SequenceNumbersService.UNASSIGNED_SEQ_NO, primaryTerm, version, versionType, Engine.Operation.Origin.PRIMARY, autoGeneratedIdTimestamp, isRetry); } catch (Exception e) { verifyNotClosed(e); @@ -522,16 +522,17 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl boolean isRetry) { try { verifyReplicationTarget(); - return prepareIndex(docMapper(source.type()), source, seqNo, version, versionType, Engine.Operation.Origin.REPLICA, autoGeneratedIdTimestamp, - isRetry); + return prepareIndex(docMapper(source.type()), source, seqNo, primaryTerm, version, versionType, + Engine.Operation.Origin.REPLICA, autoGeneratedIdTimestamp, isRetry); } catch (Exception e) { verifyNotClosed(e); throw e; } } - static Engine.Index prepareIndex(DocumentMapperForType docMapper, SourceToParse source, long seqNo, long version, VersionType versionType, - Engine.Operation.Origin origin, long autoGeneratedIdTimestamp, boolean isRetry) { + static Engine.Index prepareIndex(DocumentMapperForType docMapper, SourceToParse source, long seqNo, long primaryTerm, long version, + VersionType versionType, Engine.Operation.Origin origin, long autoGeneratedIdTimestamp, + boolean isRetry) { long startTime = System.nanoTime(); ParsedDocument doc = docMapper.getDocumentMapper().parse(source); if (docMapper.getMapping() != null) { @@ -540,8 +541,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl MappedFieldType uidFieldType = docMapper.getDocumentMapper().uidMapper().fieldType(); Query uidQuery = uidFieldType.termQuery(doc.uid(), null); Term uid = MappedFieldType.extractTerm(uidQuery); - doc.seqNo().setLongValue(seqNo); - return new Engine.Index(uid, doc, seqNo, version, versionType, origin, startTime, autoGeneratedIdTimestamp, isRetry); + return new Engine.Index(uid, doc, seqNo, primaryTerm, version, versionType, origin, startTime, autoGeneratedIdTimestamp, isRetry); } public Engine.IndexResult index(Engine.Index index) { @@ -573,21 +573,24 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl final MappedFieldType uidFieldType = documentMapper.uidMapper().fieldType(); final Query uidQuery = uidFieldType.termQuery(Uid.createUid(type, id), null); final Term uid = MappedFieldType.extractTerm(uidQuery); - return prepareDelete(type, id, uid, SequenceNumbersService.UNASSIGNED_SEQ_NO, version, versionType, Engine.Operation.Origin.PRIMARY); + return prepareDelete(type, id, uid, SequenceNumbersService.UNASSIGNED_SEQ_NO, primaryTerm, version, + versionType, Engine.Operation.Origin.PRIMARY); } - public Engine.Delete prepareDeleteOnReplica(String type, String id, long seqNo, long version, VersionType versionType) { + public Engine.Delete prepareDeleteOnReplica(String type, String id, long seqNo, long primaryTerm, + long version, VersionType versionType) { verifyReplicationTarget(); final DocumentMapper documentMapper = docMapper(type).getDocumentMapper(); final MappedFieldType uidFieldType = documentMapper.uidMapper().fieldType(); final Query uidQuery = uidFieldType.termQuery(Uid.createUid(type, id), null); final Term uid = MappedFieldType.extractTerm(uidQuery); - return prepareDelete(type, id, uid, seqNo, version, versionType, Engine.Operation.Origin.REPLICA); + return prepareDelete(type, id, uid, seqNo, primaryTerm, version, versionType, Engine.Operation.Origin.REPLICA); } - static Engine.Delete prepareDelete(String type, String id, Term uid, long seqNo, long version, VersionType versionType, Engine.Operation.Origin origin) { + static Engine.Delete prepareDelete(String type, String id, Term uid, long seqNo, long primaryTerm, long version, + VersionType versionType, Engine.Operation.Origin origin) { long startTime = System.nanoTime(); - return new Engine.Delete(type, id, uid, seqNo, version, versionType, origin, startTime); + return new Engine.Delete(type, id, uid, seqNo, primaryTerm, version, versionType, origin, startTime); } public Engine.DeleteResult delete(Engine.Delete delete) { diff --git a/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java b/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java index 7dd5cebcb2c..f27958b71f5 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java +++ b/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java @@ -155,8 +155,8 @@ public class TranslogRecoveryPerformer { // we set canHaveDuplicates to true all the time such that we de-optimze the translog case and ensure that all // autoGeneratedID docs that are coming from the primary are updated correctly. Engine.Index engineIndex = IndexShard.prepareIndex(docMapper(index.type()), source(shardId.getIndexName(), index.type(), index.id(), index.source()) - .routing(index.routing()).parent(index.parent()), index.seqNo(), - index.version(), index.versionType().versionTypeForReplicationAndRecovery(), origin, index.getAutoGeneratedIdTimestamp(), true); + .routing(index.routing()).parent(index.parent()), index.seqNo(), index.primaryTerm(), + index.version(), index.versionType().versionTypeForReplicationAndRecovery(), origin, index.getAutoGeneratedIdTimestamp(), true); maybeAddMappingUpdate(engineIndex.type(), engineIndex.parsedDoc().dynamicMappingsUpdate(), engineIndex.id(), allowMappingUpdates); if (logger.isTraceEnabled()) { logger.trace("[translog] recover [index] op of [{}][{}]", index.type(), index.id()); @@ -170,7 +170,8 @@ public class TranslogRecoveryPerformer { logger.trace("[translog] recover [delete] op of [{}][{}]", uid.type(), uid.id()); } final Engine.Delete engineDelete = new Engine.Delete(uid.type(), uid.id(), delete.uid(), delete.seqNo(), - delete.version(), delete.versionType().versionTypeForReplicationAndRecovery(), origin, System.nanoTime()); + delete.primaryTerm(), delete.version(), delete.versionType().versionTypeForReplicationAndRecovery(), + origin, System.nanoTime()); delete(engine, engineDelete); break; default: diff --git a/core/src/main/java/org/elasticsearch/index/translog/Translog.java b/core/src/main/java/org/elasticsearch/index/translog/Translog.java index 92220fa1922..f7560960660 100644 --- a/core/src/main/java/org/elasticsearch/index/translog/Translog.java +++ b/core/src/main/java/org/elasticsearch/index/translog/Translog.java @@ -825,6 +825,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC private final long autoGeneratedIdTimestamp; private final String type; private long seqNo = SequenceNumbersService.UNASSIGNED_SEQ_NO; + private long primaryTerm = 0; private final long version; private final VersionType versionType; private final BytesReference source; @@ -853,6 +854,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC } if (format >= FORMAT_SEQ_NO) { seqNo = in.readVLong(); + primaryTerm = in.readVLong(); } } @@ -863,6 +865,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC this.routing = index.routing(); this.parent = index.parent(); this.seqNo = indexResult.getSeqNo(); + this.primaryTerm = index.primaryTerm(); this.version = indexResult.getVersion(); this.versionType = index.versionType(); this.autoGeneratedIdTimestamp = index.getAutoGeneratedIdTimestamp(); @@ -914,6 +917,10 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC return seqNo; } + public long primaryTerm() { + return primaryTerm; + } + public long version() { return this.version; } @@ -940,6 +947,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC out.writeByte(versionType.getValue()); out.writeLong(autoGeneratedIdTimestamp); out.writeVLong(seqNo); + out.writeVLong(primaryTerm); } @Override @@ -955,6 +963,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC if (version != index.version || seqNo != index.seqNo || + primaryTerm != index.primaryTerm || id.equals(index.id) == false || type.equals(index.type) == false || versionType != index.versionType || @@ -974,6 +983,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC int result = id.hashCode(); result = 31 * result + type.hashCode(); result = 31 * result + Long.hashCode(seqNo); + result = 31 * result + Long.hashCode(primaryTerm); result = 31 * result + Long.hashCode(version); result = 31 * result + versionType.hashCode(); result = 31 * result + source.hashCode(); @@ -1003,6 +1013,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC private Term uid; private long seqNo = SequenceNumbersService.UNASSIGNED_SEQ_NO; + private long primaryTerm = 0; private long version = Versions.MATCH_ANY; private VersionType versionType = VersionType.INTERNAL; @@ -1015,21 +1026,23 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC assert versionType.validateVersionForWrites(this.version); if (format >= FORMAT_SEQ_NO) { seqNo = in.readVLong(); + primaryTerm = in.readVLong(); } } public Delete(Engine.Delete delete, Engine.DeleteResult deleteResult) { - this(delete.uid(), deleteResult.getSeqNo(), deleteResult.getVersion(), delete.versionType()); + this(delete.uid(), deleteResult.getSeqNo(), delete.primaryTerm(), deleteResult.getVersion(), delete.versionType()); } /** utility for testing */ public Delete(Term uid) { - this(uid, 0, Versions.MATCH_ANY, VersionType.INTERNAL); + this(uid, 0, 0, Versions.MATCH_ANY, VersionType.INTERNAL); } - public Delete(Term uid, long seqNo, long version, VersionType versionType) { + public Delete(Term uid, long seqNo, long primaryTerm, long version, VersionType versionType) { this.uid = uid; this.seqNo = seqNo; + this.primaryTerm = primaryTerm; this.version = version; this.versionType = versionType; } @@ -1052,6 +1065,10 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC return seqNo; } + public long primaryTerm() { + return primaryTerm; + } + public long version() { return this.version; } @@ -1073,6 +1090,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC out.writeLong(version); out.writeByte(versionType.getValue()); out.writeVLong(seqNo); + out.writeVLong(primaryTerm); } @Override @@ -1086,7 +1104,9 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC Delete delete = (Delete) o; - return version == delete.version && seqNo == delete.seqNo && + return version == delete.version && + seqNo == delete.seqNo && + primaryTerm == delete.primaryTerm && uid.equals(delete.uid) && versionType == delete.versionType; } @@ -1095,6 +1115,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC public int hashCode() { int result = uid.hashCode(); result = 31 * result + Long.hashCode(seqNo); + result = 31 * result + Long.hashCode(primaryTerm); result = 31 * result + Long.hashCode(version); result = 31 * result + versionType.hashCode(); return result; diff --git a/core/src/main/java/org/elasticsearch/indices/IndicesModule.java b/core/src/main/java/org/elasticsearch/indices/IndicesModule.java index 7e701ff28c0..c53b278e8af 100644 --- a/core/src/main/java/org/elasticsearch/indices/IndicesModule.java +++ b/core/src/main/java/org/elasticsearch/indices/IndicesModule.java @@ -45,13 +45,13 @@ import org.elasticsearch.index.mapper.ParentFieldMapper; import org.elasticsearch.index.mapper.RangeFieldMapper; import org.elasticsearch.index.mapper.RoutingFieldMapper; import org.elasticsearch.index.mapper.ScaledFloatFieldMapper; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.index.mapper.TokenCountFieldMapper; import org.elasticsearch.index.mapper.TypeFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; import org.elasticsearch.index.mapper.VersionFieldMapper; -import org.elasticsearch.index.mapper.internal.SeqNoFieldMapper; import org.elasticsearch.index.seqno.GlobalCheckpointSyncAction; import org.elasticsearch.indices.cluster.IndicesClusterStateService; import org.elasticsearch.indices.flush.SyncedFlushService; diff --git a/core/src/test/java/org/elasticsearch/index/IndexingSlowLogTests.java b/core/src/test/java/org/elasticsearch/index/IndexingSlowLogTests.java index b068d00b6a2..16903a01d91 100644 --- a/core/src/test/java/org/elasticsearch/index/IndexingSlowLogTests.java +++ b/core/src/test/java/org/elasticsearch/index/IndexingSlowLogTests.java @@ -28,6 +28,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.index.IndexingSlowLog.SlowLogParsedDocumentPrinter; import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.test.ESTestCase; import java.io.IOException; @@ -39,7 +40,7 @@ import static org.hamcrest.Matchers.startsWith; public class IndexingSlowLogTests extends ESTestCase { public void testSlowLogParsedDocumentPrinterSourceToLog() throws IOException { BytesReference source = JsonXContent.contentBuilder().startObject().field("foo", "bar").endObject().bytes(); - ParsedDocument pd = new ParsedDocument(new NumericDocValuesField("version", 1), new NumericDocValuesField("seqNo", 1), "id", + ParsedDocument pd = new ParsedDocument(new NumericDocValuesField("version", 1), SeqNoFieldMapper.SequenceID.emptySeqID(), "id", "test", null, null, source, null); Index index = new Index("foo", "123"); // Turning off document logging doesn't log source[] diff --git a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java index 2be63bc2f2b..340ea745aae 100644 --- a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java +++ b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java @@ -31,6 +31,7 @@ import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.codecs.Codec; import org.apache.lucene.document.Field; +import org.apache.lucene.document.LongPoint; import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.CorruptIndexException; @@ -75,7 +76,9 @@ import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.FileSystemUtils; +import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.lucene.uid.Versions; @@ -100,9 +103,9 @@ import org.elasticsearch.index.mapper.MetadataFieldMapper; import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.RootObjectMapper; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; -import org.elasticsearch.index.mapper.internal.SeqNoFieldMapper; import org.elasticsearch.index.seqno.SequenceNumbersService; import org.elasticsearch.index.shard.DocsStats; import org.elasticsearch.index.shard.IndexSearcherWrapper; @@ -268,11 +271,13 @@ public class InternalEngineTests extends ESTestCase { private ParsedDocument testParsedDocument(String uid, String id, String type, String routing, Document document, BytesReference source, Mapping mappingUpdate) { Field uidField = new Field("_uid", uid, UidFieldMapper.Defaults.FIELD_TYPE); Field versionField = new NumericDocValuesField("_version", 0); - Field seqNoField = new NumericDocValuesField("_seq_no", 0); + SeqNoFieldMapper.SequenceID seqID = SeqNoFieldMapper.SequenceID.emptySeqID(); document.add(uidField); document.add(versionField); - document.add(seqNoField); - return new ParsedDocument(versionField, seqNoField, id, type, routing, Arrays.asList(document), source, mappingUpdate); + document.add(seqID.seqNo); + document.add(seqID.seqNoDocValue); + document.add(seqID.primaryTerm); + return new ParsedDocument(versionField, seqID, id, type, routing, Arrays.asList(document), source, mappingUpdate); } protected Store createStore() throws IOException { @@ -708,11 +713,11 @@ public class InternalEngineTests extends ESTestCase { for (int i = 0; i < ops; i++) { final ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocumentWithTextField(), SOURCE, null); if (randomBoolean()) { - final Engine.Index operation = new Engine.Index(newUid("test#1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, i, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); + final Engine.Index operation = new Engine.Index(newUid("test#1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, i, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); operations.add(operation); initialEngine.index(operation); } else { - final Engine.Delete operation = new Engine.Delete("test", "1", newUid("test#1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, i, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime()); + final Engine.Delete operation = new Engine.Delete("test", "1", newUid("test#1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, i, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime()); operations.add(operation); initialEngine.delete(operation); } @@ -1039,7 +1044,7 @@ public class InternalEngineTests extends ESTestCase { engine.flush(); final boolean forceMergeFlushes = randomBoolean(); if (forceMergeFlushes) { - engine.index(new Engine.Index(newUid("3"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime() - engine.engineConfig.getFlushMergesAfter().nanos(), -1, false)); + engine.index(new Engine.Index(newUid("3"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime() - engine.engineConfig.getFlushMergesAfter().nanos(), -1, false)); } else { engine.index(new Engine.Index(newUid("3"), doc)); } @@ -1126,7 +1131,7 @@ public class InternalEngineTests extends ESTestCase { Engine.IndexResult indexResult = engine.index(create); assertThat(indexResult.getVersion(), equalTo(1L)); - create = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), create.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + create = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), create.primaryTerm(), indexResult.getVersion(), create.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(create); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -1137,18 +1142,18 @@ public class InternalEngineTests extends ESTestCase { Engine.IndexResult indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); } public void testExternalVersioningNewIndex() { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(12L)); - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(12L)); } @@ -1163,13 +1168,13 @@ public class InternalEngineTests extends ESTestCase { indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(2L)); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 1L, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1L, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); // future versions should not work as well - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 3L, VersionType.INTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 3L, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1177,15 +1182,15 @@ public class InternalEngineTests extends ESTestCase { public void testExternalVersioningIndexConflict() { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(12L)); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 14, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 14, VersionType.EXTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(14L)); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 13, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 13, VersionType.EXTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1193,7 +1198,7 @@ public class InternalEngineTests extends ESTestCase { public void testForceVersioningNotAllowedExceptForOlderIndices() throws Exception { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 42, VersionType.FORCE, PRIMARY, 0, -1, false); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 42, VersionType.FORCE, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); @@ -1205,13 +1210,13 @@ public class InternalEngineTests extends ESTestCase { .build()); try (Store store = createStore(); Engine engine = createEngine(oldIndexSettings, store, createTempDir(), NoMergePolicy.INSTANCE)) { - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 84, VersionType.FORCE, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 84, VersionType.FORCE, PRIMARY, 0, -1, false); Engine.IndexResult result = engine.index(index); assertTrue(result.hasFailure()); assertThat(result.getFailure(), instanceOf(IllegalArgumentException.class)); assertThat(result.getFailure().getMessage(), containsString("version type [FORCE] may not be used for non-translog operations")); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 84, VersionType.FORCE, + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 84, VersionType.FORCE, Engine.Operation.Origin.LOCAL_TRANSLOG_RECOVERY, 0, -1, false); result = engine.index(index); assertThat(result.getVersion(), equalTo(84L)); @@ -1230,13 +1235,13 @@ public class InternalEngineTests extends ESTestCase { engine.flush(); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 1L, VersionType.INTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1L, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); // future versions should not work as well - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 3L, VersionType.INTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 3L, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1244,17 +1249,17 @@ public class InternalEngineTests extends ESTestCase { public void testExternalVersioningIndexConflictWithFlush() { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 12, VersionType.EXTERNAL, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(12L)); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 14, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 14, VersionType.EXTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(14L)); engine.flush(); - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 13, VersionType.EXTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 13, VersionType.EXTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1365,24 +1370,24 @@ public class InternalEngineTests extends ESTestCase { indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(2L)); - Engine.Delete delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 1L, VersionType.INTERNAL, PRIMARY, 0); + Engine.Delete delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1L, VersionType.INTERNAL, PRIMARY, 0); Engine.DeleteResult result = engine.delete(delete); assertTrue(result.hasFailure()); assertThat(result.getFailure(), instanceOf(VersionConflictEngineException.class)); // future versions should not work as well - delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 3L, VersionType.INTERNAL, PRIMARY, 0); + delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 3L, VersionType.INTERNAL, PRIMARY, 0); result = engine.delete(delete); assertTrue(result.hasFailure()); assertThat(result.getFailure(), instanceOf(VersionConflictEngineException.class)); // now actually delete - delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 2L, VersionType.INTERNAL, PRIMARY, 0); + delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2L, VersionType.INTERNAL, PRIMARY, 0); result = engine.delete(delete); assertThat(result.getVersion(), equalTo(3L)); // now check if we can index to a delete doc with version - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 2L, VersionType.INTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2L, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1400,13 +1405,13 @@ public class InternalEngineTests extends ESTestCase { engine.flush(); - Engine.Delete delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 1L, VersionType.INTERNAL, PRIMARY, 0); + Engine.Delete delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1L, VersionType.INTERNAL, PRIMARY, 0); Engine.DeleteResult deleteResult = engine.delete(delete); assertTrue(deleteResult.hasFailure()); assertThat(deleteResult.getFailure(), instanceOf(VersionConflictEngineException.class)); // future versions should not work as well - delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 3L, VersionType.INTERNAL, PRIMARY, 0); + delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 3L, VersionType.INTERNAL, PRIMARY, 0); deleteResult = engine.delete(delete); assertTrue(deleteResult.hasFailure()); assertThat(deleteResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1414,14 +1419,14 @@ public class InternalEngineTests extends ESTestCase { engine.flush(); // now actually delete - delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 2L, VersionType.INTERNAL, PRIMARY, 0); + delete = new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2L, VersionType.INTERNAL, PRIMARY, 0); deleteResult = engine.delete(delete); assertThat(deleteResult.getVersion(), equalTo(3L)); engine.flush(); // now check if we can index to a delete doc with version - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 2L, VersionType.INTERNAL, PRIMARY, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2L, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1429,11 +1434,11 @@ public class InternalEngineTests extends ESTestCase { public void testVersioningCreateExistsException() { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); + Engine.Index create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(create); assertThat(indexResult.getVersion(), equalTo(1L)); - create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); + create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(create); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1441,13 +1446,13 @@ public class InternalEngineTests extends ESTestCase { public void testVersioningCreateExistsExceptionWithFlush() { ParsedDocument doc = testParsedDocument("1", "1", "test", null, testDocument(), B_1, null); - Engine.Index create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); + Engine.Index create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); Engine.IndexResult indexResult = engine.index(create); assertThat(indexResult.getVersion(), equalTo(1L)); engine.flush(); - create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); + create = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, 0, -1, false); indexResult = engine.index(create); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1464,19 +1469,20 @@ public class InternalEngineTests extends ESTestCase { assertThat(indexResult.getVersion(), equalTo(2L)); // apply the second index to the replica, should work fine - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), indexResult.getVersion(), VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(2L)); long seqNo = indexResult.getSeqNo(); + long primaryTerm = index.primaryTerm(); // now, the old one should not work - index = new Engine.Index(newUid("1"), doc, seqNo, 1L, VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, seqNo, primaryTerm, 1L, VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); // second version on replica should fail as well - index = new Engine.Index(newUid("1"), doc, seqNo, 2L + index = new Engine.Index(newUid("1"), doc, seqNo, primaryTerm, 2L , VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(2L)); @@ -1490,8 +1496,8 @@ public class InternalEngineTests extends ESTestCase { assertThat(indexResult.getVersion(), equalTo(1L)); // apply the first index to the replica, should work fine - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), 1L - , VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), 1L, + VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); @@ -1506,20 +1512,20 @@ public class InternalEngineTests extends ESTestCase { assertThat(deleteResult.getVersion(), equalTo(3L)); // apply the delete on the replica (skipping the second index) - delete = new Engine.Delete("test", "1", newUid("1"), deleteResult.getSeqNo(), 3L + delete = new Engine.Delete("test", "1", newUid("1"), deleteResult.getSeqNo(), delete.primaryTerm(), 3L , VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0); deleteResult = replicaEngine.delete(delete); assertThat(deleteResult.getVersion(), equalTo(3L)); // second time delete with same version should fail - delete = new Engine.Delete("test", "1", newUid("1"), deleteResult.getSeqNo(), 3L + delete = new Engine.Delete("test", "1", newUid("1"), deleteResult.getSeqNo(), delete.primaryTerm(), 3L , VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0); deleteResult = replicaEngine.delete(delete); assertTrue(deleteResult.hasFailure()); assertThat(deleteResult.getFailure(), instanceOf(VersionConflictEngineException.class)); // now do the second index on the replica, it should fail - index = new Engine.Index(newUid("1"), doc, deleteResult.getSeqNo(), 2L, VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); + index = new Engine.Index(newUid("1"), doc, deleteResult.getSeqNo(), delete.primaryTerm(), 2L, VersionType.INTERNAL.versionTypeForReplicationAndRecovery(), REPLICA, 0, -1, false); indexResult = replicaEngine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1638,7 +1644,7 @@ public class InternalEngineTests extends ESTestCase { // we have some docs indexed, so delete one of them id = randomFrom(indexedIds); final Engine.Delete delete = new Engine.Delete( - "test", id, newUid("test#" + id), SequenceNumbersService.UNASSIGNED_SEQ_NO, + "test", id, newUid("test#" + id), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, rarely() ? 100 : Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, 0); final Engine.DeleteResult result = initialEngine.delete(delete); if (!result.hasFailure()) { @@ -1655,7 +1661,7 @@ public class InternalEngineTests extends ESTestCase { id = randomFrom(ids); ParsedDocument doc = testParsedDocument("test#" + id, id, "test", null, testDocumentWithTextField(), SOURCE, null); final Engine.Index index = new Engine.Index(newUid("test#" + id), doc, - SequenceNumbersService.UNASSIGNED_SEQ_NO, + SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, rarely() ? 100 : Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, 0, -1, false); final Engine.IndexResult result = initialEngine.index(index); @@ -1794,7 +1800,7 @@ public class InternalEngineTests extends ESTestCase { assertThat(localCheckpoint, greaterThanOrEqualTo(prevLocalCheckpoint)); assertThat(maxSeqNo, greaterThanOrEqualTo(prevMaxSeqNo)); try (IndexReader reader = DirectoryReader.open(commit)) { - FieldStats stats = SeqNoFieldMapper.Defaults.FIELD_TYPE.stats(reader); + FieldStats stats = SeqNoFieldMapper.SeqNoDefaults.FIELD_TYPE.stats(reader); final long highestSeqNo; if (stats != null) { highestSeqNo = (long) stats.getMaxValue(); @@ -1887,10 +1893,10 @@ public class InternalEngineTests extends ESTestCase { document.add(new TextField("value", "test1", Field.Store.YES)); ParsedDocument doc = testParsedDocument("1", "1", "test", null, document, B_2, null); - engine.index(new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 1, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false)); + engine.index(new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false)); // Delete document we just added: - engine.delete(new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 10, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime())); + engine.delete(new Engine.Delete("test", "1", newUid("1"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 10, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime())); // Get should not find the document Engine.GetResult getResult = engine.get(new Engine.Get(true, newUid("1"))); @@ -1904,14 +1910,14 @@ public class InternalEngineTests extends ESTestCase { } // Delete non-existent document - engine.delete(new Engine.Delete("test", "2", newUid("2"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 10, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime())); + engine.delete(new Engine.Delete("test", "2", newUid("2"), SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 10, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime())); // Get should not find the document (we never indexed uid=2): getResult = engine.get(new Engine.Get(true, newUid("2"))); assertThat(getResult.exists(), equalTo(false)); // Try to index uid=1 with a too-old version, should fail: - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 2, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(index); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -1921,7 +1927,7 @@ public class InternalEngineTests extends ESTestCase { assertThat(getResult.exists(), equalTo(false)); // Try to index uid=2 with a too-old version, should fail: - Engine.Index index1 = new Engine.Index(newUid("2"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 2, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); + Engine.Index index1 = new Engine.Index(newUid("2"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2, VersionType.EXTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), -1, false); indexResult = engine.index(index1); assertTrue(indexResult.hasFailure()); assertThat(indexResult.getFailure(), instanceOf(VersionConflictEngineException.class)); @@ -2019,7 +2025,7 @@ public class InternalEngineTests extends ESTestCase { final int numDocs = randomIntBetween(1, 10); for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -2069,7 +2075,7 @@ public class InternalEngineTests extends ESTestCase { final int numDocs = randomIntBetween(1, 10); for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -2162,7 +2168,7 @@ public class InternalEngineTests extends ESTestCase { final int numExtraDocs = randomIntBetween(1, 10); for (int i = 0; i < numExtraDocs; i++) { ParsedDocument doc = testParsedDocument("extra" + Integer.toString(i), "extra" + Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -2191,7 +2197,7 @@ public class InternalEngineTests extends ESTestCase { final int numDocs = randomIntBetween(1, 10); for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -2234,7 +2240,7 @@ public class InternalEngineTests extends ESTestCase { int randomId = randomIntBetween(numDocs + 1, numDocs + 10); String uuidValue = "test#" + Integer.toString(randomId); ParsedDocument doc = testParsedDocument(uuidValue, Integer.toString(randomId), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(uuidValue), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 1, VersionType.EXTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(uuidValue), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 1, VersionType.EXTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); if (flush) { @@ -2242,7 +2248,7 @@ public class InternalEngineTests extends ESTestCase { } doc = testParsedDocument(uuidValue, Integer.toString(randomId), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index idxRequest = new Engine.Index(newUid(uuidValue), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 2, VersionType.EXTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index idxRequest = new Engine.Index(newUid(uuidValue), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, 2, VersionType.EXTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult result = engine.index(idxRequest); engine.refresh("test"); assertThat(result.getVersion(), equalTo(2L)); @@ -2308,7 +2314,7 @@ public class InternalEngineTests extends ESTestCase { final int numDocs = randomIntBetween(1, 10); for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult index = engine.index(firstIndexRequest); assertThat(index.getVersion(), equalTo(1L)); } @@ -2396,7 +2402,7 @@ public class InternalEngineTests extends ESTestCase { // create { ParsedDocument doc = testParsedDocument(Integer.toString(0), Integer.toString(0), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(0)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(0)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_DELETED, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); try (InternalEngine engine = new InternalEngine(copy(config, EngineConfig.OpenMode.CREATE_INDEX_AND_TRANSLOG))){ assertFalse(engine.isRecovering()); @@ -2523,7 +2529,7 @@ public class InternalEngineTests extends ESTestCase { final int numDocs = randomIntBetween(2, 10); // at least 2 documents otherwise we don't see any deletes below for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = engine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } @@ -2533,7 +2539,7 @@ public class InternalEngineTests extends ESTestCase { engine.forceMerge(randomBoolean(), 1, false, false, false); ParsedDocument doc = testParsedDocument(Integer.toString(0), Integer.toString(0), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(0)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(0)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult index = engine.index(firstIndexRequest); assertThat(index.getVersion(), equalTo(2L)); engine.flush(); // flush - buffered deletes are not counted @@ -2607,16 +2613,16 @@ public class InternalEngineTests extends ESTestCase { boolean isRetry = false; long autoGeneratedIdTimestamp = 0; - Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + Engine.Index index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); Engine.IndexResult indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); indexResult = replicaEngine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); isRetry = true; - index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + index = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); indexResult = engine.index(index); assertThat(indexResult.getVersion(), equalTo(1L)); engine.refresh("test"); @@ -2625,7 +2631,7 @@ public class InternalEngineTests extends ESTestCase { assertEquals(1, topDocs.totalHits); } - index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + index = new Engine.Index(newUid("1"), doc, indexResult.getSeqNo(), index.primaryTerm(), indexResult.getVersion(), index.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); indexResult = replicaEngine.index(index); assertThat(indexResult.hasFailure(), equalTo(false)); replicaEngine.refresh("test"); @@ -2641,16 +2647,16 @@ public class InternalEngineTests extends ESTestCase { boolean isRetry = true; long autoGeneratedIdTimestamp = 0; - Engine.Index firstIndexRequest = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + Engine.Index firstIndexRequest = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); Engine.IndexResult result = engine.index(firstIndexRequest); assertThat(result.getVersion(), equalTo(1L)); - Engine.Index firstIndexRequestReplica = new Engine.Index(newUid("1"), doc, result.getSeqNo(), result.getVersion(), firstIndexRequest.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + Engine.Index firstIndexRequestReplica = new Engine.Index(newUid("1"), doc, result.getSeqNo(), firstIndexRequest.primaryTerm(), result.getVersion(), firstIndexRequest.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); Engine.IndexResult indexReplicaResult = replicaEngine.index(firstIndexRequestReplica); assertThat(indexReplicaResult.getVersion(), equalTo(1L)); isRetry = false; - Engine.Index secondIndexRequest = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + Engine.Index secondIndexRequest = new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); Engine.IndexResult indexResult = engine.index(secondIndexRequest); assertTrue(indexResult.isCreated()); engine.refresh("test"); @@ -2659,7 +2665,7 @@ public class InternalEngineTests extends ESTestCase { assertEquals(1, topDocs.totalHits); } - Engine.Index secondIndexRequestReplica = new Engine.Index(newUid("1"), doc, result.getSeqNo(), result.getVersion(), firstIndexRequest.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); + Engine.Index secondIndexRequestReplica = new Engine.Index(newUid("1"), doc, result.getSeqNo(), secondIndexRequest.primaryTerm(), result.getVersion(), firstIndexRequest.versionType().versionTypeForReplicationAndRecovery(), REPLICA, System.nanoTime(), autoGeneratedIdTimestamp, isRetry); replicaEngine.index(secondIndexRequestReplica); replicaEngine.refresh("test"); try (Engine.Searcher searcher = replicaEngine.acquireSearcher("test")) { @@ -2670,9 +2676,9 @@ public class InternalEngineTests extends ESTestCase { public Engine.Index randomAppendOnly(int docId, ParsedDocument doc, boolean retry) { if (randomBoolean()) { - return new Engine.Index(newUid(Integer.toString(docId)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), docId, retry); + return new Engine.Index(newUid(Integer.toString(docId)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, System.nanoTime(), docId, retry); } - return new Engine.Index(newUid(Integer.toString(docId)), doc, 0, 1, VersionType.EXTERNAL, Engine.Operation.Origin.REPLICA, System.nanoTime(), docId, retry); + return new Engine.Index(newUid(Integer.toString(docId)), doc, 0, 0, 1, VersionType.EXTERNAL, Engine.Operation.Origin.REPLICA, System.nanoTime(), docId, retry); } public void testRetryConcurrently() throws InterruptedException, IOException { @@ -2857,37 +2863,74 @@ public class InternalEngineTests extends ESTestCase { } } - public void testTragicEventErrorBubblesUp() throws IOException { - engine.close(); - final AtomicBoolean failWithFatalError = new AtomicBoolean(true); - final VirtualMachineError error = randomFrom( - new InternalError(), - new OutOfMemoryError(), - new StackOverflowError(), - new UnknownError()); - engine = new InternalEngine(copy(engine.config(), EngineConfig.OpenMode.OPEN_INDEX_AND_TRANSLOG, new Analyzer() { - @Override - protected TokenStreamComponents createComponents(String fieldName) { - return new TokenStreamComponents(new Tokenizer() { - @Override - public boolean incrementToken() throws IOException { - if (failWithFatalError.get()) { - throw error; - } else { - throw new AssertionError("should not get to this point"); - } - } - }); - } - })); - final Document document = testDocument(); - document.add(new TextField("value", "test", Field.Store.YES)); - final ParsedDocument doc = testParsedDocument("1", "1", "test", null, document, B_1, null); - final Engine.Index first = new Engine.Index(newUid("1"), doc); - expectThrows(error.getClass(), () -> engine.index(first)); - failWithFatalError.set(false); - expectThrows(error.getClass(), () -> engine.index(first)); - assertNull(engine.failedEngine.get()); + public void testSequenceIDs() throws Exception { + Tuple seqID = getSequenceID(engine, new Engine.Get(false, newUid("1"))); + // Non-existent doc returns no seqnum and no primary term + assertThat(seqID.v1(), equalTo(SequenceNumbersService.UNASSIGNED_SEQ_NO)); + assertThat(seqID.v2(), equalTo(0L)); + + // create a document + Document document = testDocumentWithTextField(); + document.add(new Field(SourceFieldMapper.NAME, BytesReference.toBytes(B_1), SourceFieldMapper.Defaults.FIELD_TYPE)); + ParsedDocument doc = testParsedDocument("1", "1", "test", null, document, B_1, null); + engine.index(new Engine.Index(newUid("1"), doc)); + engine.refresh("test"); + + seqID = getSequenceID(engine, new Engine.Get(false, newUid("1"))); + logger.info("--> got seqID: {}", seqID); + assertThat(seqID.v1(), equalTo(0L)); + assertThat(seqID.v2(), equalTo(0L)); + + // Index the same document again + document = testDocumentWithTextField(); + document.add(new Field(SourceFieldMapper.NAME, BytesReference.toBytes(B_1), SourceFieldMapper.Defaults.FIELD_TYPE)); + doc = testParsedDocument("1", "1", "test", null, document, B_1, null); + engine.index(new Engine.Index(newUid("1"), doc)); + engine.refresh("test"); + + seqID = getSequenceID(engine, new Engine.Get(false, newUid("1"))); + logger.info("--> got seqID: {}", seqID); + assertThat(seqID.v1(), equalTo(1L)); + assertThat(seqID.v2(), equalTo(0L)); + + // Index the same document for the third time, this time changing the primary term + document = testDocumentWithTextField(); + document.add(new Field(SourceFieldMapper.NAME, BytesReference.toBytes(B_1), SourceFieldMapper.Defaults.FIELD_TYPE)); + doc = testParsedDocument("1", "1", "test", null, document, B_1, null); + engine.index(new Engine.Index(newUid("1"), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 1, + Versions.MATCH_ANY, VersionType.INTERNAL, Engine.Operation.Origin.PRIMARY, + System.nanoTime(), -1, false)); + engine.refresh("test"); + + seqID = getSequenceID(engine, new Engine.Get(false, newUid("1"))); + logger.info("--> got seqID: {}", seqID); + assertThat(seqID.v1(), equalTo(2L)); + assertThat(seqID.v2(), equalTo(1L)); + + // we can query by the _seq_no + Engine.Searcher searchResult = engine.acquireSearcher("test"); + MatcherAssert.assertThat(searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(1)); + MatcherAssert.assertThat(searchResult, EngineSearcherTotalHitsMatcher.engineSearcherTotalHits(LongPoint.newExactQuery("_seq_no", 2), 1)); + searchResult.close(); + } + + /** + * Return a tuple representing the sequence ID for the given {@code Get} + * operation. The first value in the tuple is the sequence number, the + * second is the primary term. + */ + private Tuple getSequenceID(Engine engine, Engine.Get get) throws EngineException { + final Searcher searcher = engine.acquireSearcher("get"); + try { + long seqNum = Versions.loadSeqNo(searcher.reader(), get.uid()); + long primaryTerm = Versions.loadPrimaryTerm(searcher.reader(), get.uid()); + return new Tuple(seqNum, primaryTerm); + } catch (Exception e) { + Releasables.closeWhileHandlingException(searcher); + throw new EngineException(shardId, "unable to retrieve sequence id", e); + } finally { + searcher.close(); + } } } diff --git a/core/src/test/java/org/elasticsearch/index/engine/ShadowEngineTests.java b/core/src/test/java/org/elasticsearch/index/engine/ShadowEngineTests.java index 50ea9c08716..a3c58f25ea9 100644 --- a/core/src/test/java/org/elasticsearch/index/engine/ShadowEngineTests.java +++ b/core/src/test/java/org/elasticsearch/index/engine/ShadowEngineTests.java @@ -54,6 +54,7 @@ import org.elasticsearch.index.codec.CodecService; import org.elasticsearch.index.mapper.Mapping; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; import org.elasticsearch.index.seqno.SequenceNumbersService; @@ -174,11 +175,14 @@ public class ShadowEngineTests extends ESTestCase { private ParsedDocument testParsedDocument(String uid, String id, String type, String routing, ParseContext.Document document, BytesReference source, Mapping mappingsUpdate) { Field uidField = new Field("_uid", uid, UidFieldMapper.Defaults.FIELD_TYPE); Field versionField = new NumericDocValuesField("_version", 0); - Field seqNoField = new NumericDocValuesField("_seq_no", 0); + SeqNoFieldMapper.SequenceID seqID = SeqNoFieldMapper.SequenceID.emptySeqID(); document.add(uidField); document.add(versionField); + document.add(seqID.seqNo); + document.add(seqID.seqNoDocValue); + document.add(seqID.primaryTerm); document.add(new LongPoint("point_field", 42)); // so that points report memory/disk usage - return new ParsedDocument(versionField, seqNoField, id, type, routing, Arrays.asList(document), source, mappingsUpdate); + return new ParsedDocument(versionField, seqID, id, type, routing, Arrays.asList(document), source, mappingsUpdate); } protected Store createStore(Path p) throws IOException { @@ -984,7 +988,7 @@ public class ShadowEngineTests extends ESTestCase { final int numDocs = randomIntBetween(2, 10); // at least 2 documents otherwise we don't see any deletes below for (int i = 0; i < numDocs; i++) { ParsedDocument doc = testParsedDocument(Integer.toString(i), Integer.toString(i), "test", null, testDocument(), new BytesArray("{}"), null); - Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); + Engine.Index firstIndexRequest = new Engine.Index(newUid(Integer.toString(i)), doc, SequenceNumbersService.UNASSIGNED_SEQ_NO, 0, Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, System.nanoTime(), -1, false); Engine.IndexResult indexResult = primaryEngine.index(firstIndexRequest); assertThat(indexResult.getVersion(), equalTo(1L)); } diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataImplTestCase.java b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataImplTestCase.java index b6ae9948675..75f53b8a7e3 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataImplTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataImplTestCase.java @@ -31,6 +31,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.Strings; import org.elasticsearch.search.MultiValueMode; +import java.util.List; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; @@ -71,57 +72,61 @@ public abstract class AbstractFieldDataImplTestCase extends AbstractFieldDataTes public void testDeletedDocs() throws Exception { add2SingleValuedDocumentsAndDeleteOneOfThem(); IndexFieldData indexFieldData = getForField("value"); - LeafReaderContext readerContext = refreshReader(); - AtomicFieldData fieldData = indexFieldData.load(readerContext); - SortedBinaryDocValues values = fieldData.getBytesValues(); - for (int i = 0; i < readerContext.reader().maxDoc(); ++i) { - values.setDocument(i); - assertThat(values.count(), greaterThanOrEqualTo(1)); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + SortedBinaryDocValues values = fieldData.getBytesValues(); + for (int i = 0; i < readerContext.reader().maxDoc(); ++i) { + values.setDocument(i); + assertThat(values.count(), greaterThanOrEqualTo(1)); + } } } public void testSingleValueAllSet() throws Exception { fillSingleValueAllSet(); IndexFieldData indexFieldData = getForField("value"); - LeafReaderContext readerContext = refreshReader(); - AtomicFieldData fieldData = indexFieldData.load(readerContext); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - bytesValues.setDocument(0); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(two()))); - bytesValues.setDocument(1); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(one()))); - bytesValues.setDocument(2); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(three()))); + bytesValues.setDocument(0); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(two()))); + bytesValues.setDocument(1); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(one()))); + bytesValues.setDocument(2); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(three()))); - assertValues(bytesValues, 0, two()); - assertValues(bytesValues, 1, one()); - assertValues(bytesValues, 2, three()); + assertValues(bytesValues, 0, two()); + assertValues(bytesValues, 1, one()); + assertValues(bytesValues, 2, three()); - IndexSearcher searcher = new IndexSearcher(readerContext.reader()); - TopFieldDocs topDocs; + IndexSearcher searcher = new IndexSearcher(readerContext.reader()); + TopFieldDocs topDocs; - topDocs = searcher.search(new MatchAllDocsQuery(), 10, - new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MIN, null)))); - assertThat(topDocs.totalHits, equalTo(3)); - assertThat(topDocs.scoreDocs[0].doc, equalTo(1)); - assertThat(toString(((FieldDoc) topDocs.scoreDocs[0]).fields[0]), equalTo(one())); - assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); - assertThat(toString(((FieldDoc) topDocs.scoreDocs[1]).fields[0]), equalTo(two())); - assertThat(topDocs.scoreDocs[2].doc, equalTo(2)); - assertThat(toString(((FieldDoc) topDocs.scoreDocs[2]).fields[0]), equalTo(three())); + topDocs = searcher.search(new MatchAllDocsQuery(), 10, + new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MIN, null)))); + assertThat(topDocs.totalHits, equalTo(3)); + assertThat(topDocs.scoreDocs[0].doc, equalTo(1)); + assertThat(toString(((FieldDoc) topDocs.scoreDocs[0]).fields[0]), equalTo(one())); + assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); + assertThat(toString(((FieldDoc) topDocs.scoreDocs[1]).fields[0]), equalTo(two())); + assertThat(topDocs.scoreDocs[2].doc, equalTo(2)); + assertThat(toString(((FieldDoc) topDocs.scoreDocs[2]).fields[0]), equalTo(three())); - topDocs = searcher.search(new MatchAllDocsQuery(), 10, - new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MAX, null), true))); - assertThat(topDocs.totalHits, equalTo(3)); - assertThat(topDocs.scoreDocs[0].doc, equalTo(2)); - assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); - assertThat(topDocs.scoreDocs[2].doc, equalTo(1)); + topDocs = searcher.search(new MatchAllDocsQuery(), 10, + new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MAX, null), true))); + assertThat(topDocs.totalHits, equalTo(3)); + assertThat(topDocs.scoreDocs[0].doc, equalTo(2)); + assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); + assertThat(topDocs.scoreDocs[2].doc, equalTo(1)); + } } protected abstract void fillSingleValueWithMissing() throws Exception; @@ -145,45 +150,52 @@ public abstract class AbstractFieldDataImplTestCase extends AbstractFieldDataTes public void testSingleValueWithMissing() throws Exception { fillSingleValueWithMissing(); IndexFieldData indexFieldData = getForField("value"); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - SortedBinaryDocValues bytesValues = fieldData - .getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - assertValues(bytesValues, 0, two()); - assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); - assertValues(bytesValues, 2, three()); + assertValues(bytesValues, 0, two()); + assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); + assertValues(bytesValues, 2, three()); + } } protected abstract void fillMultiValueAllSet() throws Exception; public void testMultiValueAllSet() throws Exception { fillMultiValueAllSet(); + // the segments are force merged to a single segment so that the sorted binary doc values can be asserted within a single segment. + // Previously we used the SlowCompositeReaderWrapper but this is an unideal solution so force merging is a better idea. + writer.forceMerge(1); IndexFieldData indexFieldData = getForField("value"); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + assertValues(bytesValues, 0, two(), four()); + assertValues(bytesValues, 1, one()); + assertValues(bytesValues, 2, three()); - assertValues(bytesValues, 0, two(), four()); - assertValues(bytesValues, 1, one()); - assertValues(bytesValues, 2, three()); + IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(writer)); + TopFieldDocs topDocs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MIN, null)))); + assertThat(topDocs.totalHits, equalTo(3)); + assertThat(topDocs.scoreDocs.length, equalTo(3)); + assertThat(topDocs.scoreDocs[0].doc, equalTo(1)); + assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); + assertThat(topDocs.scoreDocs[2].doc, equalTo(2)); - IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(writer)); - TopFieldDocs topDocs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MIN, null)))); - assertThat(topDocs.totalHits, equalTo(3)); - assertThat(topDocs.scoreDocs.length, equalTo(3)); - assertThat(topDocs.scoreDocs[0].doc, equalTo(1)); - assertThat(topDocs.scoreDocs[1].doc, equalTo(0)); - assertThat(topDocs.scoreDocs[2].doc, equalTo(2)); - - topDocs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MAX, null), true))); - assertThat(topDocs.totalHits, equalTo(3)); - assertThat(topDocs.scoreDocs.length, equalTo(3)); - assertThat(topDocs.scoreDocs[0].doc, equalTo(0)); - assertThat(topDocs.scoreDocs[1].doc, equalTo(2)); - assertThat(topDocs.scoreDocs[2].doc, equalTo(1)); + topDocs = searcher.search(new MatchAllDocsQuery(), 10, new Sort(new SortField("value", indexFieldData.comparatorSource(null, MultiValueMode.MAX, null), true))); + assertThat(topDocs.totalHits, equalTo(3)); + assertThat(topDocs.scoreDocs.length, equalTo(3)); + assertThat(topDocs.scoreDocs[0].doc, equalTo(0)); + assertThat(topDocs.scoreDocs[1].doc, equalTo(2)); + assertThat(topDocs.scoreDocs[2].doc, equalTo(1)); + } } protected abstract void fillMultiValueWithMissing() throws Exception; @@ -191,33 +203,39 @@ public abstract class AbstractFieldDataImplTestCase extends AbstractFieldDataTes public void testMultiValueWithMissing() throws Exception { fillMultiValueWithMissing(); IndexFieldData indexFieldData = getForField("value"); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - assertValues(bytesValues, 0, two(), four()); - assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); - assertValues(bytesValues, 2, three()); + assertValues(bytesValues, 0, two(), four()); + assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); + assertValues(bytesValues, 2, three()); + } } public void testMissingValueForAll() throws Exception { fillAllMissing(); IndexFieldData indexFieldData = getForField("value"); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); - // Some impls (FST) return size 0 and some (PagedBytes) do take size in the case no actual data is loaded - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(0L)); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + // Some impls (FST) return size 0 and some (PagedBytes) do take size in the case no actual data is loaded + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(0L)); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - assertValues(bytesValues, 0, Strings.EMPTY_ARRAY); - assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); - assertValues(bytesValues, 2, Strings.EMPTY_ARRAY); - SortedBinaryDocValues hashedBytesValues = fieldData.getBytesValues(); + assertValues(bytesValues, 0, Strings.EMPTY_ARRAY); + assertValues(bytesValues, 1, Strings.EMPTY_ARRAY); + assertValues(bytesValues, 2, Strings.EMPTY_ARRAY); + SortedBinaryDocValues hashedBytesValues = fieldData.getBytesValues(); - assertValues(hashedBytesValues, 0, Strings.EMPTY_ARRAY); - assertValues(hashedBytesValues, 1, Strings.EMPTY_ARRAY); - assertValues(hashedBytesValues, 2, Strings.EMPTY_ARRAY); + assertValues(hashedBytesValues, 0, Strings.EMPTY_ARRAY); + assertValues(hashedBytesValues, 1, Strings.EMPTY_ARRAY); + assertValues(hashedBytesValues, 2, Strings.EMPTY_ARRAY); + } } protected abstract void fillAllMissing() throws Exception; diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTestCase.java b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTestCase.java index 5e26f26978e..641d1eaae36 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTestCase.java @@ -29,7 +29,6 @@ import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.LogByteSizeMergePolicy; -import org.apache.lucene.index.SlowCompositeReaderWrapper; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.store.RAMDirectory; @@ -61,6 +60,7 @@ import org.junit.Before; import java.io.IOException; import java.util.Collection; +import java.util.List; import static org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested; import static org.hamcrest.Matchers.equalTo; @@ -73,8 +73,8 @@ public abstract class AbstractFieldDataTestCase extends ESSingleNodeTestCase { protected IndexFieldDataService ifdService; protected MapperService mapperService; protected IndexWriter writer; - protected LeafReaderContext readerContext; - protected DirectoryReader topLevelReader; + protected List readerContexts = null; + protected DirectoryReader topLevelReader = null; protected IndicesFieldDataCache indicesFieldDataCache; protected abstract String getFieldDataType(); @@ -146,22 +146,21 @@ public abstract class AbstractFieldDataTestCase extends ESSingleNodeTestCase { writer = new IndexWriter(new RAMDirectory(), new IndexWriterConfig(new StandardAnalyzer()).setMergePolicy(new LogByteSizeMergePolicy())); } - protected final LeafReaderContext refreshReader() throws Exception { - if (readerContext != null) { - readerContext.reader().close(); + protected final List refreshReader() throws Exception { + if (readerContexts != null && topLevelReader != null) { + topLevelReader.close(); } topLevelReader = ElasticsearchDirectoryReader.wrap(DirectoryReader.open(writer), new ShardId("foo", "_na_", 1)); - LeafReader reader = SlowCompositeReaderWrapper.wrap(topLevelReader); - readerContext = reader.getContext(); - return readerContext; + readerContexts = topLevelReader.leaves(); + return readerContexts; } @Override @After public void tearDown() throws Exception { super.tearDown(); - if (readerContext != null) { - readerContext.reader().close(); + if (topLevelReader != null) { + topLevelReader.close(); } writer.close(); } @@ -179,14 +178,16 @@ public abstract class AbstractFieldDataTestCase extends ESSingleNodeTestCase { IndexFieldData fieldData = getForField("non_existing_field"); int max = randomInt(7); - AtomicFieldData previous = null; - for (int i = 0; i < max; i++) { - AtomicFieldData current = fieldData.load(readerContext); - assertThat(current.ramBytesUsed(), equalTo(0L)); - if (previous != null) { - assertThat(current, not(sameInstance(previous))); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData previous = null; + for (int i = 0; i < max; i++) { + AtomicFieldData current = fieldData.load(readerContext); + assertThat(current.ramBytesUsed(), equalTo(0L)); + if (previous != null) { + assertThat(current, not(sameInstance(previous))); + } + previous = current; } - previous = current; } } } diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractStringFieldDataTestCase.java b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractStringFieldDataTestCase.java index 13f194a23ba..b3652ec9167 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractStringFieldDataTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractStringFieldDataTestCase.java @@ -557,37 +557,40 @@ public abstract class AbstractStringFieldDataTestCase extends AbstractFieldDataI public void testTermsEnum() throws Exception { fillExtendedMvSet(); - LeafReaderContext atomicReaderContext = refreshReader(); + writer.forceMerge(1); + List atomicReaderContexts = refreshReader(); IndexOrdinalsFieldData ifd = getForField("value"); - AtomicOrdinalsFieldData afd = ifd.load(atomicReaderContext); + for (LeafReaderContext atomicReaderContext : atomicReaderContexts) { + AtomicOrdinalsFieldData afd = ifd.load(atomicReaderContext); - TermsEnum termsEnum = afd.getOrdinalsValues().termsEnum(); - int size = 0; - while (termsEnum.next() != null) { - size++; + TermsEnum termsEnum = afd.getOrdinalsValues().termsEnum(); + int size = 0; + while (termsEnum.next() != null) { + size++; + } + assertThat(size, equalTo(12)); + + assertThat(termsEnum.seekExact(new BytesRef("10")), is(true)); + assertThat(termsEnum.term().utf8ToString(), equalTo("10")); + assertThat(termsEnum.next(), nullValue()); + + assertThat(termsEnum.seekExact(new BytesRef("08")), is(true)); + assertThat(termsEnum.term().utf8ToString(), equalTo("08")); + size = 0; + while (termsEnum.next() != null) { + size++; + } + assertThat(size, equalTo(2)); + + termsEnum.seekExact(8); + assertThat(termsEnum.term().utf8ToString(), equalTo("07")); + size = 0; + while (termsEnum.next() != null) { + size++; + } + assertThat(size, equalTo(3)); } - assertThat(size, equalTo(12)); - - assertThat(termsEnum.seekExact(new BytesRef("10")), is(true)); - assertThat(termsEnum.term().utf8ToString(), equalTo("10")); - assertThat(termsEnum.next(), nullValue()); - - assertThat(termsEnum.seekExact(new BytesRef("08")), is(true)); - assertThat(termsEnum.term().utf8ToString(), equalTo("08")); - size = 0; - while (termsEnum.next() != null) { - size++; - } - assertThat(size, equalTo(2)); - - termsEnum.seekExact(8); - assertThat(termsEnum.term().utf8ToString(), equalTo("07")); - size = 0; - while (termsEnum.next() != null) { - size++; - } - assertThat(size, equalTo(3)); } public void testGlobalOrdinalsGetRemovedOnceIndexReaderCloses() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/BinaryDVFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/BinaryDVFieldDataTests.java index eb5b1f2b874..5231ccfc380 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/BinaryDVFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/BinaryDVFieldDataTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.ParsedDocument; +import java.util.List; import static org.hamcrest.Matchers.equalTo; public class BinaryDVFieldDataTests extends AbstractFieldDataTestCase { @@ -75,30 +76,32 @@ public class BinaryDVFieldDataTests extends AbstractFieldDataTestCase { d = mapper.parse("test", "test", "4", doc.bytes()); writer.addDocument(d.rootDoc()); - LeafReaderContext reader = refreshReader(); + List readers = refreshReader(); IndexFieldData indexFieldData = getForField("field"); - AtomicFieldData fieldData = indexFieldData.load(reader); + for (LeafReaderContext reader : readers) { + AtomicFieldData fieldData = indexFieldData.load(reader); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - CollectionUtils.sortAndDedup(bytesList1); - bytesValues.setDocument(0); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytesList1.get(0)))); - assertThat(bytesValues.valueAt(1), equalTo(new BytesRef(bytesList1.get(1)))); + CollectionUtils.sortAndDedup(bytesList1); + bytesValues.setDocument(0); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytesList1.get(0)))); + assertThat(bytesValues.valueAt(1), equalTo(new BytesRef(bytesList1.get(1)))); - bytesValues.setDocument(1); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytes1))); + bytesValues.setDocument(1); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytes1))); - bytesValues.setDocument(2); - assertThat(bytesValues.count(), equalTo(0)); + bytesValues.setDocument(2); + assertThat(bytesValues.count(), equalTo(0)); - CollectionUtils.sortAndDedup(bytesList2); - bytesValues.setDocument(3); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytesList2.get(0)))); - assertThat(bytesValues.valueAt(1), equalTo(new BytesRef(bytesList2.get(1)))); + CollectionUtils.sortAndDedup(bytesList2); + bytesValues.setDocument(3); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0), equalTo(new BytesRef(bytesList2.get(0)))); + assertThat(bytesValues.valueAt(1), equalTo(new BytesRef(bytesList2.get(1)))); + } } private byte[] randomBytes() { diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/FilterFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/FilterFieldDataTests.java index d15a50300ea..33ecd57b130 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/FilterFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/FilterFieldDataTests.java @@ -28,6 +28,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.TextFieldMapper; import org.elasticsearch.index.mapper.Mapper.BuilderContext; +import java.util.List; import java.util.Random; import static org.hamcrest.Matchers.equalTo; @@ -58,7 +59,7 @@ public class FilterFieldDataTests extends AbstractFieldDataTestCase { writer.addDocument(d); } writer.forceMerge(1, true); - LeafReaderContext context = refreshReader(); + List contexts = refreshReader(); final BuilderContext builderCtx = new BuilderContext(indexService.getIndexSettings().getSettings(), new ContentPath(1)); { @@ -68,11 +69,13 @@ public class FilterFieldDataTests extends AbstractFieldDataTestCase { .fielddataFrequencyFilter(0, random.nextBoolean() ? 100 : 0.5d, 0) .build(builderCtx).fieldType(); IndexOrdinalsFieldData fieldData = ifdService.getForField(ft); - AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); - RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); - assertThat(2L, equalTo(bytesValues.getValueCount())); - assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); - assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + for (LeafReaderContext context : contexts) { + AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); + RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); + assertThat(2L, equalTo(bytesValues.getValueCount())); + assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); + assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + } } { ifdService.clear(); @@ -81,10 +84,12 @@ public class FilterFieldDataTests extends AbstractFieldDataTestCase { .fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, 201, 100) .build(builderCtx).fieldType(); IndexOrdinalsFieldData fieldData = ifdService.getForField(ft); - AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); - RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); - assertThat(1L, equalTo(bytesValues.getValueCount())); - assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("5")); + for (LeafReaderContext context : contexts) { + AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); + RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); + assertThat(1L, equalTo(bytesValues.getValueCount())); + assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("5")); + } } { @@ -94,11 +99,13 @@ public class FilterFieldDataTests extends AbstractFieldDataTestCase { .fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, Integer.MAX_VALUE, 101) .build(builderCtx).fieldType(); IndexOrdinalsFieldData fieldData = ifdService.getForField(ft); - AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); - RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); - assertThat(2L, equalTo(bytesValues.getValueCount())); - assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); - assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + for (LeafReaderContext context : contexts) { + AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); + RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); + assertThat(2L, equalTo(bytesValues.getValueCount())); + assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); + assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + } } { @@ -108,11 +115,13 @@ public class FilterFieldDataTests extends AbstractFieldDataTestCase { .fielddataFrequencyFilter(random.nextBoolean() ? 101 : 101d/200.0d, Integer.MAX_VALUE, 101) .build(builderCtx).fieldType(); IndexOrdinalsFieldData fieldData = ifdService.getForField(ft); - AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); - RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); - assertThat(2L, equalTo(bytesValues.getValueCount())); - assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); - assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + for (LeafReaderContext context : contexts) { + AtomicOrdinalsFieldData loadDirect = fieldData.loadDirect(context); + RandomAccessOrds bytesValues = loadDirect.getOrdinalsValues(); + assertThat(2L, equalTo(bytesValues.getValueCount())); + assertThat(bytesValues.lookupOrd(0).utf8ToString(), equalTo("10")); + assertThat(bytesValues.lookupOrd(1).utf8ToString(), equalTo("100")); + } } } diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/GeoFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/GeoFieldDataTests.java index 04ae9bd0840..3c362d48c11 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/GeoFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/GeoFieldDataTests.java @@ -25,6 +25,7 @@ import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.Term; import org.elasticsearch.index.fielddata.plain.AbstractAtomicGeoPointFieldData; +import java.util.List; import static org.hamcrest.Matchers.greaterThanOrEqualTo; /** @@ -153,55 +154,64 @@ public class GeoFieldDataTests extends AbstractGeoFieldDataTestCase { public void testSingleValueAllSet() throws Exception { fillSingleValueAllSet(); IndexFieldData indexFieldData = getForField("value"); - LeafReaderContext readerContext = refreshReader(); - AtomicFieldData fieldData = indexFieldData.load(readerContext); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); - assertValues(fieldValues, 0); - assertValues(fieldValues, 1); - assertValues(fieldValues, 2); + MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); + assertValues(fieldValues, 0); + assertValues(fieldValues, 1); + assertValues(fieldValues, 2); + } } @Override public void testSingleValueWithMissing() throws Exception { fillSingleValueWithMissing(); IndexFieldData indexFieldData = getForField("value"); - LeafReaderContext readerContext = refreshReader(); - AtomicFieldData fieldData = indexFieldData.load(readerContext); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); - assertValues(fieldValues, 0); - assertMissing(fieldValues, 1); - assertValues(fieldValues, 2); + MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); + assertValues(fieldValues, 0); + assertMissing(fieldValues, 1); + assertValues(fieldValues, 2); + } } @Override public void testMultiValueAllSet() throws Exception { fillMultiValueAllSet(); IndexFieldData indexFieldData = getForField("value"); - LeafReaderContext readerContext = refreshReader(); - AtomicFieldData fieldData = indexFieldData.load(readerContext); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); - assertValues(fieldValues, 0); - assertValues(fieldValues, 1); - assertValues(fieldValues, 2); + MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); + assertValues(fieldValues, 0); + assertValues(fieldValues, 1); + assertValues(fieldValues, 2); + } } @Override public void testMultiValueWithMissing() throws Exception { fillMultiValueWithMissing(); IndexFieldData indexFieldData = getForField("value"); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); - assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); + assertThat(fieldData.ramBytesUsed(), greaterThanOrEqualTo(minRamBytesUsed())); - MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); + MultiGeoPointValues fieldValues = ((AbstractAtomicGeoPointFieldData)fieldData).getGeoPointValues(); - assertValues(fieldValues, 0); - assertMissing(fieldValues, 1); - assertValues(fieldValues, 2); + assertValues(fieldValues, 0); + assertMissing(fieldValues, 1); + assertValues(fieldValues, 2); + } } } diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java index e9cfff5a4fb..b200a42b3f8 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java @@ -47,6 +47,7 @@ import org.elasticsearch.search.MultiValueMode; import org.junit.Before; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -124,44 +125,48 @@ public class ParentChildFieldDataTests extends AbstractFieldDataTestCase { } public void testGetBytesValues() throws Exception { + writer.forceMerge(1); // force merge to 1 segment so we can iterate through documents IndexFieldData indexFieldData = getForField(childType); - AtomicFieldData fieldData = indexFieldData.load(refreshReader()); + List readerContexts = refreshReader(); + for (LeafReaderContext readerContext : readerContexts) { + AtomicFieldData fieldData = indexFieldData.load(readerContext); - SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); - bytesValues.setDocument(0); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); + SortedBinaryDocValues bytesValues = fieldData.getBytesValues(); + bytesValues.setDocument(0); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); - bytesValues.setDocument(1); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); - assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("2")); + bytesValues.setDocument(1); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); + assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("2")); - bytesValues.setDocument(2); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); - assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("3")); + bytesValues.setDocument(2); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); + assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("3")); - bytesValues.setDocument(3); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); + bytesValues.setDocument(3); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); - bytesValues.setDocument(4); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); - assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("4")); + bytesValues.setDocument(4); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); + assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("4")); - bytesValues.setDocument(5); - assertThat(bytesValues.count(), equalTo(2)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); - assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("5")); + bytesValues.setDocument(5); + assertThat(bytesValues.count(), equalTo(2)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("1")); + assertThat(bytesValues.valueAt(1).utf8ToString(), equalTo("5")); - bytesValues.setDocument(6); - assertThat(bytesValues.count(), equalTo(1)); - assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); + bytesValues.setDocument(6); + assertThat(bytesValues.count(), equalTo(1)); + assertThat(bytesValues.valueAt(0).utf8ToString(), equalTo("2")); - bytesValues.setDocument(7); - assertThat(bytesValues.count(), equalTo(0)); + bytesValues.setDocument(7); + assertThat(bytesValues.count(), equalTo(0)); + } } public void testSorting() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/FieldNamesFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/FieldNamesFieldMapperTests.java index 8e508d084e0..8292970d38c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/FieldNamesFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldNamesFieldMapperTests.java @@ -97,7 +97,7 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertFieldNames(set("a", "a.keyword", "b", "b.c", "_uid", "_type", "_version", "_seq_no", "_source", "_all"), doc); + assertFieldNames(set("a", "a.keyword", "b", "b.c", "_uid", "_type", "_version", "_seq_no", "_primary_term", "_source", "_all"), doc); } public void testExplicitEnabled() throws Exception { @@ -114,7 +114,7 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase { .endObject() .bytes()); - assertFieldNames(set("field", "field.keyword", "_uid", "_type", "_version", "_seq_no", "_source", "_all"), doc); + assertFieldNames(set("field", "field.keyword", "_uid", "_type", "_version", "_seq_no", "_primary_term", "_source", "_all"), doc); } public void testDisabled() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java b/core/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java index d32ae8e03ed..ef938376940 100644 --- a/core/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java +++ b/core/src/test/java/org/elasticsearch/index/shard/IndexShardIT.java @@ -55,6 +55,7 @@ import org.elasticsearch.index.flush.FlushStats; import org.elasticsearch.index.mapper.Mapping; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; import org.elasticsearch.index.seqno.SequenceNumbersService; import org.elasticsearch.index.translog.Translog; @@ -102,12 +103,15 @@ public class IndexShardIT extends ESSingleNodeTestCase { private ParsedDocument testParsedDocument(String uid, String id, String type, String routing, long seqNo, ParseContext.Document document, BytesReference source, Mapping mappingUpdate) { Field uidField = new Field("_uid", uid, UidFieldMapper.Defaults.FIELD_TYPE); - Field seqNoField = new NumericDocValuesField("_seq_no", seqNo); Field versionField = new NumericDocValuesField("_version", 0); + SeqNoFieldMapper.SequenceID seqID = SeqNoFieldMapper.SequenceID.emptySeqID(); document.add(uidField); document.add(versionField); - return new ParsedDocument(versionField, seqNoField, id, type, routing, Collections.singletonList(document), source, - mappingUpdate); + document.add(seqID.seqNo); + document.add(seqID.seqNoDocValue); + document.add(seqID.primaryTerm); + return new ParsedDocument(versionField, seqID, id, type, routing, + Collections.singletonList(document), source, mappingUpdate); } public void testLockTryingToDelete() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java b/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java index 4ab702c33de..036faa9b903 100644 --- a/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java +++ b/core/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java @@ -70,6 +70,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapping; import org.elasticsearch.index.mapper.ParseContext; 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.snapshots.IndexShardSnapshotStatus; @@ -542,10 +543,13 @@ public class IndexShardTests extends IndexShardTestCase { ParseContext.Document document, BytesReference source, Mapping mappingUpdate) { Field uidField = new Field("_uid", uid, UidFieldMapper.Defaults.FIELD_TYPE); Field versionField = new NumericDocValuesField("_version", 0); - Field seqNoField = new NumericDocValuesField("_seq_no", 0); + SeqNoFieldMapper.SequenceID seqID = SeqNoFieldMapper.SequenceID.emptySeqID(); document.add(uidField); document.add(versionField); - return new ParsedDocument(versionField, seqNoField, id, type, routing, Arrays.asList(document), source, mappingUpdate); + document.add(seqID.seqNo); + document.add(seqID.seqNoDocValue); + document.add(seqID.primaryTerm); + return new ParsedDocument(versionField, seqID, id, type, routing, Arrays.asList(document), source, mappingUpdate); } public void testIndexingOperationsListeners() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/index/shard/RefreshListenersTests.java b/core/src/test/java/org/elasticsearch/index/shard/RefreshListenersTests.java index 0598646c163..57e40a03295 100644 --- a/core/src/test/java/org/elasticsearch/index/shard/RefreshListenersTests.java +++ b/core/src/test/java/org/elasticsearch/index/shard/RefreshListenersTests.java @@ -47,6 +47,7 @@ import org.elasticsearch.index.engine.InternalEngineTests.TranslogHandler; import org.elasticsearch.index.fieldvisitor.SingleFieldsVisitor; import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.SeqNoFieldMapper; import org.elasticsearch.index.mapper.UidFieldMapper; import org.elasticsearch.index.store.DirectoryService; import org.elasticsearch.index.store.Store; @@ -273,11 +274,14 @@ public class RefreshListenersTests extends ESTestCase { document.add(new TextField("test", testFieldValue, Field.Store.YES)); Field uidField = new Field("_uid", type + ":" + id, UidFieldMapper.Defaults.FIELD_TYPE); Field versionField = new NumericDocValuesField("_version", Versions.MATCH_ANY); - Field seqNoField = new NumericDocValuesField("_seq_no", 0); + SeqNoFieldMapper.SequenceID seqID = SeqNoFieldMapper.SequenceID.emptySeqID(); document.add(uidField); document.add(versionField); + document.add(seqID.seqNo); + document.add(seqID.seqNoDocValue); + document.add(seqID.primaryTerm); BytesReference source = new BytesArray(new byte[] { 1 }); - ParsedDocument doc = new ParsedDocument(versionField, seqNoField, id, type, null, Arrays.asList(document), source, null); + ParsedDocument doc = new ParsedDocument(versionField, seqID, id, type, null, Arrays.asList(document), source, null); Engine.Index index = new Engine.Index(new Term("_uid", uid), doc); return engine.index(index); } diff --git a/core/src/test/java/org/elasticsearch/index/translog/TranslogTests.java b/core/src/test/java/org/elasticsearch/index/translog/TranslogTests.java index 0bd1c9c6140..41118d6efa2 100644 --- a/core/src/test/java/org/elasticsearch/index/translog/TranslogTests.java +++ b/core/src/test/java/org/elasticsearch/index/translog/TranslogTests.java @@ -301,7 +301,7 @@ public class TranslogTests extends ESTestCase { assertThat(stats.estimatedNumberOfOperations(), equalTo(0L)); assertThat(stats.getTranslogSizeInBytes(), equalTo(firstOperationPosition)); assertEquals(6, total.estimatedNumberOfOperations()); - assertEquals(413, total.getTranslogSizeInBytes()); + assertEquals(419, total.getTranslogSizeInBytes()); BytesStreamOutput out = new BytesStreamOutput(); total.writeTo(out); @@ -309,13 +309,13 @@ public class TranslogTests extends ESTestCase { copy.readFrom(out.bytes().streamInput()); assertEquals(6, copy.estimatedNumberOfOperations()); - assertEquals(413, copy.getTranslogSizeInBytes()); + assertEquals(419, copy.getTranslogSizeInBytes()); try (XContentBuilder builder = XContentFactory.jsonBuilder()) { builder.startObject(); copy.toXContent(builder, ToXContent.EMPTY_PARAMS); builder.endObject(); - assertEquals("{\"translog\":{\"operations\":6,\"size_in_bytes\":413}}", builder.string()); + assertEquals("{\"translog\":{\"operations\":6,\"size_in_bytes\":419}}", builder.string()); } try { @@ -1137,7 +1137,7 @@ public class TranslogTests extends ESTestCase { try (Translog ignored = new Translog(config, translogGeneration, () -> SequenceNumbersService.UNASSIGNED_SEQ_NO)) { fail("corrupted"); } catch (IllegalStateException ex) { - assertEquals(ex.getMessage(), "Checkpoint file translog-2.ckp already exists but has corrupted content expected: Checkpoint{offset=2298, numOps=55, translogFileGeneration=2, globalCheckpoint=-2} but got: Checkpoint{offset=0, numOps=0, translogFileGeneration=0, globalCheckpoint=-2}"); + assertEquals(ex.getMessage(), "Checkpoint file translog-2.ckp already exists but has corrupted content expected: Checkpoint{offset=2353, numOps=55, translogFileGeneration=2, globalCheckpoint=-2} but got: Checkpoint{offset=0, numOps=0, translogFileGeneration=0, globalCheckpoint=-2}"); } Checkpoint.write(FileChannel::open, config.getTranslogPath().resolve(Translog.getCommitCheckpointFileName(read.generation)), read, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); try (Translog translog = new Translog(config, translogGeneration, () -> SequenceNumbersService.UNASSIGNED_SEQ_NO)) { @@ -1303,6 +1303,7 @@ public class TranslogTests extends ESTestCase { op = new Translog.Delete( new Term("_uid", threadId + "_" + opCount), opCount, + 0, 1 + randomInt(100000), randomFrom(VersionType.values())); break; diff --git a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorFieldMapperTests.java b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorFieldMapperTests.java index fad3cc27d23..533c56afac5 100644 --- a/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorFieldMapperTests.java +++ b/modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorFieldMapperTests.java @@ -359,7 +359,7 @@ public class PercolatorFieldMapperTests extends ESSingleNodeTestCase { .field("query_field2", queryBuilder) .endObject().bytes() ); - assertThat(doc.rootDoc().getFields().size(), equalTo(12)); // also includes all other meta fields + assertThat(doc.rootDoc().getFields().size(), equalTo(14)); // also includes all other meta fields BytesRef queryBuilderAsBytes = doc.rootDoc().getField("query_field1.query_builder_field").binaryValue(); assertQueryBuilder(queryBuilderAsBytes, queryBuilder); @@ -389,7 +389,7 @@ public class PercolatorFieldMapperTests extends ESSingleNodeTestCase { .field("query_field", queryBuilder) .endObject().endObject().bytes() ); - assertThat(doc.rootDoc().getFields().size(), equalTo(9)); // also includes all other meta fields + assertThat(doc.rootDoc().getFields().size(), equalTo(11)); // also includes all other meta fields BytesRef queryBuilderAsBytes = doc.rootDoc().getField("object_field.query_field.query_builder_field").binaryValue(); assertQueryBuilder(queryBuilderAsBytes, queryBuilder); @@ -400,7 +400,7 @@ public class PercolatorFieldMapperTests extends ESSingleNodeTestCase { .endArray() .endObject().bytes() ); - assertThat(doc.rootDoc().getFields().size(), equalTo(9)); // also includes all other meta fields + assertThat(doc.rootDoc().getFields().size(), equalTo(11)); // also includes all other meta fields queryBuilderAsBytes = doc.rootDoc().getField("object_field.query_field.query_builder_field").binaryValue(); assertQueryBuilder(queryBuilderAsBytes, queryBuilder); From 7f79c99e9a8f7cb79e9a0ad99e351e631784e555 Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Wed, 7 Dec 2016 12:09:09 -0500 Subject: [PATCH 5/5] Add descriptions to bulk tasks Related to #21768 --- .../org/elasticsearch/action/bulk/BulkRequest.java | 14 +++++++++++++- .../action/bulk/BulkShardRequest.java | 5 +++++ .../action/admin/cluster/node/tasks/TasksIT.java | 7 ++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java b/core/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java index 5351579278d..843e718a94e 100644 --- a/core/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java +++ b/core/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java @@ -48,9 +48,10 @@ import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import java.io.IOException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; +import java.util.Set; import static org.elasticsearch.action.ValidateActions.addValidationError; @@ -73,6 +74,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques * the one with the least casts. */ final List requests = new ArrayList<>(); + private final Set indices = new HashSet<>(); List payloads = null; protected TimeValue timeout = BulkShardRequest.DEFAULT_TIMEOUT; @@ -114,6 +116,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques } else { throw new IllegalArgumentException("No support for request [" + request + "]"); } + indices.add(request.index()); return this; } @@ -145,6 +148,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques addPayload(payload); // lack of source is validated in validate() method sizeInBytes += (request.source() != null ? request.source().length() : 0) + REQUEST_OVERHEAD; + indices.add(request.index()); return this; } @@ -172,6 +176,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques if (request.script() != null) { sizeInBytes += request.script().getIdOrCode().length() * 2; } + indices.add(request.index()); return this; } @@ -187,6 +192,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques requests.add(request); addPayload(payload); sizeInBytes += REQUEST_OVERHEAD; + indices.add(request.index()); return this; } @@ -548,4 +554,10 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques refreshPolicy.writeTo(out); timeout.writeTo(out); } + + @Override + public String getDescription() { + return "requests[" + requests.size() + "], indices[" + Strings.collectionToDelimitedString(indices, ", ") + "]"; + } + } diff --git a/core/src/main/java/org/elasticsearch/action/bulk/BulkShardRequest.java b/core/src/main/java/org/elasticsearch/action/bulk/BulkShardRequest.java index 25366d034ca..d53e9f8997e 100644 --- a/core/src/main/java/org/elasticsearch/action/bulk/BulkShardRequest.java +++ b/core/src/main/java/org/elasticsearch/action/bulk/BulkShardRequest.java @@ -100,6 +100,11 @@ public class BulkShardRequest extends ReplicatedWriteRequest { return b.toString(); } + @Override + public String getDescription() { + return "requests[" + items.length + "], index[" + index + "]"; + } + @Override public void onRetry() { for (BulkItemRequest item : items) { diff --git a/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TasksIT.java b/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TasksIT.java index 994cb3b4308..7f490ebab90 100644 --- a/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TasksIT.java +++ b/core/src/test/java/org/elasticsearch/action/admin/cluster/node/tasks/TasksIT.java @@ -303,7 +303,9 @@ public class TasksIT extends ESIntegTestCase { client().prepareBulk().add(client().prepareIndex("test", "doc", "test_id").setSource("{\"foo\": \"bar\"}")).get(); // the bulk operation should produce one main task - assertEquals(1, numberOfEvents(BulkAction.NAME, Tuple::v1)); + List topTask = findEvents(BulkAction.NAME, Tuple::v1); + assertEquals(1, topTask.size()); + assertEquals("requests[1], indices[test]", topTask.get(0).getDescription()); // we should also get 1 or 2 [s] operation with main operation as a parent // in case the primary is located on the coordinating node we will have 1 operation, otherwise - 2 @@ -317,17 +319,20 @@ public class TasksIT extends ESIntegTestCase { shardTask = shardTasks.get(0); // and it should have the main task as a parent assertParentTask(shardTask, findEvents(BulkAction.NAME, Tuple::v1).get(0)); + assertEquals("requests[1], index[test]", shardTask.getDescription()); } else { if (shardTasks.get(0).getParentTaskId().equals(shardTasks.get(1).getTaskId())) { // task 1 is the parent of task 0, that means that task 0 will control [s][p] and [s][r] tasks shardTask = shardTasks.get(0); // in turn the parent of the task 1 should be the main task assertParentTask(shardTasks.get(1), findEvents(BulkAction.NAME, Tuple::v1).get(0)); + assertEquals("requests[1], index[test]", shardTask.getDescription()); } else { // otherwise task 1 will control [s][p] and [s][r] tasks shardTask = shardTasks.get(1); // in turn the parent of the task 0 should be the main task assertParentTask(shardTasks.get(0), findEvents(BulkAction.NAME, Tuple::v1).get(0)); + assertEquals("requests[1], index[test]", shardTask.getDescription()); } }