feat: implement persist_recover with snapshot load and WAL replay (P0-4)

- Add load_snapshot(): reads P0 sentinel ("XCESNAP\0" + lsn), validates magic,
  extracts checkpoint_lsn
- Add replay_wal(): scans seg-*.wal files in LSN order, skips entries <= from_lsn,
  verifies CRC chain, stops on mismatch, applies entries via apply_wal_entry() stub
- Add persist_recover(): find latest .capnp snapshot, load it, replay post-checkpoint
  WAL, retention pass (no-op in P0)
- Fix trim_wal_segments(): compare against active segment start LSN (not checkpoint_lsn)
  to avoid deleting the currently-open segment and losing post-checkpoint WAL entries
- Add restore_job() stub in job.c (P0-12a placeholder)
- Add worker_from_capnp() stub in worker.c (P0-12 placeholder)
- Declare both new functions in cluster.h and worker.h
- Add 5 recovery tests: empty state, snapshot lsn loading, WAL replay, corrupt
  sentinel rejection, latest-snapshot selection; all 23 controller tests pass
This commit is contained in:
Rongsong Shen 2026-05-07 11:41:33 +00:00
parent e76f76a88a
commit f905f891a8
8 changed files with 584 additions and 7 deletions

View file

@ -646,3 +646,15 @@ int do_hostcontrol_op(cluster_t* c, endpoint_t* ep, xce_request_t* request)
xce_reply(ep, c->myhost, &reply);
return rc;
}
/* P0 stub — bridges Cap'n Proto deserialization to restore_worker().
* Full implementation in Task 15 (cluster wiring): deserializes the
* Cap'n Proto Worker object, deep-copies pointer fields, and calls
* restore_worker(cls, host). */
int worker_from_capnp(cluster_t* c, const void* capnp_payload, size_t len)
{
(void)c;
(void)capnp_payload;
(void)len;
return 0;
}