feat(ha-repl-hardening): snapshot transfer integration and dispatch-path tests (task 3.5d)

- Add ha_repl_send_snapshot_hook seam in ha.c/ha.h for XCE_TESTING
- test_dispatch_repl_action_send_snapshot: verifies SEND_SNAPSHOT
  decision triggers hook when standby_lsn < oldest_wal_lsn
- test_snapshot_recv_two_chunks_assembles_and_renames: verifies standby
  assembles snap.part across chunks and renames on isLast=true
- test_snapshot_recv_reconnect_discards_snappart: verifies O_TRUNC
  semantics on chunk_index==0 restart after reconnect
- All tests pass under ASAN
This commit is contained in:
Rongsong Shen 2026-06-05 02:13:11 +00:00
parent cbd91fca43
commit 18ad3e9c9f
5 changed files with 207 additions and 2 deletions

View file

@ -1167,6 +1167,12 @@ int ha_dispatch_repl_action_for_standby(ha_state_t *ha,
INFO("HA repl: standby[%d] lsn=%" PRIu64
" < oldest_wal_lsn=%" PRIu64 " → requesting snapshot transfer",
peer_idx, standby_lsn, oldest_wal_lsn);
#ifdef XCE_TESTING
if (ha_repl_send_snapshot_hook != NULL) {
ha_repl_send_snapshot_hook(peer_idx);
break;
}
#endif
if (c && c->persist.snap_path[0]) {
extern int ha_send_snapshot_to_standby(endpoint_t *, const char *,
uint64_t);
@ -1756,6 +1762,14 @@ int (*ha_repl_stream_wal_hook)(void *ep, const char *wal_path,
uint64_t standby_lsn,
uint64_t committed_lsn) = NULL;
/*
* ha_repl_send_snapshot_hook: test-only seam for ha_send_snapshot_to_standby.
* When non-NULL, ha_dispatch_repl_action_for_standby() calls this INSTEAD OF
* ha_send_snapshot_to_standby() when the decision is HA_REPL_SEND_SNAPSHOT.
* Requirements: 4.1–4.5 (ha-repl-hardening)
*/
int (*ha_repl_send_snapshot_hook)(int peer_idx) = NULL;
#endif /* XCE_TESTING */
/* ── Election Evaluation (Req 2.1, 2.7, 2.8) ───────────────────────────────