|
|
@@ -70,13 +70,13 @@ func (pr *progress) update(n uint64) {
|
|
|
func (pr *progress) optimisticUpdate(n uint64) { pr.next = n + 1 }
|
|
|
|
|
|
// maybeDecrTo returns false if the given to index comes from an out of order message.
|
|
|
-// Otherwise it decreases the progress next index and returns true.
|
|
|
-func (pr *progress) maybeDecrTo(to uint64) bool {
|
|
|
+// Otherwise it decreases the progress next index to min(rejected, last) and returns true.
|
|
|
+func (pr *progress) maybeDecrTo(rejected, last uint64) bool {
|
|
|
pr.waitReset()
|
|
|
if pr.match != 0 {
|
|
|
- // the rejection must be stale if the progress has matched and "to"
|
|
|
+ // the rejection must be stale if the progress has matched and "rejected"
|
|
|
// is smaller than "match".
|
|
|
- if to <= pr.match {
|
|
|
+ if rejected <= pr.match {
|
|
|
return false
|
|
|
}
|
|
|
// directly decrease next to match + 1
|
|
|
@@ -84,12 +84,12 @@ func (pr *progress) maybeDecrTo(to uint64) bool {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
- // the rejection must be stale if "to" does not match next - 1
|
|
|
- if pr.next-1 != to {
|
|
|
+ // the rejection must be stale if "rejected" does not match next - 1
|
|
|
+ if pr.next-1 != rejected {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
- if pr.next--; pr.next < 1 {
|
|
|
+ if pr.next = min(rejected, last+1); pr.next < 1 {
|
|
|
pr.next = 1
|
|
|
}
|
|
|
return true
|
|
|
@@ -245,8 +245,8 @@ func (r *raft) sendAppend(to uint64) {
|
|
|
if n := len(m.Entries); pr.match != 0 && n != 0 {
|
|
|
pr.optimisticUpdate(m.Entries[n-1].Index)
|
|
|
} else if pr.match == 0 {
|
|
|
- // TODO (xiangli): better way to find out if the follwer is in good path or not
|
|
|
- // a follower might be in bad path even if match != 0, since we optmistically
|
|
|
+ // TODO (xiangli): better way to find out if the follower is in good path or not
|
|
|
+ // a follower might be in bad path even if match != 0, since we optimistically
|
|
|
// increase the next.
|
|
|
pr.waitSet(r.heartbeatTimeout)
|
|
|
}
|
|
|
@@ -482,9 +482,10 @@ func stepLeader(r *raft, m pb.Message) {
|
|
|
r.bcastAppend()
|
|
|
case pb.MsgAppResp:
|
|
|
if m.Reject {
|
|
|
- log.Printf("raft: %x received msgApp rejection from %x for index %d",
|
|
|
- r.id, m.From, m.Index)
|
|
|
- if r.prs[m.From].maybeDecrTo(m.Index) {
|
|
|
+ log.Printf("raft: %x received msgApp rejection(lastindex: %d) from %x for index %d",
|
|
|
+ r.id, m.RejectHint, m.From, m.Index)
|
|
|
+ if r.prs[m.From].maybeDecrTo(m.Index, m.RejectHint) {
|
|
|
+ log.Printf("raft: %x decreased progress of %x to [%s]", r.id, m.From, r.prs[m.From])
|
|
|
r.sendAppend(m.From)
|
|
|
}
|
|
|
} else {
|
|
|
@@ -572,7 +573,7 @@ func (r *raft) handleAppendEntries(m pb.Message) {
|
|
|
} else {
|
|
|
log.Printf("raft: %x [logterm: %d, index: %d] rejected msgApp [logterm: %d, index: %d] from %x",
|
|
|
r.id, r.raftLog.term(m.Index), m.Index, m.LogTerm, m.Index, m.From)
|
|
|
- r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: m.Index, Reject: true})
|
|
|
+ r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: m.Index, Reject: true, RejectHint: r.raftLog.lastIndex()})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -593,8 +594,8 @@ func (r *raft) handleSnapshot(m pb.Message) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// restore recovers the statemachine from a snapshot. It restores the log and the
|
|
|
-// configuration of statemachine.
|
|
|
+// restore recovers the state machine from a snapshot. It restores the log and the
|
|
|
+// configuration of state machine.
|
|
|
func (r *raft) restore(s pb.Snapshot) bool {
|
|
|
if s.Metadata.Index <= r.raftLog.committed {
|
|
|
return false
|