int raft_recv_requestvote(raft_server_t* me_, int node, msg_requestvote_t* vr, msg_requestvote_response_t *r) { raft_server_private_t* me = (raft_server_private_t*)me_; if (raft_get_current_term(me_) < vr->term) me->voted_for = -1; if (vr->term < raft_get_current_term(me_) || /* we've already voted */ -1 != me->voted_for || /* we have a more up-to-date log */ vr->last_log_idx < me->current_idx) r->vote_granted = 0; else { raft_vote(me_, node); r->vote_granted = 1; } __log(me_, "node requested vote: %d replying: %s", node, r->vote_granted == 1 ? "granted" : "not granted"); r->term = raft_get_current_term(me_); return 0; }
int raft_recv_requestvote(raft_server_t* me_, int node, msg_requestvote_t* vr) { raft_server_private_t* me = (void*)me_; msg_requestvote_response_t r; if (raft_get_current_term(me_) < vr->term) { me->voted_for = -1; } if (vr->term < raft_get_current_term(me_) || /* we've already voted */ -1 != me->voted_for || /* we have a more up-to-date log */ vr->last_log_idx < me->current_idx) { r.vote_granted = 0; } else { raft_vote(me_,node); r.vote_granted = 1; } __log(me_, NULL, "node requested vote: %d replying: %s", node, r.vote_granted == 1 ? "granted" : "not granted"); r.term = raft_get_current_term(me_); if (me->cb.send) me->cb.send(me->cb_ctx, me, node, RAFT_MSG_REQUESTVOTE_RESPONSE, (void*)&r, sizeof(msg_requestvote_response_t)); return 0; }
/* Candidate 5.2 */ void TestRaft_follower_becoming_candidate_increments_current_term(CuTest * tc) { void *r = raft_new(); CuAssertTrue(tc, 0 == raft_get_current_term(r)); raft_become_candidate(r); CuAssertTrue(tc, 1 == raft_get_current_term(r)); }
static int __should_grant_vote(raft_server_private_t* me, msg_requestvote_t* vr) { if (vr->term < raft_get_current_term((void*)me)) return 0; /* TODO: if voted for is candiate return 1 (if below checks pass) */ if (raft_already_voted((void*)me)) return 0; /* Below we check if log is more up-to-date... */ int current_idx = raft_get_current_idx((void*)me); /* Our log is definitely not more up-to-date if it's empty! */ if (0 == current_idx) return 1; raft_entry_t* e = raft_get_entry_from_idx((void*)me, current_idx); if (e->term < vr->last_log_term) return 1; if (vr->last_log_term == e->term && current_idx <= vr->last_log_idx) return 1; return 0; }
void TestRaft_election_start_increments_term(CuTest * tc) { void *r = raft_new(); raft_set_current_term(r, 1); raft_election_start(r); CuAssertTrue(tc, 2 == raft_get_current_term(r)); }
/* TODO: check if test case is needed */ void TestRaft_follower_recv_appendentries_updates_currentterm_if_term_gt_currentterm( CuTest * tc) { msg_appendentries_t ae; msg_appendentries_response_t aer; void *r = raft_new(); raft_add_node(r, (void*)1, 1); raft_add_node(r, (void*)2, 0); /* older currentterm */ raft_set_current_term(r, 1); CuAssertTrue(tc, -1 == raft_get_current_leader(r)); /* newer term for appendentry */ memset(&ae, 0, sizeof(msg_appendentries_t)); /* no prev log idx */ ae.prev_log_idx = 0; ae.term = 2; /* appendentry has newer term, so we change our currentterm */ raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 1 == aer.success); /* term has been updated */ CuAssertTrue(tc, 2 == raft_get_current_term(r)); /* and leader has been updated */ CuAssertTrue(tc, 1 == raft_get_current_leader(r)); }
int raft_recv_requestvote_response(raft_server_t* me_, raft_node_t* node, msg_requestvote_response_t* r) { raft_server_private_t* me = (raft_server_private_t*)me_; __log(me_, node, "node responded to requestvote status: %s", r->vote_granted == 1 ? "granted" : "not granted"); if (!raft_is_candidate(me_)) { return 0; } else if (raft_get_current_term(me_) < r->term) { raft_set_current_term(me_, r->term); 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; } __log(me_, node, "node responded to requestvote: %d status: %s ct:%d rt:%d", node, r->vote_granted == 1 ? "granted" : "not granted", me->current_term, r->term); if (1 == r->vote_granted) { if (node) raft_node_vote_for_me(node, 1); int votes = raft_get_nvotes_for_me(me_); if (raft_votes_is_majority(me->num_nodes, votes)) raft_become_leader(me_); } return 0; }
int raft_recv_requestvote(raft_server_t* me_, raft_node_t* node, msg_requestvote_t* vr, msg_requestvote_response_t *r) { raft_server_private_t* me = (raft_server_private_t*)me_; if (raft_get_current_term(me_) < vr->term) { raft_set_current_term(me_, vr->term); raft_become_follower(me_); } if (__should_grant_vote(me, vr)) { /* It shouldn't be possible for a leader or candidate to grant a vote * Both states would have voted for themselves */ assert(!(raft_is_leader(me_) || raft_is_candidate(me_))); raft_vote_for_nodeid(me_, vr->candidate_id); r->vote_granted = 1; /* there must be in an election. */ me->current_leader = NULL; me->timeout_elapsed = 0; } else r->vote_granted = 0; __log(me_, node, "node requested vote: %d replying: %s", node, r->vote_granted == 1 ? "granted" : "not granted"); r->term = raft_get_current_term(me_); return 0; }
int raft_send_requestvote(raft_server_t* me_, int node) { raft_server_private_t* me = (raft_server_private_t*)me_; msg_requestvote_t rv; __log(me_, "sending requestvote to: %d", node); rv.term = me->current_term; rv.last_log_idx = raft_get_current_idx(me_); rv.last_log_term = raft_get_current_term(me_); rv.candidate_id = raft_get_nodeid(me_); if (me->cb.send_requestvote) me->cb.send_requestvote(me_, me->udata, node, &rv); return 0; }
void raft_become_leader(raft_server_t* me_) { raft_server_private_t* me = (raft_server_private_t*)me_; int i; __log(me_, NULL, "becoming leader term:%d", raft_get_current_term(me_)); raft_set_state(me_, RAFT_STATE_LEADER); for (i = 0; i < me->num_nodes; i++) { if (me->node == me->nodes[i] || !raft_node_is_voting(me->nodes[i])) continue; raft_node_t* node = me->nodes[i]; raft_node_set_next_idx(node, raft_get_current_idx(me_) + 1); raft_node_set_match_idx(node, 0); raft_send_appendentries(me_, node); } }
void raft_become_candidate(raft_server_t* me_) { raft_server_private_t* me = (raft_server_private_t*)me_; int i; __log(me_, NULL, "becoming candidate"); raft_set_current_term(me_, raft_get_current_term(me_) + 1); for (i = 0; i < me->num_nodes; i++) raft_node_vote_for_me(me->nodes[i], 0); raft_vote(me_, me->node); me->current_leader = NULL; raft_set_state(me_, RAFT_STATE_CANDIDATE); /* we need a random factor here to prevent simultaneous candidates */ /* TODO: this should probably be lower */ me->timeout_elapsed = rand() % me->election_timeout; for (i = 0; i < me->num_nodes; i++) if (me->node != me->nodes[i] && raft_node_is_voting(me->nodes[i])) raft_send_requestvote(me_, me->nodes[i]); }
void TestRaft_server_set_currentterm_sets_term(CuTest * tc) { void *r = raft_new(); raft_set_current_term(r, 5); CuAssertTrue(tc, 5 == raft_get_current_term(r)); }
void TestRaft_server_currentterm_defaults_to_0(CuTest * tc) { void *r = raft_new(); CuAssertTrue(tc, 0 == raft_get_current_term(r)); }