feat(raft-library): task 6.3 — delegate election dispatch to raft_* API in ha.c + cluster.c

This commit is contained in:
Rongsong Shen 2026-05-31 08:43:01 +00:00
parent 8f0d2d55c3
commit fd9933c9d0
3 changed files with 163 additions and 292 deletions

View file

@ -258,23 +258,63 @@ static int myreq_handler(vtask_t* task)
rc = do_clr_preason(c, ep, &request);
break;
case OPCode_requestVote: {
/* Task 6.3: delegate vote-request handling to raft library.
*
* The freshness gate (config_tag / log_lsn comparison) is applied here
* BEFORE calling raft_on_vote_request because raft_cb_vote_eligible
* (on_vote_eligible) intentionally skips the freshness check — it
* relies on the caller (this dispatcher) to enforce it first.
*
* raft_on_vote_request handles:
* - stale-term deny (term < current_term)
* - term upgrade (term > current_term → clear voted_for)
* - role gate: RAFT_LEADER denies; COMMITTING gate in on_vote_eligible
* - one-vote-per-term invariant (voted_for != -1 && voted_for != from_idx)
* - on_persist before granting (durability guarantee)
*
* reply_term is set by raft_on_vote_request to the current term
* (after any term upgrade), so vr_rep.term reflects the latest term. */
request_vote_req_t *vrq = request.body.requestvotemsg;
uint64_t cand_tag = vrq ? vrq->config_tag : 0;
uint64_t cand_lsn = vrq ? vrq->last_log_lsn : 0;
uint64_t cand_term = vrq ? vrq->term : 0;
uint64_t my_tag = c->myconf->config_version_tag;
uint64_t my_lsn = (uint64_t)atomic_load_explicit(
&c->ha.applied_lsn, memory_order_acquire);
int granted = handle_request_vote(
&c->ha, cand_term, vrq ? vrq->candidate_id : "",
cand_tag, cand_lsn, my_tag, my_lsn,
0 /* in_catch_up_flag: not implemented here */);
uint64_t cand_tag = vrq ? vrq->config_tag : 0;
uint64_t cand_lsn = vrq ? vrq->last_log_lsn : 0;
uint64_t cand_term = vrq ? vrq->term : 0;
uint64_t my_tag = c->myconf->config_version_tag;
uint64_t my_lsn = (uint64_t)atomic_load_explicit(
&c->ha.applied_lsn, memory_order_acquire);
/* Freshness gate: deny if candidate is not at least as fresh as us.
* (Req 2.4: config_tag must be ≥ ours; if equal, log_lsn must be ≥ ours.) */
int freshness_ok = !(cand_tag < my_tag ||
(cand_tag == my_tag && cand_lsn < my_lsn));
/* Map candidate name to integer index for raft_on_vote_request. */
int from_idx = -1;
const char *cand_id = vrq ? vrq->candidate_id : "";
if (cand_id && cand_id[0] != '\0') {
const xce_cluster_config_t *pcfg = &c->myconf->peers_cfg;
for (int i = 0; i < pcfg->candidates_count; i++) {
if (strcmp(pcfg->candidates[i].name, cand_id) == 0) {
from_idx = i;
break;
}
}
}
uint64_t reply_term = 0;
int granted = 0;
if (freshness_ok && from_idx >= 0) {
int r = raft_on_vote_request(&c->ha.raft, from_idx, cand_term,
&reply_term);
granted = (r == RAFT_GRANT) ? 1 : 0;
} else {
/* Freshness deny or unknown candidate: read current term for reply */
reply_term = atomic_load_explicit(&c->ha.term, memory_order_acquire);
}
request_vote_reply_t vr_rep;
memset(&vr_rep, 0, sizeof(vr_rep));
vr_rep.term = (uint64_t)atomic_load_explicit(
&c->ha.term, memory_order_acquire);
vr_rep.vote_granted = (granted > 0) ? 1 : 0;
vr_rep.term = reply_term;
vr_rep.vote_granted = granted;
vr_rep.peer_config_tag = my_tag;
vr_rep.peer_last_log_lsn = my_lsn;