raft: return 0 for term of compacted index

It is necessary to make this check because of the following case:

1. memory storage contains ents from index 0 to 50, and unstable has
ents from index 50 to 60.
2. raft receives an incoming snapshot with index 100.
3. raft restores its unstable to 100, but has not applied snapshot on memory storage.
4. raft receives an out-dated MsgApp from index 60.
5. raft finds the term of index 60 to check the match.
6. raft asks memory storage about the term of index 60 after it failed to get
it from unstable.
7. memory storage panics because it knows nothing about index 60.
release-2.0
Yicheng Qin 2014-12-02 23:57:02 -08:00
parent 23b32a6cbe
commit 34a468de36
2 changed files with 35 additions and 3 deletions

View File

@ -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
}

View File

@ -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)