Browse Source

raft: refactor isUpToDate and add a test

Xiang Li 11 years ago
parent
commit
94f701cf95
3 changed files with 36 additions and 7 deletions
  1. 4 5
      raft/log.go
  2. 31 0
      raft/log_test.go
  3. 1 2
      raft/raft.go

+ 4 - 5
raft/log.go

@@ -131,9 +131,9 @@ func (l *raftLog) resetNextEnts() {
 	}
 	}
 }
 }
 
 
-func (l *raftLog) lastIndex() uint64 {
-	return uint64(len(l.ents)) - 1 + l.offset
-}
+func (l *raftLog) lastIndex() uint64 { return uint64(len(l.ents)) - 1 + l.offset }
+
+func (l raftLog) lastTerm() uint64 { return l.term(l.lastIndex()) }
 
 
 func (l *raftLog) term(i uint64) uint64 {
 func (l *raftLog) term(i uint64) uint64 {
 	if e := l.at(i); e != nil {
 	if e := l.at(i); e != nil {
@@ -158,8 +158,7 @@ func (l *raftLog) entries(i uint64) []pb.Entry {
 // later term is more up-to-date. If the logs end with the same term, then
 // later term is more up-to-date. If the logs end with the same term, then
 // whichever log has the larger lastIndex is more up-to-date.
 // whichever log has the larger lastIndex is more up-to-date.
 func (l *raftLog) isUpToDate(lasti, term uint64) bool {
 func (l *raftLog) isUpToDate(lasti, term uint64) bool {
-	e := l.at(l.lastIndex())
-	return term > e.Term || (term == e.Term && lasti >= l.lastIndex())
+	return term > l.lastTerm() || (term == l.lastTerm() && lasti >= l.lastIndex())
 }
 }
 
 
 func (l *raftLog) matchTerm(i, term uint64) bool {
 func (l *raftLog) matchTerm(i, term uint64) bool {

+ 31 - 0
raft/log_test.go

@@ -59,6 +59,37 @@ func TestFindConflict(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestIsUpToDate(t *testing.T) {
+	previousEnts := []pb.Entry{{Term: 1}, {Term: 2}, {Term: 3}}
+	raftLog := newLog()
+	raftLog.ents = append(raftLog.ents, previousEnts...)
+	tests := []struct {
+		lastIndex uint64
+		term      uint64
+		wUpToDate bool
+	}{
+		// greater term, ignore lastIndex
+		{raftLog.lastIndex() - 1, 4, true},
+		{raftLog.lastIndex(), 4, true},
+		{raftLog.lastIndex() + 1, 4, true},
+		// smaller term, ignore lastIndex
+		{raftLog.lastIndex() - 1, 2, false},
+		{raftLog.lastIndex(), 2, false},
+		{raftLog.lastIndex() + 1, 2, false},
+		// equal term, lager lastIndex wins
+		{raftLog.lastIndex() - 1, 3, false},
+		{raftLog.lastIndex(), 3, true},
+		{raftLog.lastIndex() + 1, 3, true},
+	}
+
+	for i, tt := range tests {
+		gUpToDate := raftLog.isUpToDate(tt.lastIndex, tt.term)
+		if gUpToDate != tt.wUpToDate {
+			t.Errorf("#%d: uptodate = %v, want %v", i, gUpToDate, tt.wUpToDate)
+		}
+	}
+}
+
 // TestAppend ensures:
 // TestAppend ensures:
 // 1. If an existing entry conflicts with a new one (same index
 // 1. If an existing entry conflicts with a new one (same index
 // but different terms), delete the existing entry and all that
 // but different terms), delete the existing entry and all that

+ 1 - 2
raft/raft.go

@@ -348,8 +348,7 @@ func (r *raft) campaign() {
 		if i == r.id {
 		if i == r.id {
 			continue
 			continue
 		}
 		}
-		lasti := r.raftLog.lastIndex()
-		r.send(pb.Message{To: i, Type: pb.MsgVote, Index: lasti, LogTerm: r.raftLog.term(lasti)})
+		r.send(pb.Message{To: i, Type: pb.MsgVote, Index: r.raftLog.lastIndex(), LogTerm: r.raftLog.lastTerm()})
 	}
 	}
 }
 }