Rather than performing a linear search downwards for a matching
log entry, take into account follower's last log index. This
eliminates the need for a lot of round-trips if the follower is
far behind the leader, but does not have a complete common ancestry.
Change-Id: I63c815f108d322de5d438a6eda43aaa7982d820a
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit
2659ea7bb9f51d216c2736a58ad86591380a9527)
}
/**
- * Decrements the value of the follower's next index.
+ * Decrements the value of the follower's next index, taking into account its reported last log index.
*
- * @return true if the next index was decremented, ie it was previously >= 0, false otherwise.
+ * @param followerLastIndex follower's last reported index.
+ * @return true if the next index was decremented, i.e. it was previously >= 0, false otherwise.
*/
- public boolean decrNextIndex() {
+ public boolean decrNextIndex(final long followerLastIndex) {
if (nextIndex < 0) {
return false;
}
- nextIndex--;
+ if (followerLastIndex >= 0 && nextIndex > followerLastIndex) {
+ // If the follower's last log index is lower than nextIndex, jump directly to it, so we converge
+ // on a common index more quickly.
+ nextIndex = followerLastIndex;
+ } else {
+ nextIndex--;
+ }
return true;
}
+ "updated: matchIndex: {}, nextIndex: {}", logName(), followerId,
followerLogInformation.getMatchIndex(), followerLogInformation.getNextIndex());
} else {
- // The follower's log conflicts with leader's log so decrement follower's next index by 1
+ // The follower's log conflicts with leader's log so decrement follower's next index
// in an attempt to find where the logs match.
-
- if (followerLogInformation.decrNextIndex()) {
+ if (followerLogInformation.decrNextIndex(appendEntriesReply.getLogLastIndex())) {
updated = true;
log.info("{}: follower {} last log term {} conflicts with the leader's {} - dec next index to {}",
FollowerLogInformation followerLogInformation =
new FollowerLogInformation(new PeerInfo("follower1", null, VotingState.VOTING), 1, context);
- assertTrue(followerLogInformation.decrNextIndex());
+ assertTrue(followerLogInformation.decrNextIndex(1));
assertEquals("getNextIndex", 0, followerLogInformation.getNextIndex());
- assertTrue(followerLogInformation.decrNextIndex());
+ assertTrue(followerLogInformation.decrNextIndex(1));
assertEquals("getNextIndex", -1, followerLogInformation.getNextIndex());
- assertFalse(followerLogInformation.decrNextIndex());
+ assertFalse(followerLogInformation.decrNextIndex(1));
assertEquals("getNextIndex", -1, followerLogInformation.getNextIndex());
}
}