feat(raft-library): task 6.3 — delegate election dispatch to raft_* API in ha.c + cluster.c
This commit is contained in:
parent
8f0d2d55c3
commit
fd9933c9d0
3 changed files with 163 additions and 292 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue