Commit b7543091 authored by Willem Thiart's avatar Willem Thiart
Browse files

Server ignores old requestvote response messages

When the network is slow and lossy, then there's a risk that we might
receive the requestvote response much later. So late that the term of
the server who sent the requestvote message doesn't match the
addressee's term. We now ignore these old responses to ensure the
election safety invariant.
parent 103aeaaa
......@@ -407,6 +407,13 @@ int raft_recv_requestvote_response(raft_server_t* me_, int node,
raft_become_follower(me_);
return 0;
}
else if (raft_get_current_term(me_) != r->term)
{
/* The node who voted for us would have obtained our term.
* Therefore this is an old message we should ignore.
* This happens if the network is pretty choppy. */
return 0;
}
if (1 == r->vote_granted)
{
......
......@@ -419,6 +419,24 @@ void TestRaft_server_recv_requestvote_response_dont_increase_votes_for_me_when_n
CuAssertTrue(tc, 0 == raft_get_nvotes_for_me(r));
}
void TestRaft_server_recv_requestvote_response_dont_increase_votes_for_me_when_term_is_not_equal(
CuTest * tc
)
{
void *r = raft_new();
raft_add_node(r, (void*)1, 1);
raft_add_node(r, (void*)2, 0);
raft_set_current_term(r, 3);
CuAssertTrue(tc, 0 == raft_get_nvotes_for_me(r));
msg_requestvote_response_t rvr;
memset(&rvr, 0, sizeof(msg_requestvote_response_t));
rvr.term = 2;
rvr.vote_granted = 1;
raft_recv_requestvote_response(r, 1, &rvr);
CuAssertTrue(tc, 0 == raft_get_nvotes_for_me(r));
}
void TestRaft_server_recv_requestvote_response_increase_votes_for_me(
CuTest * tc
)
......@@ -2166,7 +2184,7 @@ void TestRaft_leader_sends_empty_appendentries_every_request_timeout(
void T_estRaft_leader_sends_appendentries_when_receive_entry_msg(CuTest * tc)
#endif
void TestRaft_leader_recv_voterequest_responds_without_granting(CuTest * tc)
void TestRaft_leader_recv_requestvote_responds_without_granting(CuTest * tc)
{
raft_cbs_t funcs = {
.send_appendentries = sender_appendentries,
......@@ -2199,7 +2217,7 @@ void TestRaft_leader_recv_voterequest_responds_without_granting(CuTest * tc)
CuAssertTrue(tc, 0 == rvr.vote_granted);
}
void TestRaft_leader_recv_voterequest_responds_with_granting_if_term_is_higher(CuTest * tc)
void TestRaft_leader_recv_requestvote_responds_with_granting_if_term_is_higher(CuTest * tc)
{
raft_cbs_t funcs = {
.send_appendentries = sender_appendentries,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment