-
Notifications
You must be signed in to change notification settings - Fork 24.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sequence numbers commit data for Lucene uses Iterable interface #20793
Changes from 4 commits
a014f55
1d63334
d396c7e
2ca919b
2656776
27532b1
9a62fba
70ec8f0
ca4ec96
61ee155
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,6 +124,7 @@ | |
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.concurrent.BrokenBarrierException; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.CyclicBarrier; | ||
|
@@ -138,6 +139,7 @@ | |
import static org.hamcrest.Matchers.equalTo; | ||
import static org.hamcrest.Matchers.everyItem; | ||
import static org.hamcrest.Matchers.greaterThan; | ||
import static org.hamcrest.Matchers.greaterThanOrEqualTo; | ||
import static org.hamcrest.Matchers.hasKey; | ||
import static org.hamcrest.Matchers.not; | ||
import static org.hamcrest.Matchers.notNullValue; | ||
|
@@ -583,6 +585,10 @@ public SequenceNumbersService seqNoService() { | |
assertThat( | ||
Long.parseLong(stats1.getUserData().get(InternalEngine.GLOBAL_CHECKPOINT_KEY)), | ||
equalTo(SequenceNumbersService.UNASSIGNED_SEQ_NO)); | ||
assertThat(stats1.getUserData(), hasKey(InternalEngine.MAX_SEQ_NO)); | ||
assertThat( | ||
Long.parseLong(stats1.getUserData().get(InternalEngine.MAX_SEQ_NO)), | ||
equalTo(SequenceNumbersService.NO_OPS_PERFORMED)); | ||
|
||
maxSeqNo.set(rarely() ? SequenceNumbersService.NO_OPS_PERFORMED : randomIntBetween(0, 1024)); | ||
localCheckpoint.set( | ||
|
@@ -608,6 +614,8 @@ public SequenceNumbersService seqNoService() { | |
assertThat( | ||
Long.parseLong(stats2.getUserData().get(InternalEngine.GLOBAL_CHECKPOINT_KEY)), | ||
equalTo(globalCheckpoint.get())); | ||
assertThat(stats2.getUserData(), hasKey(InternalEngine.MAX_SEQ_NO)); | ||
assertThat(Long.parseLong(stats2.getUserData().get(InternalEngine.MAX_SEQ_NO)), equalTo(maxSeqNo.get())); | ||
} finally { | ||
IOUtils.close(engine); | ||
} | ||
|
@@ -1618,13 +1626,14 @@ public void testIndexWriterInfoStream() throws IllegalAccessException { | |
} | ||
|
||
public void testSeqNoAndCheckpoints() throws IOException { | ||
// nocommit: does not test deletes | ||
final int opCount = randomIntBetween(1, 256); | ||
long primarySeqNo = SequenceNumbersService.NO_OPS_PERFORMED; | ||
final String[] ids = new String[]{"1", "2", "3"}; | ||
final Set<String> indexedIds = new HashSet<>(); | ||
long localCheckpoint = SequenceNumbersService.NO_OPS_PERFORMED; | ||
long replicaLocalCheckpoint = SequenceNumbersService.NO_OPS_PERFORMED; | ||
long globalCheckpoint = SequenceNumbersService.UNASSIGNED_SEQ_NO; | ||
long maxSeqNo = SequenceNumbersService.NO_OPS_PERFORMED; | ||
InternalEngine initialEngine = null; | ||
|
||
try { | ||
|
@@ -1633,26 +1642,61 @@ public void testSeqNoAndCheckpoints() throws IOException { | |
.seqNoService() | ||
.updateAllocationIdsFromMaster(new HashSet<>(Arrays.asList("primary", "replica")), Collections.emptySet()); | ||
for (int op = 0; op < opCount; op++) { | ||
final String id = randomFrom(ids); | ||
ParsedDocument doc = testParsedDocument("test#" + id, id, "test", null, -1, -1, testDocumentWithTextField(), SOURCE, null); | ||
final Engine.Index index = new Engine.Index(newUid("test#" + id), doc, | ||
SequenceNumbersService.UNASSIGNED_SEQ_NO, | ||
rarely() ? 100 : Versions.MATCH_ANY, VersionType.INTERNAL, | ||
PRIMARY, 0, -1, false); | ||
try { | ||
initialEngine.index(index); | ||
final String id; | ||
boolean versionConflict = false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ++ |
||
// mostly index, sometimes delete | ||
if (rarely() && indexedIds.isEmpty() == false) { | ||
// we have some docs indexed, so delete one of them | ||
id = randomFrom(indexedIds); | ||
final Engine.Delete delete = new Engine.Delete( | ||
"test", id, newUid("test#" + id), SequenceNumbersService.UNASSIGNED_SEQ_NO, | ||
rarely() ? 100 : Versions.MATCH_ANY, VersionType.INTERNAL, PRIMARY, 0, false); | ||
try { | ||
initialEngine.delete(delete); | ||
indexedIds.remove(id); | ||
} catch (VersionConflictEngineException e) { | ||
versionConflict = true; | ||
} | ||
} else { | ||
// index a document | ||
id = randomFrom(ids); | ||
ParsedDocument doc = testParsedDocument("test#" + id, id, "test", null, -1, -1, testDocumentWithTextField(), SOURCE, null); | ||
final Engine.Index index = new Engine.Index(newUid("test#" + id), doc, | ||
SequenceNumbersService.UNASSIGNED_SEQ_NO, | ||
rarely() ? 100 : Versions.MATCH_ANY, VersionType.INTERNAL, | ||
PRIMARY, 0, -1, false); | ||
try { | ||
initialEngine.index(index); | ||
indexedIds.add(id); | ||
} catch (VersionConflictEngineException e) { | ||
versionConflict = true; | ||
} | ||
} | ||
if (versionConflict == false) { | ||
primarySeqNo++; | ||
} catch (VersionConflictEngineException e) { | ||
|
||
} | ||
|
||
replicaLocalCheckpoint = | ||
rarely() ? replicaLocalCheckpoint : randomIntBetween(Math.toIntExact(replicaLocalCheckpoint), Math.toIntExact(primarySeqNo)); | ||
initialEngine.seqNoService().updateLocalCheckpointForShard("primary", initialEngine.seqNoService().getLocalCheckpoint()); | ||
initialEngine.seqNoService().updateLocalCheckpointForShard("replica", replicaLocalCheckpoint); | ||
|
||
// make sure the max seq no in the latest commit hasn't advanced due to more documents having been added; | ||
// the first time the commit data iterable gets an iterator, the max seq no from that point in time should | ||
// remain from any subsequent call to IndexWriter#getLiveCommitData unless the commit data is overwritten by a | ||
// subsequent call to IndexWriter#setLiveCommitData. | ||
assertThat( | ||
initialEngine.seqNoService().getMaxSeqNo(), | ||
// its possible we haven't indexed any documents yet, or its possible that right after a commit, a version conflict | ||
// exception happened so the max seq no was not updated, so here we check greater than or equal to | ||
initialEngine.seqNoService().getMaxSeqNo() != SequenceNumbersService.NO_OPS_PERFORMED || versionConflict ? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure we need this extra check? what were you aiming at testing ? feels like it's for the time we had caching? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It isn't asserting anything relevant about the saved commit data any longer, so I'm removing it |
||
greaterThanOrEqualTo(initialEngine.loadSeqNoStatsFromCommit().getMaxSeqNo()) : | ||
greaterThan(initialEngine.loadSeqNoStatsFromCommit().getMaxSeqNo()) | ||
); | ||
|
||
if (rarely()) { | ||
localCheckpoint = primarySeqNo; | ||
maxSeqNo = primarySeqNo; | ||
globalCheckpoint = replicaLocalCheckpoint; | ||
initialEngine.seqNoService().updateGlobalCheckpointOnPrimary(); | ||
initialEngine.flush(true, true); | ||
|
@@ -1661,6 +1705,7 @@ public void testSeqNoAndCheckpoints() throws IOException { | |
|
||
initialEngine.seqNoService().updateGlobalCheckpointOnPrimary(); | ||
|
||
assertEquals(primarySeqNo, initialEngine.seqNoService().getMaxSeqNo()); | ||
assertThat(initialEngine.seqNoService().stats().getMaxSeqNo(), equalTo(primarySeqNo)); | ||
assertThat(initialEngine.seqNoService().stats().getLocalCheckpoint(), equalTo(primarySeqNo)); | ||
assertThat(initialEngine.seqNoService().stats().getGlobalCheckpoint(), equalTo(replicaLocalCheckpoint)); | ||
|
@@ -1671,6 +1716,9 @@ public void testSeqNoAndCheckpoints() throws IOException { | |
assertThat( | ||
Long.parseLong(initialEngine.commitStats().getUserData().get(InternalEngine.GLOBAL_CHECKPOINT_KEY)), | ||
equalTo(globalCheckpoint)); | ||
assertThat( | ||
Long.parseLong(initialEngine.commitStats().getUserData().get(InternalEngine.MAX_SEQ_NO)), | ||
equalTo(maxSeqNo)); | ||
|
||
} finally { | ||
IOUtils.close(initialEngine); | ||
|
@@ -1681,12 +1729,17 @@ public void testSeqNoAndCheckpoints() throws IOException { | |
recoveringEngine = new InternalEngine(copy(initialEngine.config(), EngineConfig.OpenMode.OPEN_INDEX_AND_TRANSLOG)); | ||
recoveringEngine.recoverFromTranslog(); | ||
|
||
assertEquals(primarySeqNo, recoveringEngine.seqNoService().getMaxSeqNo()); | ||
assertThat( | ||
Long.parseLong(recoveringEngine.commitStats().getUserData().get(InternalEngine.LOCAL_CHECKPOINT_KEY)), | ||
equalTo(primarySeqNo)); | ||
assertThat( | ||
Long.parseLong(recoveringEngine.commitStats().getUserData().get(InternalEngine.GLOBAL_CHECKPOINT_KEY)), | ||
equalTo(globalCheckpoint)); | ||
assertThat( | ||
Long.parseLong(recoveringEngine.commitStats().getUserData().get(InternalEngine.MAX_SEQ_NO)), | ||
// after recovering from translog, all docs have been flushed to Lucene segments, so check against primarySeqNo | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure I follow this comment? can you elaborate? |
||
equalTo(primarySeqNo)); | ||
assertThat(recoveringEngine.seqNoService().stats().getLocalCheckpoint(), equalTo(primarySeqNo)); | ||
assertThat(recoveringEngine.seqNoService().stats().getMaxSeqNo(), equalTo(primarySeqNo)); | ||
assertThat(recoveringEngine.seqNoService().generateSeqNo(), equalTo(primarySeqNo + 1)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like we need this cashing because we load user data from the index writer. maybe we can use
lastCommittedSegmentInfos
, which can be read earlier when opening the engine?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bleskes I agree with using
lastCommittedSegmentInfos
from the engine as a solution, but my concern here was that basically we have to document and ensure that no one usesIndexWriter#getLiveCommitData
or depends on it for accurate information, otherwise the max_seq_no could be different than what is actually stored in the commit. That's why I added the caching part, which does increase complexity. Do you prefer I remove it and just document that we should never callIndexWriter#getLiveCommitData
inside ES code?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's OK to not use
IndexWriter#getLiveCommitData
- as it may not return what's in the last commit. I suspect this is why it was renamed to saylive
in the name. Is there anything specific you are concerned about?