feat(ha-term-safety): restore controller build + wire vote/AE term wire fields (tasks 1.1, 1.2)

1.1: WalCatchupEntry gains term@4/prevLogIndex@5/prevLogTerm@6 (append-only).
1.2: RequestVote/PreVote gain lastLogTerm@4/lastLogIndex@5; cluster.c vote callers
fixed to the extended library arity (RESTORES xce_controller + controller_unit_test
compile+link, broken by the raft-commit-safety signature extension); ha.c emits the
candidate's last-log tuple on send.

5 minimal stub log/commit callbacks wired into s_real_cbs so raft_init's new
non-NULL requirement is satisfied — tasks 2.x replace them with real bodies; the
logOk freshness gate is inert until the term seam (1.3) + on_get_entry_term (2.2).

Pre-existing test_repl_unit.c wal_catchup -EAGAIN failures + ASAN leaks are an
overlayfs /tmp fsync env artifact (bug-850), not from this task (untouched paths;
append-only schema cannot affect the @3 entries-list decode). Build/baseline
isolation is blocked by a c-capnproto flake-hash drift — see Implementation Notes.
This commit is contained in:
Rongsong Shen 2026-06-22 03:41:49 +00:00
parent e8e41752c0
commit 004a40bb3b
9 changed files with 264 additions and 9 deletions

View file

@ -444,13 +444,19 @@ static void test_prevote_reply_over_real_transport_reaches_tally(void)
* heartbeat gate fires first — so the freshness check is omitted for clarity.)
*
* Returns 1 = grant, 0 = deny; *out_reply_term = voter's unchanged term. */
extern int raft_on_pre_vote_request(raft_state_t *s, int from_idx, uint64_t cand_term);
/* raft_on_pre_vote_request is declared in raft.h (now carries the candidate
* (lastLogTerm, lastLogIndex) tuple — ha-term-safety task 1.2); no local extern. */
static int voter_pre_vote_decide(ha_state_t *ha, int from_idx, uint64_t cand_term,
uint64_t *out_reply_term)
{
/* Pass (0,0) for the candidate last-log tuple: this PreVote test exercises
* the role/heartbeat eligibility gate, not the logOk freshness path; with
* the on_get_entry_term stub reading local last-log term as 0, logOk grants
* so existing gate behavior is preserved (ha-term-safety task 1.2). */
int granted =
(raft_on_pre_vote_request(&ha->raft, from_idx, cand_term) == RAFT_GRANT)
(raft_on_pre_vote_request(&ha->raft, from_idx, cand_term, 0, 0)
== RAFT_GRANT)
? 1 : 0;
if (out_reply_term)
*out_reply_term = atomic_load_explicit(&ha->term, memory_order_acquire);