fix bug-1060 bug-1067

This commit is contained in:
Rongsong Shen 2026-06-24 17:05:43 +08:00
parent 6067ba6c94
commit 61e1391cd0
28 changed files with 7021 additions and 2926 deletions

View file

@ -599,6 +599,25 @@ void ha_compute_safe_committed_lsn(ha_elect_ctx_t *ctx,
uint64_t *safe_lsn_out,
uint64_t *safe_tag_out);
/* ── bug-1060: Leader Completeness guard for promotion-time WAL truncation ────
*
* ha_promotion_truncate_floor: clamp the post-election WAL truncation cutoff so
* a newly-elected leader NEVER truncates entries it holds durably.
*
* Returns max(safe_lsn, durable_tip). safe_lsn is the majority-threshold commit
* point from the vote replies (ha_compute_safe_committed_lsn); durable_tip is the
* leader's own durable WAL tip (persist_durable_floor). Because the cutoff is
* never below the leader's durable tip, persist_truncate_wal_above is a no-op on
* the leader's own durable log — preserving every entry committed by a prior
* leader (Raft §5.4 Leader Completeness). safe_lsn only governs removal of a
* divergent, non-durable tail STRICTLY ABOVE the leader's durable tip.
*
* Root cause it fixes: truncating to the bare majority element destroyed
* committed entries the new leader had acked as a standby (granted voters
* {self=47, peer=44} → safe_lsn=44 cut the leader's own committed 45..47),
* producing divergent WALs and a permanent prevote deadlock. */
uint64_t ha_promotion_truncate_floor(uint64_t safe_lsn, uint64_t durable_tip);
/* ── ha-commit-durability task 4.3: pre-promotion eligibility gate ──────────
*
* ha_promotion_gate_decision: PURE pre-promotion eligibility decision (Req 2.2,
@ -957,6 +976,17 @@ uint64_t ha_candidate_advertise_lsn(persist_t *p);
* already-higher applied_lsn (monotonic). */
void ha_sync_applied_lsn_from_recovery(ha_state_t *ha, persist_t *p);
/* ha_sync_raft_log_from_recovery (bug-1042) — after local WAL recovery on a
* (re)start, raise the raft LIBRARY's log_len / commit_index / term to the
* recovered position. ha_init_raft (before the election) sources the library's
* initial_log_len from persist_durable_floor, but on a standby-rejoin boot
* persist_recover runs LATER (cluster_init_phase2), so the library would
* otherwise stay at log_len=0 and reject every incoming AppendEntries (logOk
* fails for prevLogIndex>=1), wedging the rejoined member as a permanently non-
* converging standby. Call this right after persist_recover. Monotonic + NULL-
* safe; clamps commit_index<=log_len. */
void ha_sync_raft_log_from_recovery(ha_state_t *ha, persist_t *p);
/*
* ha_elect_evaluate_and_signal: evaluate accumulated ha_elect_ctx_t votes.
* Sets ctx->result (1=primary, 0=standby) and posts ctx->done semaphore.