feat: P2-5 repl_start/complete_catchup, repl_needs_snapshot — standby catch-up state

Implement the catch-up state machine as testable pure-logic functions:

- repl_start_catchup(): marks standby in_catch_up=1, stores join_applied_lsn
- repl_complete_catchup(): clears in_catch_up=0, broadcasts ack_cond so any
  blocked repl_wait_ack() re-checks the ACK condition immediately
- repl_needs_snapshot(): pure predicate — returns 1 when standby LSN predates
  oldest surviving WAL segment (snapshot transfer required), 0 otherwise

Also fixes pre-existing linker error: repl.c was missing from controller_src
(xce_controller production binary), causing undefined references to repl_*
symbols introduced in P2-4.

7 new TDD tests in test_repl_catchup.c — all pass. Existing tests green.
This commit is contained in:
Rongsong Shen 2026-05-07 18:14:12 +00:00
parent 3563d7387b
commit 6e4fd1aa81
5 changed files with 196 additions and 0 deletions

View file

@ -58,3 +58,15 @@ int repl_wait_ack(replicator_t *r, uint64_t target_lsn, uint32_t timeout_ms);
/* WAL trim guard */
uint64_t repl_trim_lsn(replicator_t *r, uint64_t checkpoint_lsn, uint32_t snap_interval_s);
/* Catch-up state management */
/* Mark standby as entering catch-up mode; stores join_applied_lsn */
void repl_start_catchup(replicator_t *r, repl_ep_t ep, uint64_t join_applied_lsn);
/* Mark standby catch-up complete (called on OP_replCatchUpDone receipt) */
void repl_complete_catchup(replicator_t *r, repl_ep_t ep);
/* Returns 1 if standby needs a full snapshot transfer (its LSN predates oldest WAL).
* oldest_wal_lsn == 0 means no WAL exists — no snapshot needed for LSN 0 standbys. */
int repl_needs_snapshot(replicator_t *r, uint64_t standby_lsn, uint64_t oldest_wal_lsn);