Skip to content

Commit f6a4754

Browse files
committed
Store the reason of noop in its document tombstone (#30570)
Relates #29530
1 parent 60fb4ef commit f6a4754

File tree

8 files changed

+26
-14
lines changed

8 files changed

+26
-14
lines changed

server/src/main/java/org/elasticsearch/index/engine/EngineConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,9 @@ public interface TombstoneDocSupplier {
380380

381381
/**
382382
* Creates a tombstone document for a noop operation.
383+
* @param reason the reason of an a noop
383384
*/
384-
ParsedDocument newNoopTombstoneDoc();
385+
ParsedDocument newNoopTombstoneDoc(String reason);
385386
}
386387

387388
public TombstoneDocSupplier getTombstoneDocSupplier() {

server/src/main/java/org/elasticsearch/index/engine/InternalEngine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1406,7 +1406,7 @@ private NoOpResult innerNoOp(final NoOp noOp) throws IOException {
14061406
Exception failure = null;
14071407
if (softDeleteEnabled) {
14081408
try {
1409-
final ParsedDocument tombstone = engineConfig.getTombstoneDocSupplier().newNoopTombstoneDoc();
1409+
final ParsedDocument tombstone = engineConfig.getTombstoneDocSupplier().newNoopTombstoneDoc(noOp.reason());
14101410
tombstone.updateSeqID(noOp.seqNo(), noOp.primaryTerm());
14111411
// A noop tombstone does not require a _version but it's added to have a fully dense docvalues for the version field.
14121412
// 1L is selected to optimize the compression because it might probably be the most common value in version field.

server/src/main/java/org/elasticsearch/index/engine/LuceneChangesSnapshot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private Translog.Operation readDocAsOp(int docID) throws IOException {
186186
final Translog.Operation op;
187187
final boolean isTombstone = docValues[leaf.ord].isTombstone(segmentDocID);
188188
if (isTombstone && fields.uid() == null) {
189-
op = new Translog.NoOp(seqNo, primaryTerm, ""); // TODO: store reason in ignored fields?
189+
op = new Translog.NoOp(seqNo, primaryTerm, fields.source().utf8ToString());
190190
assert version == 1L : "Noop tombstone should have version 1L; actual version [" + version + "]";
191191
assert assertDocSoftDeleted(leaf.reader(), segmentDocID) : "Noop but soft_deletes field is not set [" + op + "]";
192192
} else {

server/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
package org.elasticsearch.index.mapper;
2121

22+
import org.apache.lucene.document.StoredField;
2223
import org.apache.lucene.index.LeafReaderContext;
2324
import org.apache.lucene.search.Query;
2425
import org.apache.lucene.search.Scorer;
2526
import org.apache.lucene.search.Weight;
27+
import org.apache.lucene.util.BytesRef;
2628
import org.elasticsearch.ElasticsearchGenerationException;
2729
import org.elasticsearch.common.bytes.BytesArray;
2830
import org.elasticsearch.common.compress.CompressedXContent;
@@ -279,10 +281,14 @@ public ParsedDocument createDeleteTombstoneDoc(String index, String type, String
279281
return documentParser.parseDocument(emptySource, deleteTombstoneMetadataFieldMappers).toTombstone();
280282
}
281283

282-
public ParsedDocument createNoopTombstoneDoc(String index) throws MapperParsingException {
284+
public ParsedDocument createNoopTombstoneDoc(String index, String reason) throws MapperParsingException {
283285
final String id = ""; // _id won't be used.
284-
final SourceToParse emptySource = SourceToParse.source(index, type, id, new BytesArray("{}"), XContentType.JSON);
285-
return documentParser.parseDocument(emptySource, noopTombstoneMetadataFieldMappers).toTombstone();
286+
final SourceToParse sourceToParse = SourceToParse.source(index, type, id, new BytesArray("{}"), XContentType.JSON);
287+
final ParsedDocument parsedDoc = documentParser.parseDocument(sourceToParse, noopTombstoneMetadataFieldMappers).toTombstone();
288+
// Store the reason of a noop as a raw string in the _source field
289+
final BytesRef byteRef = new BytesRef(reason);
290+
parsedDoc.rootDoc().add(new StoredField(SourceFieldMapper.NAME, byteRef.bytes, byteRef.offset, byteRef.length));
291+
return parsedDoc;
286292
}
287293

288294
/**

server/src/main/java/org/elasticsearch/index/shard/IndexShard.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,8 +2584,8 @@ public ParsedDocument newDeleteTombstoneDoc(String type, String id) {
25842584
return docMapper(type).getDocumentMapper().createDeleteTombstoneDoc(shardId.getIndexName(), type, id);
25852585
}
25862586
@Override
2587-
public ParsedDocument newNoopTombstoneDoc() {
2588-
return noopDocumentMapper.createNoopTombstoneDoc(shardId.getIndexName());
2587+
public ParsedDocument newNoopTombstoneDoc(String reason) {
2588+
return noopDocumentMapper.createNoopTombstoneDoc(shardId.getIndexName(), reason);
25892589
}
25902590
};
25912591
}

server/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3728,7 +3728,7 @@ protected long doGenerateSeqNoForOperation(Operation operation) {
37283728
};
37293729
noOpEngine.recoverFromTranslog();
37303730
final int gapsFilled = noOpEngine.fillSeqNoGaps(primaryTerm.get());
3731-
final String reason = randomAlphaOfLength(16);
3731+
final String reason = "filling gaps";
37323732
noOpEngine.noOp(new Engine.NoOp(maxSeqNo + 1, primaryTerm.get(), LOCAL_TRANSLOG_RECOVERY, System.nanoTime(), reason));
37333733
assertThat(noOpEngine.getLocalCheckpointTracker().getCheckpoint(), equalTo((long) (maxSeqNo + 1)));
37343734
assertThat(noOpEngine.getTranslog().stats().getUncommittedOperations(), equalTo(gapsFilled));
@@ -3754,7 +3754,7 @@ protected long doGenerateSeqNoForOperation(Operation operation) {
37543754
List<Translog.Operation> operationsFromLucene = readAllOperationsInLucene(noOpEngine, mapperService);
37553755
assertThat(operationsFromLucene, hasSize(maxSeqNo + 2 - localCheckpoint)); // fills n gap and 2 manual noop.
37563756
for (int i = 0; i < operationsFromLucene.size(); i++) {
3757-
assertThat(operationsFromLucene.get(i), equalTo(new Translog.NoOp(localCheckpoint + 1 + i, primaryTerm.get(), "")));
3757+
assertThat(operationsFromLucene.get(i), equalTo(new Translog.NoOp(localCheckpoint + 1 + i, primaryTerm.get(), "filling gaps")));
37583758
}
37593759
assertConsistentHistoryBetweenTranslogAndLuceneIndex(noOpEngine, mapperService);
37603760
} finally {

server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.lucene.search.TopDocs;
3030
import org.apache.lucene.store.AlreadyClosedException;
3131
import org.apache.lucene.store.IOContext;
32+
import org.apache.lucene.util.BytesRef;
3233
import org.apache.lucene.util.Constants;
3334
import org.elasticsearch.Version;
3435
import org.elasticsearch.action.ActionListener;
@@ -75,7 +76,6 @@
7576
import org.elasticsearch.index.VersionType;
7677
import org.elasticsearch.index.engine.Engine;
7778
import org.elasticsearch.index.engine.EngineException;
78-
import org.elasticsearch.index.engine.EngineTestCase;
7979
import org.elasticsearch.index.engine.InternalEngine;
8080
import org.elasticsearch.index.engine.InternalEngineFactory;
8181
import org.elasticsearch.index.engine.Segment;
@@ -89,6 +89,7 @@
8989
import org.elasticsearch.index.mapper.ParseContext;
9090
import org.elasticsearch.index.mapper.ParsedDocument;
9191
import org.elasticsearch.index.mapper.SeqNoFieldMapper;
92+
import org.elasticsearch.index.mapper.SourceFieldMapper;
9293
import org.elasticsearch.index.mapper.SourceToParse;
9394
import org.elasticsearch.index.mapper.Uid;
9495
import org.elasticsearch.index.mapper.VersionFieldMapper;
@@ -2963,13 +2964,15 @@ public void testSupplyTombstoneDoc() throws Exception {
29632964
assertThat(deleteDoc.getField(IdFieldMapper.NAME).binaryValue(), equalTo(Uid.encodeId(id)));
29642965
assertThat(deleteDoc.getField(SeqNoFieldMapper.TOMBSTONE_NAME).numericValue().longValue(), equalTo(1L));
29652966

2966-
ParsedDocument noopTombstone = shard.getEngine().config().getTombstoneDocSupplier().newNoopTombstoneDoc();
2967+
final String reason = randomUnicodeOfLength(200);
2968+
ParsedDocument noopTombstone = shard.getEngine().config().getTombstoneDocSupplier().newNoopTombstoneDoc(reason);
29672969
assertThat(noopTombstone.docs(), hasSize(1));
29682970
ParseContext.Document noopDoc = noopTombstone.docs().get(0);
29692971
assertThat(noopDoc.getFields().stream().map(IndexableField::name).collect(Collectors.toList()),
2970-
containsInAnyOrder(VersionFieldMapper.NAME, SeqNoFieldMapper.TOMBSTONE_NAME,
2972+
containsInAnyOrder(VersionFieldMapper.NAME, SourceFieldMapper.NAME, SeqNoFieldMapper.TOMBSTONE_NAME,
29712973
SeqNoFieldMapper.NAME, SeqNoFieldMapper.NAME, SeqNoFieldMapper.PRIMARY_TERM_NAME));
29722974
assertThat(noopDoc.getField(SeqNoFieldMapper.TOMBSTONE_NAME).numericValue().longValue(), equalTo(1L));
2975+
assertThat(noopDoc.getField(SourceFieldMapper.NAME).binaryValue(), equalTo(new BytesRef(reason)));
29732976

29742977
closeShards(shard);
29752978
}

test/framework/src/main/java/org/elasticsearch/index/engine/EngineTestCase.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ public ParsedDocument newDeleteTombstoneDoc(String type, String id) {
307307
}
308308

309309
@Override
310-
public ParsedDocument newNoopTombstoneDoc() {
310+
public ParsedDocument newNoopTombstoneDoc(String reason) {
311311
final ParseContext.Document doc = new ParseContext.Document();
312312
SeqNoFieldMapper.SequenceIDFields seqID = SeqNoFieldMapper.SequenceIDFields.emptySeqID();
313313
doc.add(seqID.seqNo);
@@ -317,6 +317,8 @@ public ParsedDocument newNoopTombstoneDoc() {
317317
doc.add(seqID.tombstoneField);
318318
Field versionField = new NumericDocValuesField(VersionFieldMapper.NAME, 0);
319319
doc.add(versionField);
320+
BytesRef byteRef = new BytesRef(reason);
321+
doc.add(new StoredField(SourceFieldMapper.NAME, byteRef.bytes, byteRef.offset, byteRef.length));
320322
return new ParsedDocument(versionField, seqID, null, null, null,
321323
Collections.singletonList(doc), null, XContentType.JSON, null);
322324
}

0 commit comments

Comments
 (0)