feat(raft-drive-async): snapshot SlowLane offload + WAL-trim cursor guard (task 3.2)
Part B (LIVE, default-ON): trim_wal_segments now bounds WAL-segment deletion by repl_trim_lsn(&p->repl, active_seg_lsn) = min(active segment LSN, every active standby acked_lsn, every valid disconnected-slot last_disconnected_lsn), after repl_expire_disconnect_slots ages out stale slot guards. floor <= active_seg_lsn structurally, so the guard can only preserve more segments, never delete one a live standby still needs — closes the bug-795/828 trim-vs-cursor race for connected/recently-disconnected standbys (bug-1147 stopgap; empty/cursor=0 join still needs entity-bearing snapshots). Part A (DORMANT, g_drive_async_snapshot_offload default OFF): ha_snapshot_send_ dispatch routes HA_REPL_SEND_SNAPSHOT inline (flag OFF — byte-for-byte legacy, on io_worker) or to slowlane_submit+snapshot_lane_fn (flag ON). Send body factored into ha_snapshot_do_send. Per-peer single-flight via ha_state_t.snapshot_inflight[] CAS + slowlane key; in-flight flag cleared on all four terminal paths, mirroring the reconnect offload (task 2.1). Lands dormant like task 3.1: snapshot_lane_fn borrows a standby endpoint it does not own, so flag-ON would race io_worker RDHUP teardown (cross-thread UAF, bug-1197 family). Flag OFF keeps send+teardown serialized on the io_worker. Task 3.4 is the single gate that flips both this and the peerctrl flag ON after establishing endpoint-lifetime discipline; bug-1198 stays open by design until then. The offload flag was initially authored default-ON (would ship the UAF) and corrected to OFF in ha.c and the ha.h accessor doc (bug-1210). Tests (controller 196/0, 0 new leaks): test_snapshot_offload_runs_on_lane, test_snapshot_inline_when_flag_off, test_snapshot_offload_dedups_per_peer, test_trim_guard_preserves_standby_segments, test_trim_without_standbys_proceeds_normally. Adversarial cpp-review: GO. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S6fDCtXkkEgupu7rUah1y2
This commit is contained in:
parent
e17a6a613c
commit
6c0523b69b
8 changed files with 2046 additions and 850 deletions
|
|
@ -273,6 +273,18 @@ typedef struct {
|
|||
* that peer. Indexed by ABSOLUTE candidate
|
||||
* index (peers_cfg.candidates[]). 0 at
|
||||
* init (ha_init memset). */
|
||||
/* ── New field added by raft-drive-async spec (Task 3.2) ──────── */
|
||||
_Atomic int snapshot_inflight[MAX_HA_CANDIDATES]; /* Per-peer
|
||||
* single-flight guard for the offloaded
|
||||
* snapshot send (Req 1.5): set (CAS
|
||||
* 0->1) when a snapshot to peer[i] is
|
||||
* submitted to the slow lane, cleared by
|
||||
* the lane worker on completion (success
|
||||
* or failure). While set, the heartbeat
|
||||
* decision loop enqueues no duplicate
|
||||
* snapshot for that peer. Indexed by
|
||||
* ABSOLUTE candidate index. 0 at
|
||||
* init (ha_init memset). */
|
||||
} ha_state_t;
|
||||
|
||||
/* ── Public API ────────────────────────────────────────────── */
|
||||
|
|
@ -1227,6 +1239,19 @@ void ha_start_primary_heartbeat(cluster_t *c);
|
|||
void ha_set_reconnect_offload_for_test(int on);
|
||||
int ha_reconnect_offload_enabled(void);
|
||||
|
||||
/*
|
||||
* ha_set_snapshot_offload_for_test / ha_snapshot_offload_enabled:
|
||||
* TDD kill-switch for raft-drive-async task 3.2 snapshot slow-lane offload.
|
||||
* OFF (0, PRODUCTION DEFAULT): snapshot send runs INLINE on the caller
|
||||
* (io_worker/drive) thread — byte-for-byte the legacy path. The offload
|
||||
* lands DORMANT because it borrows a standby endpoint that is not yet
|
||||
* pool-lifetime-safe (bug-1197); so bug-1198 stays open by design until
|
||||
* Task 3.4 flips this ON together with the peer-control dispatch flag.
|
||||
* ON (1): snapshot send runs on a slow-lane worker, off the drive thread.
|
||||
*/
|
||||
void ha_set_snapshot_offload_for_test(int on);
|
||||
int ha_snapshot_offload_enabled(void);
|
||||
|
||||
/*
|
||||
* ha_set_peerctrl_dispatch_for_test / ha_peerctrl_dispatch_enabled:
|
||||
* Feature-flag accessors (raft-drive-async Task 3.1). The dispatch flag gates
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue