diff --git a/raft/log.go b/raft/log.go index 6cb1d851d..5d2e63596 100644 --- a/raft/log.go +++ b/raft/log.go @@ -199,7 +199,9 @@ func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) } func (l *raftLog) lastTerm() uint64 { return l.term(l.lastIndex()) } func (l *raftLog) term(i uint64) uint64 { - if i > l.lastIndex() { + // the valid term range is [index of dummy entry, last index] + dummyIndex := l.firstIndex() - 1 + if i < dummyIndex || i > l.lastIndex() { return 0 } diff --git a/raft/log_test.go b/raft/log_test.go index 609654c60..f85a4f9d5 100644 --- a/raft/log_test.go +++ b/raft/log_test.go @@ -634,7 +634,7 @@ func TestTerm(t *testing.T) { num := uint64(100) storage := NewMemoryStorage() - storage.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: offset}}) + storage.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: offset, Term: 1}}) l := newLog(storage) for i = 1; i < num; i++ { l.append(pb.Entry{Index: offset + i, Term: i}) @@ -645,7 +645,7 @@ func TestTerm(t *testing.T) { w uint64 }{ {offset - 1, 0}, - {offset, 0}, + {offset, 1}, {offset + num/2, num / 2}, {offset + num - 1, num - 1}, {offset + num, 0}, @@ -659,6 +659,36 @@ func TestTerm(t *testing.T) { } } +func TestTermWithUnstableSnapshot(t *testing.T) { + storagesnapi := uint64(100) + unstablesnapi := storagesnapi + 5 + + storage := NewMemoryStorage() + storage.ApplySnapshot(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: storagesnapi, Term: 1}}) + l := newLog(storage) + l.restore(pb.Snapshot{Metadata: pb.SnapshotMetadata{Index: unstablesnapi, Term: 1}}) + + tests := []struct { + index uint64 + w uint64 + }{ + // cannot get term from storage + {storagesnapi, 0}, + // cannot get term from the gap between storage ents and unstable snapshot + {storagesnapi + 1, 0}, + {unstablesnapi - 1, 0}, + // get term from unstable snapshot index + {unstablesnapi, 1}, + } + + for i, tt := range tests { + term := l.term(tt.index) + if !reflect.DeepEqual(term, tt.w) { + t.Errorf("#%d: at = %d, want %d", i, term, tt.w) + } + } +} + func TestSlice(t *testing.T) { var i uint64 offset := uint64(100)