forked from lei.chen/myxce
docs(raft-ha-core-safety): document term-blind bypass safe-by-guard + pin restart identity (task 6.2)
The term-blind ha_apply_single_entry direct-persist branch (carried forward from task 2.4) is unreachable with a real non-zero term in any current production path: its only trigger, raft_send_append_entries, has zero production call sites (library simulator only). Both real senders (repl_broadcast, ha_stream_wal_to_standby) always emit a non-zero term for a present LSN. Documents this in ha.c and design.md rather than structurally retiring a dormant path (YAGNI), with an explicit flag for future re-evaluation if a heartbeat-driver task ever wires up raft_send_append_entries. Adds two regression pins: restart preserves (term,lsn) identity (replay_wal already reconstructs the term index via record_entry_term), and real senders never produce the term-blind wire shape. test_ha_core_safety 28/0, no regression, no ASAN reports.
This commit is contained in:
parent
4e1e3e07fb
commit
9344b8ed60
4 changed files with 338 additions and 8 deletions
|
|
@ -2130,7 +2130,32 @@ static void ha_advance_applied_lsn(ha_state_t *ha, uint64_t new_lsn)
|
|||
* Payload bytes (raw_payload/raw_payload_len, extracted by xce_decode)
|
||||
* are passed through to apply_wal_entry so entity state is restored —
|
||||
* not just the LSN chain (task 7.3).
|
||||
* Returns 0 on success, non-zero on error (caller logs and skips). */
|
||||
* Returns 0 on success, non-zero on error (caller logs and skips).
|
||||
*
|
||||
* raft-ha-core-safety task 6.2 — TERM-BLIND DIRECT-PERSIST BYPASS, SAFE-BY-
|
||||
* GUARD (documented, not structurally retired): this function does NOT go
|
||||
* through raft_on_append_entries_request's logOk/(term,lsn) reconcile — it
|
||||
* calls persist_wal_write_replicated directly. Task 2.4 deferred deciding
|
||||
* this bypass's fate to 6.2; 6.2's reachability trace (see the two call
|
||||
* sites below and ha_apply_wal_catchup_entry) found it is UNREACHABLE with
|
||||
* real production data today: every real sender (repl_broadcast for live
|
||||
* replication; ha_stream_wal_to_standby for catch-up) always supplies
|
||||
* n_entries>=1 with a non-zero term (persist_entry_term's legacy-zero rule
|
||||
* maps a stored term of 0 to WAL_LEGACY_TERM for any present LSN — it never
|
||||
* returns 0 for a real entry). The ONLY function that could ever drive a
|
||||
* term==0 / n_entries==0 message into this path (repl_send_append_entries)
|
||||
* is called solely from the raft library's raft_send_append_entries, which
|
||||
* has zero production callers (only lib/raft/raft_sim.c and an XCE_TESTING
|
||||
* helper call it) — so that trigger is dormant, not live, code. Even if this
|
||||
* path were reached, the task-2.2 (term,lsn,payload-crc)-aware guard inside
|
||||
* persist_wal_write_replicated already refuses to degrade a stored non-empty
|
||||
* entry to empty and raises the sticky non-promotable fence on an
|
||||
* unrepairable below-tip conflict — pinned by
|
||||
* test_2_3_termblind_route_payload_guarded and
|
||||
* test_2_3_unrepairable_catchup_raises_nonpromotable_fence
|
||||
* (test_ha_core_safety.c). See ha_apply_wal_catchup_entry below and
|
||||
* test_6_2_real_senders_never_produce_termblind_shape for the reachability
|
||||
* evidence this comment summarizes. */
|
||||
static int ha_apply_single_entry(persist_t *p, wal_catchup_entry_t *e)
|
||||
{
|
||||
/* Persist-before-apply-before-ACK: durably write the replicated entry to
|
||||
|
|
@ -2316,7 +2341,18 @@ int ha_apply_wal_catchup_entry(ha_state_t *ha, persist_t *p,
|
|||
* retires the term-0 direct-apply path for live/catch-up replication.
|
||||
* Entries stream in ascending LSN order, so the library's contiguity
|
||||
* (prev tuple) is satisfied in sequence; a not-yet-applicable entry
|
||||
* (logOk reject) is left for the catch-up continuation. */
|
||||
* (logOk reject) is left for the catch-up continuation.
|
||||
*
|
||||
* raft-ha-core-safety task 6.2: the `sub->term != 0` fallthrough
|
||||
* below is the term-blind direct-persist bypass (ha_apply_single_
|
||||
* entry) — documented SAFE-BY-GUARD, not structurally retired.
|
||||
* ha_stream_wal_to_standby (the only real batch-catch-up sender)
|
||||
* always stamps sub->term via persist_entry_term, which maps a
|
||||
* legacy on-disk term of 0 to WAL_LEGACY_TERM for any present LSN,
|
||||
* so a real streamed sub-entry is never term==0 — this fallthrough
|
||||
* is unreachable with production data (see the ha_apply_single_
|
||||
* entry comment for the full reachability trace + the pin test
|
||||
* test_6_2_real_senders_never_produce_termblind_shape). */
|
||||
if (c && c->ha.raft_c == c && sub->term != 0) {
|
||||
if (ha_apply_term_entry_via_library(ha, p, c, ep, sub)) {
|
||||
last_good_lsn = sub->lsn;
|
||||
|
|
@ -2356,7 +2392,20 @@ int ha_apply_wal_catchup_entry(ha_state_t *ha, persist_t *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ── Single-entry mode (task 2.1 backward-compatible path) ────────────── */
|
||||
/* ── Single-entry mode (task 2.1 backward-compatible path) ──────────────
|
||||
* raft-ha-core-safety task 6.2: this branch calls ha_apply_single_entry
|
||||
* UNCONDITIONALLY — no term check at all — so it is the other half of the
|
||||
* term-blind bypass documented at ha_apply_single_entry above. It is only
|
||||
* ever reached with entry->n_entries==0, the 0-entry AppendEntries
|
||||
* heartbeat shape built by repl_send_append_entries. That function is
|
||||
* called solely from the raft library's raft_send_append_entries, which
|
||||
* has ZERO production call sites (only lib/raft/raft_sim.c and an
|
||||
* XCE_TESTING test helper call it) — so in the CURRENT codebase this
|
||||
* branch is dormant/unreachable from any live sender, not a legacy-
|
||||
* rollout shape carrying real data. Documented SAFE-BY-GUARD (not
|
||||
* structurally retired): see the ha_apply_single_entry comment for the
|
||||
* full reachability trace and the task-2.2 guard that would still bound
|
||||
* the damage if this ever became reachable. */
|
||||
int rc = ha_apply_single_entry(p, entry);
|
||||
if (rc != 0) {
|
||||
/* -EAGAIN = contiguity gap (bug-850): dropped quietly, backfilled by
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue