Skip to content

Commit

Permalink
merge fix from etcd-io/etcd#10822
Browse files Browse the repository at this point in the history
  • Loading branch information
absolute8511 committed Jun 15, 2021
1 parent 05cd559 commit 9f2eff2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
7 changes: 7 additions & 0 deletions raft/raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,14 @@ func (r *raft) hup(t CampaignType) {
r.campaign(t)
}

// campaign transitions the raft instance to candidate state. This must only be
// called after verifying that this is a legitimate transition.
func (r *raft) campaign(t CampaignType) {
if !r.promotable() {
// This path should not be hit (callers are supposed to check), but
// better safe than sorry.
r.logger.Warningf("%x is unpromotable; campaign() should have been called", r.id)
}
var term uint64
var voteMsg pb.MessageType
if t == campaignPreElection {
Expand Down
39 changes: 39 additions & 0 deletions raft/raft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4054,6 +4054,45 @@ func TestNodeWithSmallerTermCanCompleteElection(t *testing.T) {
}
}

// TestLearnerCampaign verifies that a learner won't campaign even if it receives
// a MsgHup or MsgTimeoutNow.
func TestLearnerCampaign(t *testing.T) {
n1 := newTestRaft(1, []uint64{1}, 10, 1, NewMemoryStorage())
grp2 := pb.Group{
NodeId: 2,
GroupId: 1,
RaftReplicaId: 2,
}
n1.addLearner(2, grp2)
n2 := newTestRaft(2, []uint64{1}, 10, 1, NewMemoryStorage())
n2.addLearner(2, grp2)
nt := newNetwork(n1, n2)
nt.send(pb.Message{From: 2, To: 2, Type: pb.MsgHup})

if !n2.isLearner {
t.Fatalf("failed to make n2 a learner")
}

if n2.state != StateFollower {
t.Fatalf("n2 campaigned despite being learner")
}

nt.send(pb.Message{From: 1, To: 1, Type: pb.MsgHup})
if n1.state != StateLeader || n1.lead != 1 {
t.Fatalf("n1 did not become leader")
}

// NB: TransferLeader already checks that the recipient is not a learner, but
// the check could have happened by the time the recipient becomes a learner,
// in which case it will receive MsgTimeoutNow as in this test case and we
// verify that it's ignored.
nt.send(pb.Message{From: 1, To: 2, Type: pb.MsgTimeoutNow})

if n2.state != StateFollower {
t.Fatalf("n2 accepted leadership transfer despite being learner")
}
}

// simulate rolling update a cluster for Pre-Vote. cluster has 3 nodes [n1, n2, n3].
// n1 is leader with term 2
// n2 is follower with term 2
Expand Down

0 comments on commit 9f2eff2

Please sign in to comment.