@@ -769,7 +769,6 @@ func (r *raft) reset(term uint64) {
769
769
r .Vote = None
770
770
}
771
771
r .lead = None
772
- r .logSynced = false
773
772
774
773
r .electionElapsed = 0
775
774
r .heartbeatElapsed = 0
@@ -873,10 +872,6 @@ func (r *raft) becomeFollower(term uint64, lead uint64) {
873
872
r .reset (term )
874
873
r .tick = r .tickElection
875
874
r .lead = lead
876
- // If the last entry term matches the leader term, the log is guaranteed to be
877
- // a prefix of the leader's log. Otherwise, we will establish this guarantee
878
- // later, on the first successful MsgApp.
879
- r .logSynced = r .raftLog .lastTerm () == term
880
875
r .state = StateFollower
881
876
r .logger .Infof ("%x became follower at term %d" , r .id , r .Term )
882
877
}
@@ -919,7 +914,6 @@ func (r *raft) becomeLeader() {
919
914
r .reset (r .Term )
920
915
r .tick = r .tickHeartbeat
921
916
r .lead = r .id
922
- r .logSynced = true // the leader's log is in sync with itself
923
917
r .state = StateLeader
924
918
// Followers enter replicate mode when they've been successfully probed
925
919
// (perhaps after having received a snapshot as a result). The leader is
@@ -947,6 +941,8 @@ func (r *raft) becomeLeader() {
947
941
// so the preceding log append does not count against the uncommitted log
948
942
// quota of the new leader. In other words, after the call to appendEntry,
949
943
// r.uncommittedSize is still 0.
944
+
945
+ r .raftLog .leaderTerm = r .Term // the leader's log is consistent with itself
950
946
r .logger .Infof ("%x became leader at term %d" , r .id , r .Term )
951
947
}
952
948
@@ -1747,7 +1743,7 @@ func (r *raft) handleAppendEntries(m pb.Message) {
1747
1743
return
1748
1744
}
1749
1745
if mlastIndex , ok := r .raftLog .maybeAppend (m .Index , m .LogTerm , m .Commit , m .Entries ... ); ok {
1750
- r .logSynced = true // from now on, the log is a prefix of the leader's log
1746
+ r .raftLog . leaderTerm = m . Term // the log is now consistent with the leader
1751
1747
r .send (pb.Message {To : m .From , Type : pb .MsgAppResp , Index : mlastIndex })
1752
1748
return
1753
1749
}
@@ -1787,10 +1783,10 @@ func (r *raft) handleHeartbeat(m pb.Message) {
1787
1783
// leader's log. Otherwise, entries at this index may mismatch.
1788
1784
//
1789
1785
// TODO(pav-kv): move this logic to r.raftLog, which is more appropriate for
1790
- // handling safety. The raftLog can use the logSynced flag for other safety
1791
- // checks. For example, unstable.truncateAndAppend currently may override a
1792
- // suffix of the log unconditionally, but it can only be done if !logSynced .
1793
- if r . logSynced {
1786
+ // handling safety. The raftLog can use leaderTerm for other safety checks.
1787
+ // For example, unstable.truncateAndAppend currently may override a suffix of
1788
+ // the log unconditionally, but it can only be done if m.Term > leaderTerm .
1789
+ if m . Term == r . raftLog . leaderTerm {
1794
1790
r .raftLog .commitTo (min (m .Commit , r .raftLog .lastIndex ()))
1795
1791
}
1796
1792
r .send (pb.Message {To : m .From , Type : pb .MsgHeartbeatResp , Context : m .Context })
@@ -1807,6 +1803,7 @@ func (r *raft) handleSnapshot(m pb.Message) {
1807
1803
if r .restore (s ) {
1808
1804
r .logger .Infof ("%x [commit: %d] restored snapshot [index: %d, term: %d]" ,
1809
1805
r .id , r .raftLog .committed , sindex , sterm )
1806
+ r .raftLog .leaderTerm = m .Term // the log is now consistent with the leader
1810
1807
r .send (pb.Message {To : m .From , Type : pb .MsgAppResp , Index : r .raftLog .lastIndex ()})
1811
1808
} else {
1812
1809
r .logger .Infof ("%x [commit: %d] ignored snapshot [index: %d, term: %d]" ,
0 commit comments