Skip to content

Commit ee45d3d

Browse files
authored
Merge pull request #525 from rabbitmq/do-not-call-for-elections-if-you-cannot-vote
Don't allow a non-voter to start elections
2 parents 40696e1 + 215611c commit ee45d3d

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed

src/ra_server.erl

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -920,12 +920,12 @@ handle_leader({transfer_leadership, ServerId},
920920
?DEBUG("~ts: transfer leadership to ~w requested",
921921
[LogId, ServerId]),
922922
%% TODO find a timeout
923-
gen_statem:cast(ServerId, try_become_leader),
924923
{await_condition,
925924
State#{condition =>
926925
#{predicate_fun => fun transfer_leadership_condition/2,
927-
timeout => #{effects => [], transition_to => leader}}},
928-
[{reply, ok}]}
926+
timeout => #{effects => [],
927+
transition_to => leader}}},
928+
[{reply, ok}, {send_msg, ServerId, election_timeout, cast}]}
929929
end;
930930
handle_leader({register_external_log_reader, Pid}, #{log := Log0} = State) ->
931931
{Log, Effs} = ra_log:register_reader(Pid, Log0),
@@ -1113,7 +1113,8 @@ handle_pre_vote(#pre_vote_result{term = Term, vote_granted = true,
11131113
votes := Votes,
11141114
cfg := #cfg{log_id = LogId},
11151115
pre_vote_token := Token,
1116-
cluster := Nodes} = State0) ->
1116+
cluster := Nodes,
1117+
membership := voter} = State0) ->
11171118
?DEBUG("~ts: pre_vote granted ~w for term ~b votes ~b",
11181119
[LogId, Token, Term, Votes + 1]),
11191120
NewVotes = Votes + 1,
@@ -1124,17 +1125,14 @@ handle_pre_vote(#pre_vote_result{term = Term, vote_granted = true,
11241125
_ ->
11251126
{pre_vote, State#{votes => NewVotes}, []}
11261127
end;
1127-
handle_pre_vote(#pre_vote_result{vote_granted = false}, State) ->
1128+
handle_pre_vote(#pre_vote_result{}, State) ->
11281129
%% just handle negative results to avoid printing an unhandled message log
11291130
{pre_vote, State, []};
11301131
handle_pre_vote(#pre_vote_rpc{} = PreVote, State) ->
11311132
process_pre_vote(pre_vote, PreVote, State);
11321133
handle_pre_vote(#request_vote_result{}, State) ->
11331134
%% handle to avoid logging as unhandled
11341135
{pre_vote, State, []};
1135-
handle_pre_vote(#pre_vote_result{}, State) ->
1136-
%% handle to avoid logging as unhandled
1137-
{pre_vote, State, []};
11381136
handle_pre_vote(election_timeout, State) ->
11391137
call_for_election(pre_vote, State);
11401138
handle_pre_vote({ra_log_event, Evt}, State = #{log := Log0}) ->
@@ -1360,15 +1358,15 @@ handle_follower({ra_log_event, Evt}, #{log := Log0,
13601358
handle_follower(#pre_vote_rpc{},
13611359
#{cfg := #cfg{log_id = LogId},
13621360
membership := Membership} = State) when Membership =/= voter ->
1363-
?DEBUG("~ts: follower ignored pre_vote_rpc, non-voter: ~p0",
1361+
?DEBUG("~ts: follower ignored pre_vote_rpc, non-voter: ~0p",
13641362
[LogId, Membership]),
13651363
{follower, State, []};
13661364
handle_follower(#pre_vote_rpc{} = PreVote, State) ->
13671365
process_pre_vote(follower, PreVote, State);
13681366
handle_follower(#request_vote_rpc{},
13691367
#{cfg := #cfg{log_id = LogId},
13701368
membership := Membership} = State) when Membership =/= voter ->
1371-
?DEBUG("~ts: follower ignored request_vote_rpc, non-voter: ~p0",
1369+
?DEBUG("~ts: follower ignored request_vote_rpc, non-voter: ~0p",
13721370
[LogId, Membership]),
13731371
{follower, State, []};
13741372
handle_follower(#request_vote_rpc{candidate_id = Cand, term = Term},
@@ -1485,13 +1483,13 @@ handle_follower(#append_entries_reply{}, State) ->
14851483
handle_follower(election_timeout,
14861484
#{cfg := #cfg{log_id = LogId},
14871485
membership := Membership} = State) when Membership =/= voter ->
1488-
?DEBUG("~ts: follower ignored election_timeout, non-voter: ~p0",
1486+
?INFO("~ts: follower ignored election_timeout, non-voter: ~0p",
14891487
[LogId, Membership]),
14901488
{follower, State, []};
14911489
handle_follower(election_timeout, State) ->
14921490
call_for_election(pre_vote, State);
14931491
handle_follower(try_become_leader, State) ->
1494-
call_for_election(pre_vote, State);
1492+
handle_follower(election_timeout, State);
14951493
handle_follower({register_external_log_reader, Pid}, #{log := Log0} = State) ->
14961494
{Log, Effs} = ra_log:register_reader(Pid, Log0),
14971495
{follower, State#{log => Log}, Effs};

test/ra_server_SUITE.erl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ all() ->
3535
leader_does_not_abdicate_to_unknown_peer,
3636
higher_term_detected,
3737
pre_vote_election,
38+
pre_vote_election_non_voter,
3839
pre_vote_election_reverts,
3940
candidate_receives_pre_vote,
4041
leader_receives_pre_vote,
@@ -2104,6 +2105,7 @@ candidate_election(_Config) ->
21042105
pre_vote_election(_Config) ->
21052106
Token = make_ref(),
21062107
State = (base_state(5, ?FUNCTION_NAME))#{votes => 1,
2108+
membership => voter,
21072109
pre_vote_token => Token},
21082110
Reply = #pre_vote_result{term = 5, token = Token, vote_granted = true},
21092111
{pre_vote, #{votes := 2} = State1, []}
@@ -2129,6 +2131,15 @@ pre_vote_election(_Config) ->
21292131
{candidate,
21302132
#{current_term := 6}, _} = ra_server:handle_pre_vote(Reply, State1).
21312133

2134+
pre_vote_election_non_voter(_Config) ->
2135+
Token = make_ref(),
2136+
State = (base_state(5, ?FUNCTION_NAME))#{votes => 1,
2137+
membership => promotable,
2138+
pre_vote_token => Token},
2139+
Reply = #pre_vote_result{term = 5, token = Token, vote_granted = true},
2140+
% non-voter should ignore pre-vote
2141+
{pre_vote, #{votes := 1}, []} = ra_server:handle_pre_vote(Reply, State).
2142+
21322143
pre_vote_election_reverts(_Config) ->
21332144
N2 = ?N2,
21342145
Token = make_ref(),

0 commit comments

Comments
 (0)