Get max_seq_no after snapshot translog and Lucene (#45461)
We should capture max_seq_no after snapshotting translog and Lucene; otherwise, that max_seq_no can be smaller some operation in translog or Lucene. With this change, we also hold the Engine#writeLock during this check so that no indexing can happen. Closes #45454
This commit is contained in:
parent
adf8e20021
commit
24514275c7
|
@ -68,6 +68,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.util.BigArrays;
|
import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.common.util.set.Sets;
|
import org.elasticsearch.common.util.set.Sets;
|
||||||
|
import org.elasticsearch.common.util.concurrent.ReleasableLock;
|
||||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
@ -1075,42 +1076,47 @@ public abstract class EngineTestCase extends ESTestCase {
|
||||||
|| (engine instanceof InternalEngine) == false) {
|
|| (engine instanceof InternalEngine) == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final long maxSeqNo = ((InternalEngine) engine).getLocalCheckpointTracker().getMaxSeqNo();
|
// hold writeLock during this check so indexing can't happen
|
||||||
final List<Translog.Operation> translogOps = new ArrayList<>();
|
try (ReleasableLock ignored = engine.writeLock.acquire()) {
|
||||||
try (Translog.Snapshot snapshot = EngineTestCase.getTranslog(engine).newSnapshot()) {
|
final List<Translog.Operation> translogOps = new ArrayList<>();
|
||||||
Translog.Operation op;
|
try (Translog.Snapshot snapshot = EngineTestCase.getTranslog(engine).newSnapshot()) {
|
||||||
while ((op = snapshot.next()) != null) {
|
Translog.Operation op;
|
||||||
assertThat("translog operation [" + op + "] > max_seq_no[" + maxSeqNo + "]", op.seqNo(), lessThanOrEqualTo(maxSeqNo));
|
while ((op = snapshot.next()) != null) {
|
||||||
translogOps.add(op);
|
translogOps.add(op);
|
||||||
}
|
|
||||||
}
|
|
||||||
final Map<Long, Translog.Operation> luceneOps = readAllOperationsInLucene(engine, mapper).stream()
|
|
||||||
.collect(Collectors.toMap(Translog.Operation::seqNo, Function.identity()));
|
|
||||||
for (Translog.Operation op : luceneOps.values()) {
|
|
||||||
assertThat("lucene operation [" + op + "] > max_seq_no[" + maxSeqNo + "]", op.seqNo(), lessThanOrEqualTo(maxSeqNo));
|
|
||||||
}
|
|
||||||
final long globalCheckpoint = EngineTestCase.getTranslog(engine).getLastSyncedGlobalCheckpoint();
|
|
||||||
final long retainedOps = engine.config().getIndexSettings().getSoftDeleteRetentionOperations();
|
|
||||||
final long seqNoForRecovery;
|
|
||||||
try (Engine.IndexCommitRef safeCommit = engine.acquireSafeIndexCommit()) {
|
|
||||||
seqNoForRecovery = Long.parseLong(safeCommit.getIndexCommit().getUserData().get(SequenceNumbers.LOCAL_CHECKPOINT_KEY)) + 1;
|
|
||||||
}
|
|
||||||
final long minSeqNoToRetain = Math.min(seqNoForRecovery, globalCheckpoint + 1 - retainedOps);
|
|
||||||
for (Translog.Operation translogOp : translogOps) {
|
|
||||||
final Translog.Operation luceneOp = luceneOps.get(translogOp.seqNo());
|
|
||||||
if (luceneOp == null) {
|
|
||||||
if (minSeqNoToRetain <= translogOp.seqNo()) {
|
|
||||||
fail("Operation not found seq# [" + translogOp.seqNo() + "], global checkpoint [" + globalCheckpoint + "], " +
|
|
||||||
"retention policy [" + retainedOps + "], maxSeqNo [" + maxSeqNo + "], translog op [" + translogOp + "]");
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertThat(luceneOp, notNullValue());
|
final Map<Long, Translog.Operation> luceneOps = readAllOperationsInLucene(engine, mapper).stream()
|
||||||
assertThat(luceneOp.toString(), luceneOp.primaryTerm(), equalTo(translogOp.primaryTerm()));
|
.collect(Collectors.toMap(Translog.Operation::seqNo, Function.identity()));
|
||||||
assertThat(luceneOp.opType(), equalTo(translogOp.opType()));
|
final long maxSeqNo = ((InternalEngine) engine).getLocalCheckpointTracker().getMaxSeqNo();
|
||||||
if (luceneOp.opType() == Translog.Operation.Type.INDEX) {
|
for (Translog.Operation op : translogOps) {
|
||||||
assertThat(luceneOp.getSource().source, equalTo(translogOp.getSource().source));
|
assertThat("translog operation [" + op + "] > max_seq_no[" + maxSeqNo + "]", op.seqNo(), lessThanOrEqualTo(maxSeqNo));
|
||||||
|
}
|
||||||
|
for (Translog.Operation op : luceneOps.values()) {
|
||||||
|
assertThat("lucene operation [" + op + "] > max_seq_no[" + maxSeqNo + "]", op.seqNo(), lessThanOrEqualTo(maxSeqNo));
|
||||||
|
}
|
||||||
|
final long globalCheckpoint = EngineTestCase.getTranslog(engine).getLastSyncedGlobalCheckpoint();
|
||||||
|
final long retainedOps = engine.config().getIndexSettings().getSoftDeleteRetentionOperations();
|
||||||
|
final long seqNoForRecovery;
|
||||||
|
try (Engine.IndexCommitRef safeCommit = engine.acquireSafeIndexCommit()) {
|
||||||
|
seqNoForRecovery = Long.parseLong(safeCommit.getIndexCommit().getUserData().get(SequenceNumbers.LOCAL_CHECKPOINT_KEY)) + 1;
|
||||||
|
}
|
||||||
|
final long minSeqNoToRetain = Math.min(seqNoForRecovery, globalCheckpoint + 1 - retainedOps);
|
||||||
|
for (Translog.Operation translogOp : translogOps) {
|
||||||
|
final Translog.Operation luceneOp = luceneOps.get(translogOp.seqNo());
|
||||||
|
if (luceneOp == null) {
|
||||||
|
if (minSeqNoToRetain <= translogOp.seqNo()) {
|
||||||
|
fail("Operation not found seq# [" + translogOp.seqNo() + "], global checkpoint [" + globalCheckpoint + "], " +
|
||||||
|
"retention policy [" + retainedOps + "], maxSeqNo [" + maxSeqNo + "], translog op [" + translogOp + "]");
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertThat(luceneOp, notNullValue());
|
||||||
|
assertThat(luceneOp.toString(), luceneOp.primaryTerm(), equalTo(translogOp.primaryTerm()));
|
||||||
|
assertThat(luceneOp.opType(), equalTo(translogOp.opType()));
|
||||||
|
if (luceneOp.opType() == Translog.Operation.Type.INDEX) {
|
||||||
|
assertThat(luceneOp.getSource().source, equalTo(translogOp.getSource().source));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue