Commit 1aee978a authored by Willem Thiart's avatar Willem Thiart
Browse files

Add membership changes

parent 1c6cb689
......@@ -560,6 +560,11 @@ int raft_get_my_id(raft_server_t* me);
* @param[in] node The server to vote for */
void raft_vote(raft_server_t* me_, raft_node_t* node);
/** Vote for a server.
* This should be used to reload persistent state, ie. the voted-for field.
* @param[in] nodeid The server to vote for by nodeid */
void raft_vote_for_nodeid(raft_server_t* me_, const int nodeid);
/** Set the current term.
* This should be used to reload persistent state, ie. the current_term field.
* @param[in] term The new current term */
......
......@@ -21,7 +21,7 @@ typedef struct {
/* The candidate the server voted for in its current term,
* or Nil if it hasn't voted for any. */
raft_node_t* voted_for;
int voted_for;
/* the log which is replicated */
void* log;
......
......@@ -103,7 +103,6 @@ void raft_node_set_voting(raft_node_t* me_, int voting)
me->flags |= RAFT_NODE_VOTING;
else
me->flags &= ~RAFT_NODE_VOTING;
}
int raft_node_is_voting(raft_node_t* me_)
......
......@@ -44,7 +44,7 @@ raft_server_t* raft_new()
if (!me)
return NULL;
me->current_term = 0;
me->voted_for = NULL;
me->voted_for = -1;
me->timeout_elapsed = 0;
me->request_timeout = 200;
me->election_timeout = 1000;
......@@ -144,9 +144,7 @@ int raft_periodic(raft_server_t* me_, int msec_since_last_period)
}
else if (me->election_timeout <= me->timeout_elapsed)
{
if (1 == me->num_nodes)
raft_become_leader(me_);
else
if (1 < me->num_nodes)
raft_election_start(me_);
}
......@@ -270,9 +268,6 @@ int raft_recv_appendentries(
{
raft_server_private_t* me = (raft_server_private_t*)me_;
assert(node);
assert(node != me->node);
me->timeout_elapsed = 0;
if (0 < ae->n_entries)
......@@ -285,11 +280,13 @@ int raft_recv_appendentries(
ae->prev_log_term,
ae->n_entries);
printf("%p %p\n", node, raft_get_current_leader_node(me_));
r->term = me->current_term;
if (raft_is_candidate(me_) && me->current_term == ae->term)
{
me->voted_for = NULL;
me->voted_for = -1;
raft_become_follower(me_);
}
else if (me->current_term < ae->term)
......@@ -402,7 +399,7 @@ static int __should_grant_vote(raft_server_private_t* me, msg_requestvote_t* vr)
/* TODO: if voted for is candiate return 1 (if below checks pass) */
/* we've already voted */
if (me->voted_for)
if (0 < me->voted_for)
return 0;
int current_idx = raft_get_current_idx((void*)me);
......@@ -427,9 +424,6 @@ int raft_recv_requestvote(raft_server_t* me_,
{
raft_server_private_t* me = (raft_server_private_t*)me_;
assert(node);
assert(node != me->node);
if (raft_get_current_term(me_) < vr->term)
{
raft_set_current_term(me_, vr->term);
......@@ -442,7 +436,7 @@ int raft_recv_requestvote(raft_server_t* me_,
* Both states would have voted for themselves */
assert(!(raft_is_leader(me_) || raft_is_candidate(me_)));
raft_vote(me_, node);
raft_vote_for_nodeid(me_, vr->candidate_id);
r->vote_granted = 1;
/* there must be in an election. */
......@@ -662,7 +656,7 @@ void raft_send_appendentries_all(raft_server_t* me_)
me->timeout_elapsed = 0;
for (i = 0; i < me->num_nodes; i++)
if (me->node != me->nodes[i] && raft_node_is_voting(me->nodes[i]))
if (me->node != me->nodes[i])
raft_send_appendentries(me_, me->nodes[i]);
}
......@@ -702,21 +696,24 @@ int raft_get_nvotes_for_me(raft_server_t* me_)
if (raft_node_has_vote_for_me(me->nodes[i]))
votes += 1;
if (me->voted_for == me->node)
if (me->voted_for == raft_get_nodeid(me_))
votes += 1;
return votes;
}
void raft_vote(raft_server_t* me_, raft_node_t* node)
void raft_vote_for_nodeid(raft_server_t* me_, const int nodeid)
{
raft_server_private_t* me = (raft_server_private_t*)me_;
assert(!me->voted_for || node != me->voted_for);
me->voted_for = node;
me->voted_for = nodeid;
if (me->cb.persist_vote)
me->cb.persist_vote(me_, me->udata, raft_node_get_id(node));
me->cb.persist_vote(me_, me->udata, nodeid);
}
void raft_vote(raft_server_t* me_, raft_node_t* node)
{
raft_vote_for_nodeid(me_, node ? raft_node_get_id(node) : -1);
}
int raft_msg_entry_response_committed(raft_server_t* me_,
......
......@@ -66,9 +66,7 @@ int raft_get_log_count(raft_server_t* me_)
int raft_get_voted_for(raft_server_t* me_)
{
raft_server_private_t* me = (raft_server_private_t*)me_;
if (me->voted_for)
return raft_node_get_id(me->voted_for);
return -1;
return me->voted_for;
}
void raft_set_current_term(raft_server_t* me_, const int term)
......@@ -77,7 +75,7 @@ void raft_set_current_term(raft_server_t* me_, const int term)
if (me->current_term < term)
{
me->current_term = term;
me->voted_for = NULL;
me->voted_for = -1;
if (me->cb.persist_term)
me->cb.persist_term(me_, me->udata, term);
}
......
......@@ -581,6 +581,7 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
/* current term is less than term */
msg_requestvote_t rv;
memset(&rv, 0, sizeof(msg_requestvote_t));
rv.candidate_id = 2;
rv.term = 2;
rv.last_log_idx = 1;
msg_requestvote_response_t rvr;
......@@ -590,6 +591,30 @@ void TestRaft_server_recv_requestvote_candidate_step_down_if_term_is_higher_than
CuAssertIntEquals(tc, 2, raft_get_voted_for(r));
}
void TestRaft_server_recv_requestvote_depends_on_candidate_id(
CuTest * tc
)
{
void *r = raft_new();
raft_add_node(r, NULL, 1, 1);
raft_add_node(r, NULL, 2, 0);
raft_become_candidate(r);
raft_set_current_term(r, 1);
CuAssertIntEquals(tc, 1, raft_get_voted_for(r));
/* current term is less than term */
msg_requestvote_t rv;
memset(&rv, 0, sizeof(msg_requestvote_t));
rv.candidate_id = 3;
rv.term = 2;
rv.last_log_idx = 1;
msg_requestvote_response_t rvr;
raft_recv_requestvote(r, NULL, &rv, &rvr);
CuAssertIntEquals(tc, 1, raft_is_follower(r));
CuAssertIntEquals(tc, 2, raft_get_current_term(r));
CuAssertIntEquals(tc, 3, raft_get_voted_for(r));
}
/* If votedFor is null or candidateId, and candidate's log is at
* least as up-to-date as local log, grant vote (5.2, 5.4) */
void TestRaft_server_dont_grant_vote_if_we_didnt_vote_for_this_candidate(
......
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