@@ -723,14 +723,13 @@ public void testTranslogRecoveryDoesNotReplayIntoTranslog() throws IOException {
723
723
recoveringEngine = new InternalEngine (copy (initialEngine .config (), EngineConfig .OpenMode .OPEN_INDEX_AND_TRANSLOG )) {
724
724
@ Override
725
725
public CommitId flush (boolean force , boolean waitIfOngoing ) throws EngineException {
726
- assertThat (getTranslog ().uncommittedOperations (), equalTo (docs ));
726
+ assertThat (getTranslog ().stats (). getUncommittedOperations (), equalTo (docs ));
727
727
final CommitId commitId = super .flush (force , waitIfOngoing );
728
728
flushed .set (true );
729
729
return commitId ;
730
730
}
731
731
};
732
-
733
- assertThat (recoveringEngine .getTranslog ().uncommittedOperations (), equalTo (docs ));
732
+ assertThat (recoveringEngine .getTranslog ().stats ().getUncommittedOperations (), equalTo (docs ));
734
733
recoveringEngine .recoverFromTranslog ();
735
734
assertTrue (flushed .get ());
736
735
} finally {
@@ -2884,7 +2883,7 @@ public void testCurrentTranslogIDisCommitted() throws IOException {
2884
2883
assertEquals (engine .getTranslog ().getTranslogUUID (), userData .get (Translog .TRANSLOG_UUID_KEY ));
2885
2884
expectThrows (IllegalStateException .class , () -> engine .recoverFromTranslog ());
2886
2885
assertEquals (1 , engine .getTranslog ().currentFileGeneration ());
2887
- assertEquals (0L , engine .getTranslog ().uncommittedOperations ());
2886
+ assertEquals (0L , engine .getTranslog ().stats (). getUncommittedOperations ());
2888
2887
}
2889
2888
}
2890
2889
@@ -3840,7 +3839,7 @@ protected long doGenerateSeqNoForOperation(Operation operation) {
3840
3839
System .nanoTime (),
3841
3840
reason ));
3842
3841
assertThat (noOpEngine .getLocalCheckpointTracker ().getCheckpoint (), equalTo ((long ) (maxSeqNo + 1 )));
3843
- assertThat (noOpEngine .getTranslog ().uncommittedOperations (), equalTo (1 + gapsFilled ));
3842
+ assertThat (noOpEngine .getTranslog ().stats (). getUncommittedOperations (), equalTo (1 + gapsFilled ));
3844
3843
// skip to the op that we added to the translog
3845
3844
Translog .Operation op ;
3846
3845
Translog .Operation last = null ;
@@ -4041,7 +4040,7 @@ public void testFillUpSequenceIdGapsOnRecovery() throws IOException {
4041
4040
assertEquals (checkpointOnReplica , replicaEngine .getLocalCheckpointTracker ().getCheckpoint ());
4042
4041
recoveringEngine = new InternalEngine (copy (
4043
4042
replicaEngine .config (), EngineConfig .OpenMode .OPEN_INDEX_AND_TRANSLOG , globalCheckpoint ::get ));
4044
- assertEquals (numDocsOnReplica , recoveringEngine .getTranslog ().uncommittedOperations ());
4043
+ assertEquals (numDocsOnReplica , recoveringEngine .getTranslog ().stats (). getUncommittedOperations ());
4045
4044
recoveringEngine .recoverFromTranslog ();
4046
4045
assertEquals (maxSeqIDOnReplica , recoveringEngine .getLocalCheckpointTracker ().getMaxSeqNo ());
4047
4046
assertEquals (checkpointOnReplica , recoveringEngine .getLocalCheckpointTracker ().getCheckpoint ());
@@ -4076,7 +4075,7 @@ public void testFillUpSequenceIdGapsOnRecovery() throws IOException {
4076
4075
recoveringEngine = new InternalEngine (
4077
4076
copy (replicaEngine .config (), EngineConfig .OpenMode .OPEN_INDEX_AND_TRANSLOG , globalCheckpoint ::get ));
4078
4077
if (flushed ) {
4079
- assertEquals ( 0 , recoveringEngine .getTranslog ().uncommittedOperations ( ));
4078
+ assertThat ( recoveringEngine .getTranslog ().stats (). getUncommittedOperations (), equalTo ( 0 ));
4080
4079
}
4081
4080
recoveringEngine .recoverFromTranslog ();
4082
4081
assertEquals (maxSeqIDOnReplica , recoveringEngine .getLocalCheckpointTracker ().getMaxSeqNo ());
@@ -4451,31 +4450,71 @@ public void testShouldPeriodicallyFlush() throws Exception {
4451
4450
engine .index (indexForDoc (doc ));
4452
4451
}
4453
4452
assertThat ("Not exceeded translog flush threshold yet" , engine .shouldPeriodicallyFlush (), equalTo (false ));
4454
- long flushThreshold = RandomNumbers .randomLongBetween (random (), 100 , engine .getTranslog ().uncommittedSizeInBytes ());
4453
+ long flushThreshold = RandomNumbers .randomLongBetween (random (), 100 , engine .getTranslog ().stats (). getUncommittedSizeInBytes ());
4455
4454
final IndexSettings indexSettings = engine .config ().getIndexSettings ();
4456
4455
final IndexMetaData indexMetaData = IndexMetaData .builder (indexSettings .getIndexMetaData ())
4457
4456
.settings (Settings .builder ().put (indexSettings .getSettings ())
4458
4457
.put (IndexSettings .INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE_SETTING .getKey (), flushThreshold + "b" )).build ();
4459
4458
indexSettings .updateIndexMetaData (indexMetaData );
4460
4459
engine .onSettingsChanged ();
4461
- assertThat (engine .getTranslog ().uncommittedOperations (), equalTo (numDocs ));
4460
+ assertThat (engine .getTranslog ().stats (). getUncommittedOperations (), equalTo (numDocs ));
4462
4461
assertThat (engine .shouldPeriodicallyFlush (), equalTo (true ));
4463
4462
engine .flush ();
4464
- assertThat (engine .getTranslog ().uncommittedOperations (), equalTo (0 ));
4463
+ assertThat (engine .getTranslog ().stats (). getUncommittedOperations (), equalTo (0 ));
4465
4464
// Stale operations skipped by Lucene but added to translog - still able to flush
4466
4465
for (int id = 0 ; id < numDocs ; id ++) {
4467
4466
final ParsedDocument doc = testParsedDocument (Integer .toString (id ), null , testDocumentWithTextField (), SOURCE , null );
4468
4467
final Engine .IndexResult result = engine .index (replicaIndexForDoc (doc , 1L , id , false ));
4469
4468
assertThat (result .isCreated (), equalTo (false ));
4470
4469
}
4471
4470
SegmentInfos lastCommitInfo = engine .getLastCommittedSegmentInfos ();
4472
- assertThat (engine .getTranslog ().uncommittedOperations (), equalTo (numDocs ));
4471
+ assertThat (engine .getTranslog ().stats (). getUncommittedOperations (), equalTo (numDocs ));
4473
4472
assertThat (engine .shouldPeriodicallyFlush (), equalTo (true ));
4474
4473
engine .flush (false , false );
4475
4474
assertThat (engine .getLastCommittedSegmentInfos (), not (sameInstance (lastCommitInfo )));
4476
- assertThat (engine .getTranslog ().uncommittedOperations (), equalTo (0 ));
4475
+ assertThat (engine .getTranslog ().stats ().getUncommittedOperations (), equalTo (0 ));
4476
+ // If the new index commit still points to the same translog generation as the current index commit,
4477
+ // we should not enable the periodically flush condition; otherwise we can get into an infinite loop of flushes.
4478
+ engine .getLocalCheckpointTracker ().generateSeqNo (); // create a gap here
4479
+ for (int id = 0 ; id < numDocs ; id ++) {
4480
+ if (randomBoolean ()) {
4481
+ engine .getTranslog ().rollGeneration ();
4482
+ }
4483
+ final ParsedDocument doc = testParsedDocument ("new" + id , null , testDocumentWithTextField (), SOURCE , null );
4484
+ engine .index (replicaIndexForDoc (doc , 2L , engine .getLocalCheckpointTracker ().generateSeqNo (), false ));
4485
+ if (engine .shouldPeriodicallyFlush ()) {
4486
+ engine .flush ();
4487
+ assertThat (engine .getLastCommittedSegmentInfos (), not (sameInstance (lastCommitInfo )));
4488
+ assertThat (engine .shouldPeriodicallyFlush (), equalTo (false ));
4489
+ }
4490
+ }
4477
4491
}
4478
4492
4493
+ public void testStressShouldPeriodicallyFlush () throws Exception {
4494
+ final long flushThreshold = randomLongBetween (100 , 5000 );
4495
+ final long generationThreshold = randomLongBetween (1000 , 5000 );
4496
+ final IndexSettings indexSettings = engine .config ().getIndexSettings ();
4497
+ final IndexMetaData indexMetaData = IndexMetaData .builder (indexSettings .getIndexMetaData ())
4498
+ .settings (Settings .builder ().put (indexSettings .getSettings ())
4499
+ .put (IndexSettings .INDEX_TRANSLOG_GENERATION_THRESHOLD_SIZE_SETTING .getKey (), generationThreshold + "b" )
4500
+ .put (IndexSettings .INDEX_TRANSLOG_FLUSH_THRESHOLD_SIZE_SETTING .getKey (), flushThreshold + "b" )).build ();
4501
+ indexSettings .updateIndexMetaData (indexMetaData );
4502
+ engine .onSettingsChanged ();
4503
+ final int numOps = scaledRandomIntBetween (100 , 10_000 );
4504
+ for (int i = 0 ; i < numOps ; i ++) {
4505
+ final long localCheckPoint = engine .getLocalCheckpointTracker ().getCheckpoint ();
4506
+ final long seqno = randomLongBetween (Math .max (0 , localCheckPoint ), localCheckPoint + 5 );
4507
+ final ParsedDocument doc = testParsedDocument (Long .toString (seqno ), null , testDocumentWithTextField (), SOURCE , null );
4508
+ engine .index (replicaIndexForDoc (doc , 1L , seqno , false ));
4509
+ if (rarely () && engine .getTranslog ().shouldRollGeneration ()) {
4510
+ engine .rollTranslogGeneration ();
4511
+ }
4512
+ if (rarely () || engine .shouldPeriodicallyFlush ()) {
4513
+ engine .flush ();
4514
+ assertThat (engine .shouldPeriodicallyFlush (), equalTo (false ));
4515
+ }
4516
+ }
4517
+ }
4479
4518
4480
4519
public void testStressUpdateSameDocWhileGettingIt () throws IOException , InterruptedException {
4481
4520
final int iters = randomIntBetween (1 , 15 );
0 commit comments