47
47
import org .apache .lucene .util .InfoStream ;
48
48
import org .elasticsearch .Assertions ;
49
49
import org .elasticsearch .ExceptionsHelper ;
50
- import org .elasticsearch .Version ;
51
50
import org .elasticsearch .action .index .IndexRequest ;
52
51
import org .elasticsearch .common .Nullable ;
53
52
import org .elasticsearch .common .SuppressForbidden ;
@@ -146,6 +145,10 @@ public class InternalEngine extends Engine {
146
145
private final AtomicLong maxUnsafeAutoIdTimestamp = new AtomicLong (-1 );
147
146
private final AtomicLong maxSeenAutoIdTimestamp = new AtomicLong (-1 );
148
147
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 ;
149
152
private final CounterMetric numVersionLookups = new CounterMetric ();
150
153
private final CounterMetric numIndexVersionsLookups = new CounterMetric ();
151
154
// Lucene operations since this engine was opened - not include operations from existing segments.
@@ -228,6 +231,7 @@ public InternalEngine(EngineConfig engineConfig) {
228
231
() -> acquireSearcher ("create_local_checkpoint_tracker" , SearcherScope .INTERNAL ), localCheckpointTrackerSupplier );
229
232
this .lastRefreshedCheckpointListener = new LastRefreshedCheckpointListener (localCheckpointTracker .getCheckpoint ());
230
233
this .internalSearcherManager .addListener (lastRefreshedCheckpointListener );
234
+ maxSeqNoOfUpdatesOrDeletes = new AtomicLong (SequenceNumbers .max (localCheckpointTracker .getMaxSeqNo (), translog .getMaxSeqNo ()));
231
235
success = true ;
232
236
} finally {
233
237
if (success == false ) {
@@ -405,7 +409,6 @@ public InternalEngine recoverFromTranslog(TranslogRecoveryRunner translogRecover
405
409
flushLock .lock ();
406
410
try (ReleasableLock lock = readLock .acquire ()) {
407
411
ensureOpen ();
408
- assert getMaxSeqNoOfUpdatesOrDeletes () != SequenceNumbers .UNASSIGNED_SEQ_NO : "max_seq_no_of_updates is uninitialized" ;
409
412
if (pendingTranslogRecovery .get () == false ) {
410
413
throw new IllegalStateException ("Engine has already been recovered" );
411
414
}
@@ -874,7 +877,7 @@ public IndexResult index(Index index) throws IOException {
874
877
875
878
final boolean toAppend = plan .indexIntoLucene && plan .useLuceneUpdateDocument == false ;
876
879
if (toAppend == false ) {
877
- advanceMaxSeqNoOfUpdatesOrDeletes (index .seqNo ());
880
+ advanceMaxSeqNoOfUpdatesOrDeletesOnPrimary (index .seqNo ());
878
881
}
879
882
} else {
880
883
markSeqNoAsSeen (index .seqNo ());
@@ -981,7 +984,6 @@ protected IndexingStrategy indexingStrategyForOperation(final Index index) throw
981
984
982
985
protected final IndexingStrategy planIndexingAsPrimary (Index index ) throws IOException {
983
986
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" ;
985
987
final IndexingStrategy plan ;
986
988
// resolve an external operation into an internal one which is safe to replay
987
989
if (canOptimizeAddDocument (index )) {
@@ -1322,7 +1324,6 @@ protected boolean assertNonPrimaryOrigin(final Operation operation) {
1322
1324
1323
1325
protected final DeletionStrategy planDeletionAsPrimary (Delete delete ) throws IOException {
1324
1326
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" ;
1326
1327
// resolve operation from external to internal
1327
1328
final VersionValue versionValue = resolveDocVersion (delete , delete .getIfSeqNo () != SequenceNumbers .UNASSIGNED_SEQ_NO );
1328
1329
assert incrementVersionLookup ();
@@ -2718,13 +2719,22 @@ private void updateAutoIdTimestamp(long newTimestamp, boolean unsafe) {
2718
2719
assert maxUnsafeAutoIdTimestamp .get () <= maxSeenAutoIdTimestamp .get ();
2719
2720
}
2720
2721
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
+
2721
2736
private boolean assertMaxSeqNoOfUpdatesIsAdvanced (Term id , long seqNo , boolean allowDeleted , boolean relaxIfGapInSeqNo ) {
2722
2737
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
- }
2728
2738
// We treat a delete on the tombstones on replicas as a regular document, then use updateDocument (not addDocument).
2729
2739
if (allowDeleted ) {
2730
2740
final VersionValue versionValue = versionMap .getVersionForAssert (id .bytes ());
@@ -2742,12 +2752,6 @@ private boolean assertMaxSeqNoOfUpdatesIsAdvanced(Term id, long seqNo, boolean a
2742
2752
return true ;
2743
2753
}
2744
2754
2745
- @ Override
2746
- public void reinitializeMaxSeqNoOfUpdatesOrDeletes () {
2747
- final long maxSeqNo = SequenceNumbers .max (localCheckpointTracker .getMaxSeqNo (), translog .getMaxSeqNo ());
2748
- advanceMaxSeqNoOfUpdatesOrDeletes (maxSeqNo );
2749
- }
2750
-
2751
2755
private static void trimUnsafeCommits (EngineConfig engineConfig ) throws IOException {
2752
2756
final Store store = engineConfig .getStore ();
2753
2757
final String translogUUID = store .readLastCommittedSegmentsInfo ().getUserData ().get (Translog .TRANSLOG_UUID_KEY );
0 commit comments