From b3841afcc33f25d0f0607e8232326c335553c174 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 2 Dec 2014 21:34:14 -0800 Subject: [PATCH] raft: do not restore snapshot if local raft has longer matching history Raft should not restore the snapshot if it has longer matching history. Or restoring snapshot might remove the matched entries. --- raft/raft.go | 7 +++++++ raft/raft_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/raft/raft.go b/raft/raft.go index bd3347384..0100bad15 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -581,6 +581,13 @@ func (r *raft) restore(s pb.Snapshot) bool { if s.Metadata.Index <= r.raftLog.committed { return false } + if r.raftLog.matchTerm(s.Metadata.Index, s.Metadata.Term) { + log.Printf("raft: %x [commit: %d, lastindex: %d, lastterm: %d] fast-forwarded commit to snapshot [index: %d, term: %d]", + r.id, r.Commit, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term) + r.raftLog.commitTo(s.Metadata.Index) + return false + } + log.Printf("raft: %x [commit: %d, lastindex: %d, lastterm: %d] starts to restore snapshot [index: %d, term: %d]", r.id, r.Commit, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term) diff --git a/raft/raft_test.go b/raft/raft_test.go index d4ed2ea5d..5cc51e25c 100644 --- a/raft/raft_test.go +++ b/raft/raft_test.go @@ -1121,6 +1121,40 @@ func TestRestore(t *testing.T) { } } +func TestRestoreIgnoreSnapshot(t *testing.T) { + previousEnts := []pb.Entry{{Term: 1, Index: 1}, {Term: 1, Index: 2}, {Term: 1, Index: 3}} + commit := uint64(1) + storage := NewMemoryStorage() + sm := newRaft(1, []uint64{1, 2}, 10, 1, storage) + sm.raftLog.append(previousEnts...) + sm.raftLog.commitTo(commit) + + s := pb.Snapshot{ + Metadata: pb.SnapshotMetadata{ + Index: commit, + Term: 1, + ConfState: pb.ConfState{Nodes: []uint64{1, 2}}, + }, + } + + // ignore snapshot + if ok := sm.restore(s); ok { + t.Errorf("restore = %t, want %t", ok, false) + } + if sm.raftLog.committed != commit { + t.Errorf("commit = %d, want %d", sm.raftLog.committed, commit) + } + + // ignore snapshot and fast forward commit + s.Metadata.Index = commit + 1 + if ok := sm.restore(s); ok { + t.Errorf("restore = %t, want %t", ok, false) + } + if sm.raftLog.committed != commit+1 { + t.Errorf("commit = %d, want %d", sm.raftLog.committed, commit+1) + } +} + func TestProvideSnap(t *testing.T) { // restore the statemachin from a snapshot // so it has a compacted log and a snapshot