feat(ha-term-safety): out-of-band config bytes, hash-verify-before-activate, serve-fence (task 4.3)
Wires config_committed_marker to a production consumer (config_activate_committed): verifies pushed bytes' sha256 against the committed marker before activation, fences (loud, non-serving, stay-alive) on mismatch, and activates the latest committed marker on recovery. Enforced via ha_dispatch_gate + promotion gate. Fixes bug-981: a 2nd+ config upgrade could permanently fence a standby on a push-before-commit ordering. Adds an off-iomgr delaymgr retry scheduled from the commit-advance hook (atomic read + non-blocking enqueue only on the ACK thread) that re-activates and clears the stale fence once the new marker commits and bytes verify.
This commit is contained in:
parent
c3201a2b1e
commit
be4c1f0721
7 changed files with 1074 additions and 12 deletions
|
|
@ -237,6 +237,23 @@ typedef struct {
|
|||
* caught-up or stopped member never
|
||||
* FATALs. NULL at init / when no fence
|
||||
* timer is pending. */
|
||||
/* ── New field added by ha-term-safety spec (Task 4.3) ──────── */
|
||||
_Atomic int config_serve_fence; /* Config byte-delivery serve-fence
|
||||
* (R7.9): set when the latest committed
|
||||
* WAL_CONFIG_MARKER references config
|
||||
* bytes whose sha256 does NOT match the
|
||||
* locally-held bytes (or the bytes are
|
||||
* absent locally). While set, the member
|
||||
* MUST NOT serve under the new
|
||||
* configuration; the bytes travel
|
||||
* out-of-band via the existing config-push
|
||||
* transport, so the member STAYS ALIVE and
|
||||
* config_activate_committed KEEPS RETRYING
|
||||
* until the matching bytes arrive and
|
||||
* hash-verify, at which point the fence is
|
||||
* cleared and the config is activated.
|
||||
* NEVER self-terminates (loud non-serving
|
||||
* fence only). 0 at init (ha_init memset). */
|
||||
} ha_state_t;
|
||||
|
||||
/* ── Public API ────────────────────────────────────────────── */
|
||||
|
|
@ -528,6 +545,17 @@ int ha_is_primary(const ha_state_t *ha);
|
|||
*/
|
||||
int ha_dispatch_gate(ha_state_t *ha, int opcode);
|
||||
|
||||
/*
|
||||
* ha_config_promotion_fenced: 1 when this member is config serve-fenced and
|
||||
* therefore NON-PROMOTABLE — its latest committed WAL_CONFIG_MARKER references
|
||||
* config bytes it does not hold/match, so it must not become authoritative
|
||||
* CTRL_PRIMARY (ha-term-safety task 4.3, R7.9). 0 otherwise. The pre-promotion
|
||||
* gate in raft_cb_become_leader consults this; a fenced member stays ALIVE and
|
||||
* non-promotable until the correct bytes arrive out-of-band and re-verify clears
|
||||
* the fence (controller-never-self-terminate). Pure atomic read (no I/O).
|
||||
*/
|
||||
int ha_config_promotion_fenced(const ha_state_t *ha);
|
||||
|
||||
/*
|
||||
* ha_apply_wal_catchup_entry: apply a single WAL catch-up entry to local
|
||||
* persistent storage and advance ha->applied_lsn on success.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue