forked from lei.chen/myxce
feat(ha-entity-snapshots): track in-flight snapshot transfer LSN per peer (task 4.1)
Adds snapshot_inflight_lsn[MAX_HA_CANDIDATES] to ha_state_t, alongside the existing snapshot_inflight[] flag it mirrors exactly: set to the checkpoint's LSN at ha_snapshot_send_dispatch before a transfer's first byte goes out, cleared to 0 at every completion/failure path (snapshot_lane_fn's normal completion, and all 3 early-return failure sites: malloc failure, slowlane dedup-refuse, slowlane submit failure). This is the foundation task 4.3 will consult from rotate_snapshots to avoid deleting a checkpoint file a peer is still mid-transfer reading from -- the one genuinely new retention guard this feature needs (the existing write_snapshot-before-trim_wal_segments sequencing already satisfies the WAL-trim side of Requirement 3). Proven via a new gated unit test (test_ha_liveness.c) that observes the tracked LSN mid-flight while the send body is parked at a test gate, not just before/after -- confirms the lifecycle ordering, not just the endpoints. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JDYFbrgyDHbvNYcxApKhrX
This commit is contained in:
parent
eac7bb8ad8
commit
8d1ee8b761
4 changed files with 108 additions and 3 deletions
|
|
@ -2778,7 +2778,12 @@ static void snapshot_lane_fn(void *arg)
|
|||
ha_snapshot_do_send(c, sx->ep, peer_idx);
|
||||
|
||||
/* Clear in-flight LAST so a concurrent heartbeat tick cannot enqueue a
|
||||
* second snapshot for this peer until this one has fully finished. */
|
||||
* second snapshot for this peer until this one has fully finished.
|
||||
* Clear the tracked LSN (Req 3.1-3.3) alongside the flag — same
|
||||
* lifecycle, one more field — so rotate_snapshots never sees a stale
|
||||
* in-flight LSN for a transfer that has already completed. */
|
||||
atomic_store_explicit(&c->ha.snapshot_inflight_lsn[peer_idx], 0,
|
||||
memory_order_release);
|
||||
atomic_store_explicit(&c->ha.snapshot_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
free(sx);
|
||||
|
|
@ -2810,8 +2815,19 @@ static void ha_snapshot_send_dispatch(ha_state_t *ha, cluster_t *c,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Record the checkpoint position this transfer references (Req 3.1-3.3)
|
||||
* at the SAME point the flag above is set — before the first byte of the
|
||||
* transfer goes out — so a reader that observes snapshot_inflight[peer_idx]
|
||||
* == 1 can find a meaningful LSN alongside it. rotate_snapshots (task 4.3)
|
||||
* consults this to avoid deleting the checkpoint file this transfer is
|
||||
* still reading from. */
|
||||
atomic_store_explicit(&ha->snapshot_inflight_lsn[peer_idx],
|
||||
c->persist.checkpoint_lsn, memory_order_release);
|
||||
|
||||
snapshot_send_ctx_t *sx = malloc(sizeof(*sx));
|
||||
if (!sx) {
|
||||
atomic_store_explicit(&ha->snapshot_inflight_lsn[peer_idx], 0,
|
||||
memory_order_release);
|
||||
atomic_store_explicit(&ha->snapshot_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
return;
|
||||
|
|
@ -2827,6 +2843,8 @@ static void ha_snapshot_send_dispatch(ha_state_t *ha, cluster_t *c,
|
|||
* refused — release the flag we set so no clear is lost, and let the
|
||||
* next tick retry. */
|
||||
free(sx);
|
||||
atomic_store_explicit(&ha->snapshot_inflight_lsn[peer_idx], 0,
|
||||
memory_order_release);
|
||||
atomic_store_explicit(&ha->snapshot_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
return;
|
||||
|
|
@ -2838,11 +2856,14 @@ static void ha_snapshot_send_dispatch(ha_state_t *ha, cluster_t *c,
|
|||
WARN("HA repl: slowlane_submit snapshot peer[%d] failed: %d — retry "
|
||||
"next cycle", peer_idx, srv);
|
||||
free(sx);
|
||||
atomic_store_explicit(&ha->snapshot_inflight_lsn[peer_idx], 0,
|
||||
memory_order_release);
|
||||
atomic_store_explicit(&ha->snapshot_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
return;
|
||||
}
|
||||
/* 0 or -EAGAIN: enqueued exactly once; snapshot_lane_fn clears the flag. */
|
||||
/* 0 or -EAGAIN: enqueued exactly once; snapshot_lane_fn clears the flag
|
||||
* and the tracked LSN. */
|
||||
}
|
||||
|
||||
/* ───────────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue