void sender_poll_msgs(void* s) { sender_t* me = s; msg_t* m; while ((m = llqueue_poll(me->inbox))) { switch (m->type) { case RAFT_MSG_APPENDENTRIES: raft_recv_appendentries(me->raft, m->sender, m->data); break; case RAFT_MSG_APPENDENTRIES_RESPONSE: raft_recv_appendentries_response(me->raft, m->sender, m->data); break; case RAFT_MSG_REQUESTVOTE: raft_recv_requestvote(me->raft, m->sender, m->data); break; case RAFT_MSG_REQUESTVOTE_RESPONSE: raft_recv_requestvote_response(me->raft, m->sender, m->data); break; case RAFT_MSG_ENTRY: raft_recv_entry(me->raft, m->sender, m->data); break; case RAFT_MSG_ENTRY_RESPONSE: //raft_recv_entry_response(me->raft, m->sender, m->data); break; } } }
void TestRaft_follower_recv_appendentries_does_not_log_if_no_entries_are_specified( 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); raft_set_state(r, RAFT_STATE_FOLLOWER); /* log size s */ CuAssertTrue(tc, 0 == raft_get_log_count(r)); /* receive an appendentry with commit */ memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; ae.prev_log_term = 1; ae.prev_log_idx = 4; ae.leader_commit = 5; ae.n_entries = 0; raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 0 == raft_get_log_count(r)); }
void TestRaft_follower_recv_appendentries_add_new_entries_not_already_in_log( 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, 1); msg_appendentries_t ae; msg_appendentries_response_t aer; memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; ae.prev_log_idx = 0; ae.prev_log_term = 1; /* include entries */ msg_entry_t e[2]; memset(&e, 0, sizeof(msg_entry_t) * 2); e[0].id = 1; e[1].id = 2; ae.entries = e; ae.n_entries = 2; raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 1 == aer.success); CuAssertTrue(tc, 2 == raft_get_log_count(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)); }
/* 5.1 */ void TestRaft_follower_recv_appendentries_reply_false_if_term_less_than_currentterm( CuTest * tc) { msg_appendentries_t ae; msg_appendentries_response_t aer, *aerr; void *r = raft_new(); raft_add_node(r, (void*)1, 1); raft_add_node(r, (void*)2, 0); void *sender = sender_new(NULL); /* no leader known at this point */ CuAssertTrue(tc, -1 == raft_get_current_leader(r)); /* term is low */ memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; /* higher current term */ raft_set_current_term(r, 5); raft_recv_appendentries(r, 1, &ae, &aer); aerr = sender_poll_msg_data(sender); CuAssertTrue(tc, NULL != aerr); CuAssertTrue(tc, 0 == aerr->success); /* rejected appendentries doesn't change the current leader. */ CuAssertTrue(tc, -1 == raft_get_current_leader(r)); }
/* 5.3 */ void TestRaft_follower_recv_appendentries_delete_entries_if_conflict_with_new_entries( CuTest * tc) { msg_appendentries_t ae; msg_appendentries_response_t aer; raft_entry_t *ety_appended; void *r = raft_new(); raft_add_node(r, (void*)1, 1); raft_add_node(r, (void*)2, 0); raft_set_current_term(r, 1); raft_entry_t ety; /* increase log size */ char *str1 = "111"; ety.data.buf = str1; ety.data.len = 3; ety.id = 1; ety.term = 1; raft_append_entry(r, &ety); CuAssertTrue(tc, 1 == raft_get_log_count(r)); /* this log will be overwritten by the appendentries below */ char *str2 = "222"; ety.data.buf = str2; ety.data.len = 3; ety.id = 2; ety.term = 1; raft_append_entry(r, &ety); CuAssertTrue(tc, 2 == raft_get_log_count(r)); CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 2))); CuAssertTrue(tc, !strncmp(ety_appended->data.buf, str2, 3)); /* pass a appendentry that is newer */ msg_entry_t mety; memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 2; ae.prev_log_idx = 1; ae.prev_log_term = 1; /* include one entry */ memset(&mety, 0, sizeof(msg_entry_t)); char *str3 = "333"; mety.data.buf = str3; mety.data.len = 3; mety.id = 3; ae.entries = &mety; ae.n_entries = 1; raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 1 == aer.success); CuAssertTrue(tc, 2 == raft_get_log_count(r)); CuAssertTrue(tc, NULL != (ety_appended = raft_get_entry_from_idx(r, 1))); CuAssertTrue(tc, !strncmp(ety_appended->data.buf, str1, 3)); }
void TestRaft_follower_recv_appendentries_set_commitidx_to_LeaderCommit( CuTest * tc) { void *r = raft_new(); raft_add_node(r, (void*)1, 1); raft_add_node(r, (void*)2, 0); msg_appendentries_t ae; msg_appendentries_response_t aer; memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; ae.prev_log_idx = 0; ae.prev_log_term = 1; /* include entries */ msg_entry_t e[4]; memset(&e, 0, sizeof(msg_entry_t) * 4); e[0].term = 1; e[0].id = 1; e[1].term = 1; e[1].id = 2; e[2].term = 1; e[2].id = 3; e[3].term = 1; e[3].id = 4; ae.entries = e; ae.n_entries = 4; raft_recv_appendentries(r, 1, &ae, &aer); /* receive an appendentry with commit */ memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; ae.prev_log_term = 1; ae.prev_log_idx = 3; ae.leader_commit = 3; /* receipt of appendentries changes commit idx */ raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 1 == aer.success); /* set to 3 because leaderCommit is lower */ CuAssertTrue(tc, 3 == raft_get_commit_idx(r)); }
int RaftConsensus::onReceivedAppendEntries(const Connection::Ptr& pConnection, msg_appendentries_t& data) { OSS::mutex_lock lock(_raftMutex); int ret = 0; msg_appendentries_response_t response; ret = raft_recv_appendentries(_raft, pConnection->getNode().node(), &data, &response); if (ret != 0) { return ret; } return pConnection->onSendAppendEntriesResponse(response); }
void TestRaft_follower_recv_appendentries_resets_election_timeout( CuTest * tc) { void *r = raft_new(); raft_set_election_timeout(r, 1000); raft_periodic(r, 900); msg_appendentries_t ae; msg_appendentries_response_t aer; memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 1; raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 0 == raft_get_timeout_elapsed(r)); }
/* 5.3 */ void TestRaft_follower_recv_appendentries_reply_false_if_doesnt_have_log_at_prev_log_idx_which_matches_prev_log_term( CuTest * tc) { msg_entry_t ety; char *str = "aaa"; 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); /* term is different from appendentries */ raft_set_current_term(r, 2); raft_set_commit_idx(r, 1); raft_set_last_applied_idx(r, 1); // TODO at log manually? /* log idx that server doesn't have */ memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 2; ae.prev_log_idx = 1; /* prev_log_term is less than current term (ie. 2) */ ae.prev_log_term = 1; /* include one entry */ memset(&ety, 0, sizeof(msg_entry_t)); ety.data.buf = str; ety.data.len = 3; ety.id = 1; ae.entries = &ety; ae.n_entries = 1; /* trigger reply */ raft_recv_appendentries(r, 1, &ae, &aer); /* reply is false */ CuAssertTrue(tc, 0 == aer.success); }
void TestRaft_follower_recv_appendentries_increases_log(CuTest * tc) { msg_appendentries_t ae; msg_entry_t ety; msg_appendentries_response_t aer; char *str = "aaa"; void *r = raft_new(); raft_add_node(r, (void*)1, 1); raft_add_node(r, (void*)2, 0); raft_set_state(r, RAFT_STATE_FOLLOWER); /* log size s */ CuAssertTrue(tc, 0 == raft_get_log_count(r)); /* receive an appendentry with commit */ memset(&ae, 0, sizeof(msg_appendentries_t)); ae.term = 3; ae.prev_log_term = 1; /* first appendentries msg */ ae.prev_log_idx = 0; ae.leader_commit = 5; /* include one entry */ memset(&ety, 0, sizeof(msg_entry_t)); ety.data.buf = str; ety.data.len = 3; ety.id = 1; /* check that old terms are passed onto the log */ ety.term = 2; ae.entries = &ety; ae.n_entries = 1; raft_recv_appendentries(r, 1, &ae, &aer); CuAssertTrue(tc, 1 == aer.success); CuAssertTrue(tc, 1 == raft_get_log_count(r)); raft_entry_t* log = raft_get_entry_from_idx(r, 1); CuAssertTrue(tc, 2 == log->term); }