int raft_recv_appendentries_response(raft_server_t* me_, int node, msg_appendentries_response_t* r) { raft_server_private_t* me = (void*)me_; raft_node_t* p; __log(me_, NULL, "received appendentries response from: %d", node); p = raft_get_node(me_, node); if (1 == r->success) { int i; for (i=r->first_idx; i<=r->current_idx; i++) log_mark_node_has_committed(me->log, i); while (1) { raft_entry_t* e; e = log_get_from_idx(me->log, me->last_applied_idx + 1); /* majority has this */ if (e && me->num_nodes / 2 <= e->num_nodes) { if (0 == raft_apply_entry(me_)) break; } else { break; } } } else { /* If AppendEntries fails because of log inconsistency: decrement nextIndex and retry (�3) */ assert(0 <= raft_node_get_next_idx(p)); // TODO does this have test coverage? // TODO can jump back to where node is different instead of iterating raft_node_set_next_idx(p, raft_node_get_next_idx(p)-1); raft_send_appendentries(me_, node); } return 1; }
int raft_apply_entry(raft_server_t* me_) { raft_server_private_t* me = (void*)me_; raft_entry_t* e; if (!(e = log_get_from_idx(me->log, me->last_applied_idx+1))) return 0; __log(me_, NULL, "applying log: %d", me->last_applied_idx); me->last_applied_idx++; if (me->commit_idx < me->last_applied_idx) me->commit_idx = me->last_applied_idx; if (me->cb.applylog) me->cb.applylog(me->cb_ctx, me, e->data, e->len); return 1; }
raft_entry_t* raft_get_entries_from_idx(raft_server_t* me_, int idx, int* n_etys) { raft_server_private_t* me = (raft_server_private_t*)me_; return log_get_from_idx(me->log, idx, n_etys); }
raft_entry_t* raft_get_entry_from_idx(raft_server_t* me_, int etyidx) { raft_server_private_t* me = (void*)me_; return log_get_from_idx(me->log, etyidx); }
void log_mark_node_has_committed(log_t* me_, int idx) { raft_entry_t* e = log_get_from_idx(me_, idx); if (e) e->num_nodes += 1; }