forked from lei.chen/myxce
feat(raft-drive-async): offload requester-less config-push to slow lane (task 3.3)
push_config_transport_only spawns one thread per standby then joins them with a CONF_PUSH_TIMEOUT_MS bounded wait — blocking the caller. On the requester-less drive-thread paths (promotion + heartbeat convergence) that wait stalls the io_worker. Route those through ha_config_push_offloadable, gated by g_drive_async_configpush_offload (default OFF → inline, byte-for-byte legacy; ON → slow lane, non-blocking). Flag ON deep-copies the config bytes + sha into a lane ctx (caller keeps owning and freeing its own buffer); a single cluster-wide single-flight guard (ha_state_t.configpush_inflight scalar CAS + lane key=1) bounds it to one config-push fan-out in flight; the in-flight flag is cleared on every terminal path (two alloc failures, -EEXIST, hard submit error, lane completion). Send body factored into ha_config_push_do_send. Three requester-less drive-thread call sites converted: raft_cb_become_leader (promotion), the HA_REPL_PUSH_CONFIG heartbeat case, and the direct-CTRL_PRIMARY FSM promotion branch. The admin-upgrade barrier (push_config_to_standbys, has a waiting requester) and join.c are untouched. Lands DORMANT like tasks 3.1/3.2: the lane reads c->ha.standby_endpoints and writes those borrowed standby endpoints, racing io_worker RDHUP teardown if run off-thread (bug-1197 family). Flag OFF keeps push+teardown serialized on the io_worker. Task 3.4 flips this ON together with the snapshot and peerctrl flags after establishing endpoint-lifetime discipline. Tests (controller suite EXIT=0): test_configpush_offload_runs_on_lane, test_configpush_inline_when_flag_off, test_configpush_offload_dedups. Adversarial cpp-review: no CRITICAL/HIGH/MEDIUM findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S6fDCtXkkEgupu7rUah1y2
This commit is contained in:
parent
6c0523b69b
commit
bd02064ebc
5 changed files with 515 additions and 13 deletions
|
|
@ -285,6 +285,20 @@ typedef struct {
|
|||
* snapshot for that peer. Indexed by
|
||||
* ABSOLUTE candidate index. 0 at
|
||||
* init (ha_init memset). */
|
||||
/* ── New field added by raft-drive-async spec (Task 3.3) ──────── */
|
||||
_Atomic int configpush_inflight; /* CLUSTER-WIDE single-flight guard
|
||||
* for the offloaded requester-less
|
||||
* config push. Config push is a
|
||||
* cluster-wide fan-out (one push thread
|
||||
* per standby), so at most ONE is in
|
||||
* flight at a time — hence a scalar, not
|
||||
* a per-peer array. Set (CAS 0->1) when
|
||||
* a config push is submitted to the slow
|
||||
* lane, cleared by the lane worker on
|
||||
* completion (success or failure). While
|
||||
* set, the heartbeat decision loop /
|
||||
* promotion enqueues no duplicate config
|
||||
* push. 0 at init (ha_init memset). */
|
||||
} ha_state_t;
|
||||
|
||||
/* ── Public API ────────────────────────────────────────────── */
|
||||
|
|
@ -1252,6 +1266,27 @@ int ha_reconnect_offload_enabled(void);
|
|||
void ha_set_snapshot_offload_for_test(int on);
|
||||
int ha_snapshot_offload_enabled(void);
|
||||
|
||||
/*
|
||||
* ha_set_configpush_offload_for_test / ha_configpush_offload_enabled:
|
||||
* TDD kill-switch for raft-drive-async task 3.3 requester-less config-push
|
||||
* slow-lane offload.
|
||||
* OFF (0, PRODUCTION DEFAULT): the config push runs INLINE on the caller
|
||||
* (io_worker/drive) thread — byte-for-byte the legacy path (the
|
||||
* requester-less push_config_transport_only fan-out + its blocking
|
||||
* wait_all_with_timeout up to CONF_PUSH_TIMEOUT_MS). The offload lands
|
||||
* DORMANT because the lane task borrows standby endpoints it does not own
|
||||
* (bug-1197 family) and reads c->ha.standby_endpoints; moving the push to a
|
||||
* lane thread while the io_worker may RDHUP-free those endpoints is a
|
||||
* cross-thread UAF. Flag-ON is therefore only safe once Task 3.4
|
||||
* establishes endpoint-lifetime discipline, and flipping it ON is owned by
|
||||
* Task 3.4 (the single gate that flips the snapshot + peerctrl flags too).
|
||||
* ON (1): the config push runs on a slow-lane worker, off the drive thread.
|
||||
* NOTE: the admin-upgrade path (push_config_to_standbys, which has a waiting
|
||||
* requester / barrier) is NOT affected by this flag.
|
||||
*/
|
||||
void ha_set_configpush_offload_for_test(int on);
|
||||
int ha_configpush_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