浏览代码

Merge pull request #1149 from unihorn/137

raft: stop tickElection when the node is not in peer list
Xiang Li 11 年之前
父节点
当前提交
1f736263b2
共有 2 个文件被更改,包括 33 次插入0 次删除
  1. 11 0
      raft/raft.go
  2. 22 0
      raft/raft_test.go

+ 11 - 0
raft/raft.go

@@ -265,6 +265,10 @@ func (r *raft) appendEntry(e pb.Entry) {
 
 // tickElection is ran by followers and candidates after r.electionTimeout.
 func (r *raft) tickElection() {
+	if !r.promotable() {
+		r.elapsed = 0
+		return
+	}
 	r.elapsed++
 	// TODO (xiangli): elctionTimeout should be randomized.
 	if r.elapsed > r.electionTimeout {
@@ -530,6 +534,13 @@ func (r *raft) delProgress(id int64) {
 	delete(r.prs, id)
 }
 
+// promotable indicates whether state machine can be promoted to leader,
+// which is true when its own id is in progress list.
+func (r *raft) promotable() bool {
+	_, ok := r.prs[r.id]
+	return ok
+}
+
 func (r *raft) loadEnts(ents []pb.Entry) {
 	r.raftLog.load(ents)
 }

+ 22 - 0
raft/raft_test.go

@@ -1053,6 +1053,28 @@ func TestRemoveNode(t *testing.T) {
 	}
 }
 
+func TestPromotable(t *testing.T) {
+	id := int64(1)
+	tests := []struct {
+		peers []int64
+		wp    bool
+	}{
+		{[]int64{1}, true},
+		{[]int64{1, 2, 3}, true},
+		{[]int64{}, false},
+		{[]int64{2, 3}, false},
+	}
+	for i, tt := range tests {
+		r := &raft{id: id, prs: make(map[int64]*progress)}
+		for _, id := range tt.peers {
+			r.prs[id] = &progress{}
+		}
+		if g := r.promotable(); g != tt.wp {
+			t.Errorf("#%d: promotable = %v, want %v", i, g, tt.wp)
+		}
+	}
+}
+
 func ents(terms ...int64) *raft {
 	ents := []pb.Entry{{}}
 	for _, term := range terms {