Browse Source

raft: not recover from outdated snapshot

Yicheng Qin 11 years ago
parent
commit
01c40fcf50
2 changed files with 18 additions and 4 deletions
  1. 11 3
      raft/raft.go
  2. 7 1
      raft/raft_test.go

+ 11 - 3
raft/raft.go

@@ -398,8 +398,11 @@ func (sm *stateMachine) handleAppendEntries(m Message) {
 }
 
 func (sm *stateMachine) handleSnapshot(m Message) {
-	sm.restore(m.Snapshot)
-	sm.send(Message{To: m.From, Type: msgAppResp, Index: sm.raftLog.lastIndex()})
+	if sm.restore(m.Snapshot) {
+		sm.send(Message{To: m.From, Type: msgAppResp, Index: sm.raftLog.lastIndex()})
+	} else {
+		sm.send(Message{To: m.From, Type: msgAppResp, Index: sm.raftLog.committed})
+	}
 }
 
 func (sm *stateMachine) addNode(id int64) {
@@ -503,7 +506,11 @@ func (sm *stateMachine) compact(d []byte) {
 
 // restore recovers the statemachine from a snapshot. It restores the log and the
 // configuration of statemachine.
-func (sm *stateMachine) restore(s Snapshot) {
+func (sm *stateMachine) restore(s Snapshot) bool {
+	if s.Index <= sm.raftLog.committed {
+		return false
+	}
+
 	sm.raftLog.restore(s)
 	sm.index.Set(sm.raftLog.lastIndex())
 	sm.ins = make(map[int64]*index)
@@ -515,6 +522,7 @@ func (sm *stateMachine) restore(s Snapshot) {
 		}
 	}
 	sm.pendingConf = false
+	return true
 }
 
 func (sm *stateMachine) needSnapshot(i int64) bool {

+ 7 - 1
raft/raft_test.go

@@ -781,7 +781,9 @@ func TestRestore(t *testing.T) {
 	}
 
 	sm := newStateMachine(0, []int64{0, 1})
-	sm.restore(s)
+	if ok := sm.restore(s); !ok {
+		t.Fatal("restore fail, want succeed")
+	}
 
 	if sm.raftLog.lastIndex() != s.Index {
 		t.Errorf("log.lastIndex = %d, want %d", sm.raftLog.lastIndex(), s.Index)
@@ -799,6 +801,10 @@ func TestRestore(t *testing.T) {
 	if !reflect.DeepEqual(sm.raftLog.snapshot, s) {
 		t.Errorf("snapshot = %+v, want %+v", sm.raftLog.snapshot, s)
 	}
+
+	if ok := sm.restore(s); ok {
+		t.Fatal("restore succeed, want fail")
+	}
 }
 
 func TestProvideSnap(t *testing.T) {