4747import org .apache .lucene .util .InfoStream ;
4848import org .elasticsearch .Assertions ;
4949import org .elasticsearch .ExceptionsHelper ;
50- import org .elasticsearch .Version ;
5150import org .elasticsearch .action .index .IndexRequest ;
5251import org .elasticsearch .common .Nullable ;
5352import org .elasticsearch .common .SuppressForbidden ;
@@ -146,6 +145,10 @@ public class InternalEngine extends Engine {
146145 private final AtomicLong maxUnsafeAutoIdTimestamp = new AtomicLong (-1 );
147146 private final AtomicLong maxSeenAutoIdTimestamp = new AtomicLong (-1 );
148147 private final AtomicLong maxSeqNoOfNonAppendOnlyOperations = new AtomicLong (SequenceNumbers .NO_OPS_PERFORMED );
148+ // max_seq_no_of_updates_or_deletes tracks the max seq_no of update or delete operations that have been processed in this engine.
149+ // An index request is considered as an update if it overwrites existing documents with the same docId in the Lucene index.
150+ // The value of this marker never goes backwards, and is tracked/updated differently on primary and replica.
151+ private final AtomicLong maxSeqNoOfUpdatesOrDeletes ;
149152 private final CounterMetric numVersionLookups = new CounterMetric ();
150153 private final CounterMetric numIndexVersionsLookups = new CounterMetric ();
151154 // Lucene operations since this engine was opened - not include operations from existing segments.
@@ -228,6 +231,7 @@ public InternalEngine(EngineConfig engineConfig) {
228231 () -> acquireSearcher ("create_local_checkpoint_tracker" , SearcherScope .INTERNAL ), localCheckpointTrackerSupplier );
229232 this .lastRefreshedCheckpointListener = new LastRefreshedCheckpointListener (localCheckpointTracker .getCheckpoint ());
230233 this .internalSearcherManager .addListener (lastRefreshedCheckpointListener );
234+ maxSeqNoOfUpdatesOrDeletes = new AtomicLong (SequenceNumbers .max (localCheckpointTracker .getMaxSeqNo (), translog .getMaxSeqNo ()));
231235 success = true ;
232236 } finally {
233237 if (success == false ) {
@@ -405,7 +409,6 @@ public InternalEngine recoverFromTranslog(TranslogRecoveryRunner translogRecover
405409 flushLock .lock ();
406410 try (ReleasableLock lock = readLock .acquire ()) {
407411 ensureOpen ();
408- assert getMaxSeqNoOfUpdatesOrDeletes () != SequenceNumbers .UNASSIGNED_SEQ_NO : "max_seq_no_of_updates is uninitialized" ;
409412 if (pendingTranslogRecovery .get () == false ) {
410413 throw new IllegalStateException ("Engine has already been recovered" );
411414 }
@@ -874,7 +877,7 @@ public IndexResult index(Index index) throws IOException {
874877
875878 final boolean toAppend = plan .indexIntoLucene && plan .useLuceneUpdateDocument == false ;
876879 if (toAppend == false ) {
877- advanceMaxSeqNoOfUpdatesOrDeletes (index .seqNo ());
880+ advanceMaxSeqNoOfUpdatesOrDeletesOnPrimary (index .seqNo ());
878881 }
879882 } else {
880883 markSeqNoAsSeen (index .seqNo ());
@@ -981,7 +984,6 @@ protected IndexingStrategy indexingStrategyForOperation(final Index index) throw
981984
982985 protected final IndexingStrategy planIndexingAsPrimary (Index index ) throws IOException {
983986 assert index .origin () == Operation .Origin .PRIMARY : "planing as primary but origin isn't. got " + index .origin ();
984- assert getMaxSeqNoOfUpdatesOrDeletes () != SequenceNumbers .UNASSIGNED_SEQ_NO : "max_seq_no_of_updates is not initialized" ;
985987 final IndexingStrategy plan ;
986988 // resolve an external operation into an internal one which is safe to replay
987989 if (canOptimizeAddDocument (index )) {
@@ -1322,7 +1324,6 @@ protected boolean assertNonPrimaryOrigin(final Operation operation) {
13221324
13231325 protected final DeletionStrategy planDeletionAsPrimary (Delete delete ) throws IOException {
13241326 assert delete .origin () == Operation .Origin .PRIMARY : "planing as primary but got " + delete .origin ();
1325- assert getMaxSeqNoOfUpdatesOrDeletes () != SequenceNumbers .UNASSIGNED_SEQ_NO : "max_seq_no_of_updates is not initialized" ;
13261327 // resolve operation from external to internal
13271328 final VersionValue versionValue = resolveDocVersion (delete , delete .getIfSeqNo () != SequenceNumbers .UNASSIGNED_SEQ_NO );
13281329 assert incrementVersionLookup ();
@@ -2718,13 +2719,22 @@ private void updateAutoIdTimestamp(long newTimestamp, boolean unsafe) {
27182719 assert maxUnsafeAutoIdTimestamp .get () <= maxSeenAutoIdTimestamp .get ();
27192720 }
27202721
2722+ @ Override
2723+ public long getMaxSeqNoOfUpdatesOrDeletes () {
2724+ return maxSeqNoOfUpdatesOrDeletes .get ();
2725+ }
2726+
2727+ @ Override
2728+ public void advanceMaxSeqNoOfUpdatesOrDeletes (long maxSeqNoOfUpdatesOnPrimary ) {
2729+ if (maxSeqNoOfUpdatesOnPrimary == SequenceNumbers .UNASSIGNED_SEQ_NO ) {
2730+ assert false : "max_seq_no_of_updates on primary is unassigned" ;
2731+ throw new IllegalArgumentException ("max_seq_no_of_updates on primary is unassigned" );
2732+ }
2733+ this .maxSeqNoOfUpdatesOrDeletes .updateAndGet (curr -> Math .max (curr , maxSeqNoOfUpdatesOnPrimary ));
2734+ }
2735+
27212736 private boolean assertMaxSeqNoOfUpdatesIsAdvanced (Term id , long seqNo , boolean allowDeleted , boolean relaxIfGapInSeqNo ) {
27222737 final long maxSeqNoOfUpdates = getMaxSeqNoOfUpdatesOrDeletes ();
2723- // If the primary is on an old version which does not replicate msu, we need to relax this assertion for that.
2724- if (maxSeqNoOfUpdates == SequenceNumbers .UNASSIGNED_SEQ_NO ) {
2725- assert config ().getIndexSettings ().getIndexVersionCreated ().before (Version .V_6_5_0 );
2726- return true ;
2727- }
27282738 // We treat a delete on the tombstones on replicas as a regular document, then use updateDocument (not addDocument).
27292739 if (allowDeleted ) {
27302740 final VersionValue versionValue = versionMap .getVersionForAssert (id .bytes ());
@@ -2742,12 +2752,6 @@ private boolean assertMaxSeqNoOfUpdatesIsAdvanced(Term id, long seqNo, boolean a
27422752 return true ;
27432753 }
27442754
2745- @ Override
2746- public void reinitializeMaxSeqNoOfUpdatesOrDeletes () {
2747- final long maxSeqNo = SequenceNumbers .max (localCheckpointTracker .getMaxSeqNo (), translog .getMaxSeqNo ());
2748- advanceMaxSeqNoOfUpdatesOrDeletes (maxSeqNo );
2749- }
2750-
27512755 private static void trimUnsafeCommits (EngineConfig engineConfig ) throws IOException {
27522756 final Store store = engineConfig .getStore ();
27532757 final String translogUUID = store .readLastCommittedSegmentsInfo ().getUserData ().get (Translog .TRANSLOG_UUID_KEY );
0 commit comments