raft: abort leader transferring if the target is demoted (#11417)

Signed-off-by: qupeng <qupeng@pingcap.com>
release-3.5
qupeng 2019-12-20 12:07:52 +08:00 committed by Xiang Li
parent 5770a6d286
commit eaa0612e02
2 changed files with 34 additions and 2 deletions

View File

@ -1566,8 +1566,8 @@ func (r *raft) switchToConfig(cfg tracker.Config, prs tracker.ProgressMap) pb.Co
r.maybeSendAppend(id, false /* sendIfEmpty */)
})
}
// If the the leadTransferee was removed, abort the leadership transfer.
if _, tOK := r.prs.Progress[r.leadTransferee]; !tOK && r.leadTransferee != 0 {
// If the the leadTransferee was removed or demoted, abort the leadership transfer.
if _, tOK := r.prs.Config.Voters.IDs()[r.leadTransferee]; !tOK && r.leadTransferee != 0 {
r.abortLeaderTransfer()
}

View File

@ -3601,6 +3601,38 @@ func TestLeaderTransferRemoveNode(t *testing.T) {
checkLeaderTransferState(t, lead, StateLeader, 1)
}
func TestLeaderTransferDemoteNode(t *testing.T) {
nt := newNetwork(nil, nil, nil)
nt.send(pb.Message{From: 1, To: 1, Type: pb.MsgHup})
nt.ignore(pb.MsgTimeoutNow)
lead := nt.peers[1].(*raft)
// The leadTransferee is demoted when leadship transferring.
nt.send(pb.Message{From: 3, To: 1, Type: pb.MsgTransferLeader})
if lead.leadTransferee != 3 {
t.Fatalf("wait transferring, leadTransferee = %v, want %v", lead.leadTransferee, 3)
}
lead.applyConfChange(pb.ConfChangeV2{
Changes: []pb.ConfChangeSingle{
{
Type: pb.ConfChangeRemoveNode,
NodeID: 3,
},
{
Type: pb.ConfChangeAddLearnerNode,
NodeID: 3,
},
},
})
// Make the Raft group commit the LeaveJoint entry.
lead.applyConfChange(pb.ConfChangeV2{})
checkLeaderTransferState(t, lead, StateLeader, 1)
}
// TestLeaderTransferBack verifies leadership can transfer back to self when last transfer is pending.
func TestLeaderTransferBack(t *testing.T) {
nt := newNetwork(nil, nil, nil)