Commit graph

171 commits

Author SHA1 Message Date
3030012f51 feat: JOB_STAT_TRANSIENT, job_should_retain, worker_should_retain, dead_since (P0-5a, P0-8, P0-13)
Add terminal-state constants and GC retention predicates for the
checkpoint xzarray_thaw() GC pass:

- types.h: add JOB_STAT_TRANSIENT (0x400), XCE_WORKER_HIDDEN (0x00200000),
  QUEUE_STAT_HIDDEN (0x0100)
- persist.c: implement job_is_terminal(), job_should_retain(),
  worker_should_retain() — placed here so the unit test binary
  (which links only persist.c) can access them without RTTI deps
- persist.h: declare the three GC predicates; include xce/types.h
- worker.c: set dead_since = time(NULL) in mark_worker_unavail()
  when dead_since is not already set
- cluster.c: add TODO P0-8b marker on zarray_del endpoint cleanup
- meson.build: register test_gc_retention.c; raise test timeout 60→120s
- testsuite/test_gc_retention.c: 19 tests covering job_is_terminal,
  job_should_retain (TRANSIENT TTL, terminal TTL, non-terminal always
  retained), and worker_should_retain (HIDDEN/UNAVAIL/healthy/zero
  dead_since); all pass (63 total, 0 failures)
2026-05-07 12:52:07 +00:00
6f3b98c6b5 feat: persistence hook functions wired to WAL write on AFTER_EVENT (P0-6)
Implements persist_job_hook_fun, persist_queue_hook_fun, and
persist_worker_hook_fun — AFTER_EVENT hooks that write WAL entries
whenever state mutations occur in the controller.

- detail_to_wal_type() maps all 15 HOOK_DETAIL_* values to WAL types;
  unknown details return 0 and are silently skipped
- HOOK_DETAIL_JOB_NEW uses the sync replication path (WAL_JOB_SUBMIT);
  all others use persist_wal_async
- P0 payload: 4-byte detail value; full Cap'n Proto serialization in Task 15
- Hook signature matches hook_fn_t exactly:
  int fn(int type, int situation, int detail, void* cls, va_list ap)
- Added <stdarg.h> to persist.h for va_list; added hook.h and
  xce/cluster_def.h includes to persist.c
- 18 new unit tests in test_persist_hooks.c covering all 15 detail→WAL
  mappings, skip-on-unknown, and sequential LSN advancement
2026-05-07 12:28:20 +00:00
045d9e3287 feat: add HOOK_DETAIL_JOB_STOP/RESUME; fix xce_reply ordering after AFTER_EVENT hooks (P0-4a)
- cluster_def.h: add struct tag `cluster_s` to cluster_t to resolve
  conflicting typedef with persist.h forward declaration
- cluster_def.h: add HOOK_DETAIL_JOB_STOP and HOOK_DETAIL_JOB_RESUME enum
  values after HOOK_DETAIL_JOB_RUSAGE_UPDATE
- job.c on_job_stop(): replace mark_job_update() call with direct
  xce_run_hooks(BEFORE/AFTER, HOOK_DETAIL_JOB_STOP) so WAL writer
  records stop events with the correct detail value
- job.c on_job_resume(): same pattern with HOOK_DETAIL_JOB_RESUME
- job.c do_clr_preason(): fix typo — second hook call was HOOK_BEFORE_EVENT
  instead of HOOK_AFTER_EVENT (double-before, zero-after bug)
- join.c handle_worker_join(): move xce_reply() to after HOOK_AFTER_EVENT
  so client ACK is not sent before WAL write completes (durability fix)
- testsuite/test_hooks.c: new TDD tests for JOB_STOP/RESUME enum values
- testsuite/controller_test.c + meson.build: register test_hooks suite

Reply ordering audit results:
  job.c handle_jobsubmit: reply before AFTER_EVENT — intentional (jobid
    returned to client before scheduler notification; WAL hook belongs in
    BEFORE_EVENT for this path, handled in Task 13)
  job.c do_set_preason: reply before set_preason() loop — intentional
    fire-and-forget (no AFTER_EVENT hook at top level)
  job.c do_clr_preason: reply before loop — same fire-and-forget pattern
  job.c do_jobcontrol_op: no AFTER_EVENT hook, reply only — OK
  join.c handle_worker_join: FIXED (reply moved after AFTER_EVENT)
  worker.c on_worker_update/dead: reply after all hooks — OK
  cluster.c: AFTER_EVENT hooks are internal (no reply) — OK
2026-05-07 12:08:52 +00:00
f905f891a8 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
2026-05-07 11:41:33 +00:00
e76f76a88a feat: implement persist_checkpoint with WAL marker, snapshot, trim, rotation (P0-3)
- persist_write_checkpoint_marker(): writes WAL_CHECKPOINT header entry
  with CRC, increments current_lsn; never updates last_replicated_crc
  (checkpoint markers are local-only, never replicated)
- write_snapshot(): atomic tmp→rename write of P0 sentinel snapshot
  ("XCESNAP\0" + checkpoint_lsn); full Cap'n Proto body in Task 11
- trim_wal_segments(): removes seg-*.wal files whose start LSN is
  strictly less than checkpoint_lsn
- rotate_snapshots(): collects .capnp files, sorts by name (LSN order),
  deletes oldest beyond snap_keep_n
- persist_checkpoint(): EBUSY guard via atomic_exchange, sequences
  marker→lsn record→snapshot→trim→rotate, clears flag on exit
- 5 TDD tests in test_persist_checkpoint.c covering: snapshot file
  creation, checkpoint_lsn advance, WAL lsn advance, EBUSY guard,
  and rotation keeping at most snap_keep_n files
- All 18 controller unit tests pass (0 failures)
2026-05-07 11:19:08 +00:00
813a5a3359 test: add KVMGR_KEY_INT coverage to kvmgr_capture_keys tests
Adds test_capture_keys_int_kvmgr() to verify integer-keyed kvmgr path.
Tests that kvmgr_capture_keys() correctly formats integer keys as decimal
strings via snprintf (PRId64), and validates key_len == strlen(key) + 1.

All 4 kvmgr_capture tests pass.
2026-05-07 11:12:11 +00:00
eaf1801d6d feat: implement kvmgr_capture_keys for lock-free checkpoint serialization (P0-14a)
Add kvtab_foreach walk primitive (P0-14) to kv.c/kv.h, then implement
kvmgr_capture_keys in kvmgr.c that deep-copies all key→index mappings
into a malloc'd slot_key_t[] array safe to read after the write lock is
released during checkpoint serialization (Part 3.8).

Key design points:
- Both kvtab_foreach and kvmgr_capture_keys take var (RTTI data pointer)
  and use RTTI_DATA_TO_OBJ internally — the RTTI framework's makeInstance
  returns the data region pointer, not the meta_obj_t header pointer
- String keys are copied via strncpy into slot_key_t.key[XCE_MAXNAME_LEN]
- Integer keys are formatted as decimal strings via snprintf
- Two-pass approach: count live entries first, allocate, then fill
- Tests cover string kvmgr (3 entries), empty kvmgr, and deep-copy safety
2026-05-07 11:07:41 +00:00
4903c83f28 feat: add PersistConfig, SnapshotHeader, ReplEnvelope Cap'n Proto schemas (P0-9)
Extends src/schema/controller.capnp with persistence structures needed
for WAL replication and snapshots:

- PersistConfig (8 fields, @0-@7): capnp-serialisable copy of the
  persistence configuration; mapped to capnp_persist_cfg_t to avoid
  collision with the plain-C persist_config_t in persist.h
- SnapshotHeader (9 fields, @0-@8): snapshot manifest with LSN, term,
  timestamp, record counts and checksums; mapped to capnp_snap_hdr_t
- ReplEnvelope (6 fields, @0-@5): replication wire envelope (NOT the
  on-disk format); named to avoid collision with wal_entry_hdr_t and
  the WALEntry_ internal symbol c-capnproto generates; mapped to
  capnp_repl_envelope_t

Also extends existing structs:
- Job.transientSince @11 (UInt64=0, mapname transient_since): set when
  job enters JOB_STAT_TRANSIENT; also adds uint64_t transient_since to
  xce_job_t in types.h
- Worker.deadSince @6 (UInt64=0, mapname dead_since): mirrors existing
  time_t dead_since field in xce_worker_t

OPCode enum extended with 7 replication opcodes @22-@28:
  replEntry, replAck, redirect, heartbeat, steppingDown,
  replSnapshot, replCatchUpDone

New C typedefs (capnp_persist_cfg_t, capnp_snap_hdr_t,
capnp_repl_envelope_t) added to typemap.h for the encode/decode shims.

TDD: test_persist_schema.c added (6 tests, all GREEN). Controller test
suite remains 1/1 PASS.
2026-05-07 10:19:33 +00:00
1fe79ff934 fix: check rotate_segment return value; use uint32_t for CRC fields
- In persist_wal_async(), check rotate_segment() return value and propagate -EIO on failure (MEDIUM)
- Change last_crc and last_replicated_crc fields from uint64_t to uint32_t to match CRC32 width (LOW)

Both fixes address code review issues in commit b0a5fbb.
2026-05-07 10:04:43 +00:00
b0a5fbb4e9 feat: persist.c WAL writer with chained CRC32 and dedicated fsync pthread (P0-1)
- Expose persist_t struct concretely in persist.h (opaque pattern deferred)
- persist_set_workdir() derives wal/snap paths from workdir+name
- persist_init() creates WAL/snap directories, rejects NFS mounts
- persist_wal_async() writes WAL entries with chained CRC32 via zlib
- Dedicated fsync pthread fires every wal_sync_ms milliseconds
- persist_flush() forces fdatasync for tests and clean shutdown
- WAL_CHECKPOINT type rejected with -EINVAL (never written via async path)
- Stubs: persist_recover, persist_wal_sync_append, persist_checkpoint
- Add fsync_thread_running flag to guard persist_stop when thread not started
- Add zlib_dep to controller and unit test meson targets
- 3 new TDD tests: init_creates_directories, wal_async_writes_entry,
  checkpoint_type_rejected — all GREEN
2026-05-07 10:00:10 +00:00
d66a8a98b6 fix: use acquire/release ordering for inuse atomic ops in xzarray (P0-2)
Changed all memory_order_relaxed accesses on xzarray_item_t.inuse to use:
- memory_order_acquire for loads
- memory_order_release for stores

This ensures proper synchronization semantics as specified in the P0-2 spec,
even in xzarray_thaw() where accesses are under an exclusive write lock.

15 sites changed:
- xzarray_destroy: 1 load (line 424)
- xzarray_ensure_items: 1 store, 1 load (lines 457, 464)
- xzarray_store: 1 load, 1 store (lines 487, 489)
- xzarray_get_vec: 3 loads (lines 525, 529, 543)
- xzarray_put_vec: 1 load, 1 store (lines 591, 600)
- xzarray_clear: 1 load, 1 store (lines 624, 631)
- xzarray_iter_next: 1 load (line 654)
- xzarray_thaw: 2 loads, 1 store (lines 732, 743, 745)

All COW tests pass (test_freeze_thaw_slots_exist through
test_double_freeze_fails). Same 4 pre-existing failures expected.
2026-05-07 09:51:37 +00:00
4c591a11d3 feat: implement xzarray COW freeze/thaw with pre-grown shadow array (P0-2)
- Add in_cow flag + shadow/shadow_caps fields to xzarray_private_t
- Convert xzarray_item_t.inuse from bitfield to _Atomic _Bool; update
  all read/write sites to use atomic_load/store_explicit
- Implement xzarray_freeze(): O(1) ptr swap, pre-grows active array
  1.5x+16 to avoid realloc during COW, sets pos past shadow range
- Implement xzarray_thaw(): merges shadow into active (shadow wins only
  for slots not updated during COW), supports optional retain_fn GC
- xzarray_get_vec(): falls back to shadow during COW so reads remain
  valid between freeze and thaw
- Add COW guard assertion in xzarray_clear()
- Wire vfreeze/vthaw into xzarray_type interface
- Tests: 5 new COW tests all green; 4 pre-existing failures unchanged
2026-05-07 09:46:28 +00:00
fe69dcbd7a feat: add persist.h — WAL types, persist_config_t, slot_key_t (P0-B)
- Define wal_entry_hdr_t (40 bytes, _Static_assert enforced)
- Define wal_entry_type enum (WAL_JOB_SUBMIT=1 … WAL_CHECKPOINT=100)
- Define persist_config_t with persist_config_defaults() inline helper
- Define slot_key_t (index, key[XCE_MAXNAME_LEN], key_len)
- Forward-declare persist_t opaque struct and full persist_* API surface
- Bootstrap controller Unity test suite (controller_unit_test binary)
- Register test('controller test', …, suite: 'controller') in meson
- 4 new tests all PASS: wal_header_size, wal_entry_types,
  persist_config_defaults, slot_key_t_fields
2026-05-07 09:21:36 +00:00
0107828a77 fix: handle precision_ms >= 1000 in delay_worker nanosleep (tv_nsec overflow) 2026-05-07 09:12:10 +00:00
6d4d8eb81d feat: rename delaymgr precision→precision_ms, replace sleep() with nanosleep() (P0-2b)
- Rename `precision` field to `precision_ms` in delaymgr_t struct (delay.h)
- Replace `sleep(mgr->precision)` with `nanosleep()` for 10ms granularity (delay.c)
- Add `#include <time.h>` to delay.c (already in delay.h)
- Update delaymgr_init() to store precision_ms parameter
- Update all call sites: cluster.c (2→200ms), controller/testsuite/test.c (2→2000ms),
  lib/testsuite/test_delay.c (1→1000ms)
- Add TDD test test_delaymgr_precision_ms_field verifying field exists and stores correctly
- delay_task() delay parameter remains in seconds; only sleep granularity changes
2026-05-07 09:08:03 +00:00
762b59c043 fix typo caused dead lock 2026-05-07 09:07:36 +00:00
c78f9cf91c feat: add vfreeze/vthaw slots to intf_varray_t; designated initializers (P0-0b)
rtti header already present at rtti-0.0.2 with vfreeze_fn_t, vthaw_fn_t,
retain_fn_t, and the two new slots in intf_varray_t. No header modification
needed.

Convert intf_varray_t compound-literal initializers in zarray.c and kvmgr.c
to designated style with explicit .vfreeze = NULL and .vthaw = NULL slots.
kv.c has no intf_varray_t initializer.

Add test_zarray_cow.c with test_freeze_thaw_slots_exist which verifies the
struct layout has the slots accessible and that they are NULL until P0-2
wires the real implementations. Wire test into meson.build and test.c.

Full clean rebuild confirmed: 27/28 targets linked, no new test failures.
Only the 4 pre-existing failures remain.
2026-05-07 08:54:18 +00:00
e0e2f56c81 feat: add persistence/HA system constants to config.h with tests (P0-A)
Adds 17 compile-time constants covering WAL format, HA topology,
snapshot sizing, and operational defaults. test_persistence_constants
in test_config.c validates every constant value; all 6 config tests
pass (4 pre-existing unrelated failures unchanged).
2026-05-07 08:41:19 +00:00
dffa44d59b chore: remove dead code from job.c/cluster.c (Part 1)
- job.c: remove unused #define NJOBS (100) constant
- job.c: remove unused global uint64_t jobid = 100
- job.c: remove #if 0 dead block inside load_jobs()
- cluster.c: expand cluster_build_groups() stub with TODO comment
2026-05-07 08:31:29 +00:00
9da6bbb260 Merge branch 'merge_api_server' into persistent_ha 2026-05-07 04:41:14 +00:00
c772d7e601 Merge branch 'share_host_ctx' into merge_api_server 2026-05-07 04:38:01 +00:00
52d67726ec fix select eval ctx share 2026-05-07 04:37:18 +00:00
d6008ead99 improve frontend jobid display 2026-05-07 02:36:24 +00:00
3ed7ef011a fix go jobId schema bug 2026-05-03 11:45:14 +08:00
d7afd72e5b fix front end issues 2026-05-01 21:22:45 +08:00
177cf45af5 docs: mark Phase 6 complete in phase6-scheduler-integration-plan 2026-04-30 07:17:32 +00:00
9b0e9571d1 docs: mark Phase 6 complete in resreq-ast-cse-impl-plan 2026-04-30 07:06:36 +00:00
d438742f1a fix: staging_merge_complete bootstrap deadlock and missing recompact_node_ids
Two correctness fixes found during final Phase 6 code review:

F1 (CRITICAL): GC permanently disabled — staging_merge_complete bootstrapping deadlock.
sched_begin_session reset staging_merge_complete to 0 but never set it back to 1,
so sched_end_session's guard (!staging_merge_complete) always fired, preventing GC
from ever running. select-node memory leaked indefinitely across scheduling sessions.
Fix: set staging_merge_complete=1 at the end of sched_begin_session after all
staging work (sched_account_jobs etc.) completes.

F2 (HIGH): recompact_node_ids() omitted from GC protocol in sched_end_session.
The protocol in resreq.h requires gc_sweep → recompact_node_ids. Without
recompaction, sel_node_next_id grows monotonically across sessions and
select_eval_ctx_t arrays (sized by max node_id) grow without bound.
Fix: call recompact_node_ids() after gc_sweep_select_nodes.

Also adds test_staging_merge_complete_gc_guard to document the bootstrap
invariant: sched_begin_session must leave staging_merge_complete=1 so the
GC guard in sched_end_session does not fire.
2026-04-30 06:48:01 +00:00
5fcf85c494 test: scheduler integration tests for sched_meet_host_selection (6-11) 2026-04-30 06:23:28 +00:00
1eb4eb1335 fix: use _Atomic flag for sel_alloc_thread_id registration, move reg before loop, add wrong-thread guard test 2026-04-30 06:15:01 +00:00
b722e5cb3d feat: add sel_alloc_thread_id ownership check in eval_select and gc_sweep (6-10) 2026-04-30 06:04:21 +00:00
742d79ee55 fix: free live_jobs and null-sentinel on realloc failure in sched_end_session 2026-04-30 05:54:46 +00:00
fb5127ad66 fix: skip GC in sched_end_session when live_jobs allocation fails (OOM safety) 2026-04-30 05:49:49 +00:00
5267d36a84 feat: drive GC from sched_end_session — live_jobs mark, seq_cst fence, gc_sweep (6-8, 6-12) 2026-04-30 05:44:46 +00:00
8cff4ac889 fix: add bounds checks in eval_select_simple for null/empty host_eval_ctx; remove empty_ctx hack
- simple_num/simple_str: guard h->numvals/strvals NULL and idx out-of-range before array access
- eval_select_simple SEL_RESNAME: guard host->numvals NULL and idx bounds before deref
- eval_select_inner SEL_RESNAME (memoizing path): same NULL/bounds guards for numvals and strvals
- build_host_eval_ctx: return valid empty context (num_res=0, NULL arrays) instead of NULL when num_res<=0
- sched_meet_host_selection: remove empty_ctx stack hack; always call build_host_eval_ctx which now handles the zero-resource case cleanly
2026-04-30 05:20:37 +00:00
9ed38d4bad fix: address fifth-round adversarial review findings for persistence-and-ha-design
P1 fixes:
- A5-008: Change `in_catch_up` from plain `int` to `_Atomic int` with
  documented access patterns and memory ordering
- A5-002: Add missing opcodes to Part 5.10 capnp schema (heartbeat,
  steppingDown, replSnapshot, replCatchUpDone)
- A5-004: Add hook list synchronization spec for demotion (RCU-style
  removal with disabled flag and deferred memory reclamation)
- A5-005: Change xce_connect_cluster return type from int to SSL*,
  add xce_disconnect_cluster(SSL*), update xce_reconnect to SSL**
- A5-006: Add GC use-after-free mitigation section (per-operation READ
  lock hold for P0, epoch-based reclamation as P3)
- A5-010: Add OP_steppingDown handler spec to P1-2 milestone
- A5-001: Clarify P0-3 checkpoint timer vs dedicated pthread timers
- A5-003: Clarify WAL_CRC_NONE handling in replication CRC validation
- A5-013: Add repl_remove_standby slot cleanup requirement
- A5-012: Add primary_ep lifecycle documentation (iomgr-owned borrow,
  NULL-before-free under mutex)
- A5-014: Add async hook error handling convention
- A5-015: Add aggregate memory budget analysis for concurrent snapshots
- A5-016: Fix ha_check_heartbeat plain role read to use atomic_load_explicit
- A5-017: Fix Appendix A.4 in_catch_up type consistency (_Atomic int)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 05:17:56 +00:00
40261b7e96 feat: implement sched_meet_host_selection using eval_select_simple (6-5)
Replace the always-return-1 stub with a real implementation that:
- Returns 1 immediately when s == NULL or s->root == NULL (no constraint)
- Builds a host_eval_ctx_t from w->resvals and calls eval_select_simple
- Uses a zero-resource stack context when resvals.caps == 0 so constant
  sub-expressions (SEL_TRUE, SEL_FALSE, SEL_ANY) still evaluate correctly
- On OOM (build_host_eval_ctx returns NULL), conservatively passes the host
- Maps eval_select_simple result: >0 → 1 (match), <=0 → 0 (no-match)

Add #define UNIT_TEST 1 to test.c, remove redundant #ifdef guard, and
add three new TDD tests covering NULL select, SEL_TRUE, and SEL_FALSE.
All 6 tests pass.
2026-04-30 05:04:47 +00:00
2e3469c3c5 fix: correct zarray single-pointer convention in build_host_eval_ctx; add num_res guard 2026-04-30 04:58:28 +00:00
907d8d80a3 feat: implement build_host_eval_ctx — project resvals zarray to host_eval_ctx_t (6-7) 2026-04-30 04:49:27 +00:00
acda9bb228 feat: add sched GC predicate statics; wire sel_optimize_set(1) in sched_init (6-4, 6-9) 2026-04-30 04:13:14 +00:00
72546d3a22 fix: restore libxce_deps in scheduler test deps (removed by mistake in task 3) 2026-04-30 04:08:14 +00:00
823a66e91e feat: add _Atomic gc-predicate fields to xce_scheduler_t (phase 6 task 6-3) 2026-04-30 04:03:51 +00:00
4e177047c9 fix: correct SEL_NUM bit-cast in gc test; assert n1 swept; add recompact to protocol comment 2026-04-30 03:55:15 +00:00
9a19a8f932 feat: export gc_clear_marks + gc_mark_select_tree; remove clear from gc_sweep (phase 6)
- Add gc_clear_marks(): iterates intern table and zeroes all gc_mark bits
- Rename static gc_mark_tree → public gc_mark_select_tree (no attribute((unused)))
- Remove Phase 6 guard (live_jobs != NULL early return) from gc_sweep_select_nodes
- Remove the mark-clear loop from gc_sweep_select_nodes; add (void) casts for now-unused params
- Declare gc_clear_marks and gc_mark_select_tree in resreq.h with protocol comment
- Add TDD test test_gc_clear_marks_exported verifying the exported primitives
- Prefix all existing gc_sweep_select_nodes(NULL, 0) call sites in test_select.c with gc_clear_marks()
2026-04-30 03:40:24 +00:00
bb4a95ce37 chore: phase 6 pre-audit — allocator single-threaded confirmed, stub at resource.c:127 2026-04-30 03:28:41 +00:00
c623e37b84 fix: address fourth-round adversarial review findings for persistence-and-ha-design
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 14:01:26 +00:00
454b4aa355 fix: address third-round adversarial review findings for persistence-and-ha-design
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 13:36:43 +00:00
f1641b1fbf docs: fix 9 P0 and 6 P1 issues from second adversarial review
P0 fixes (9):
- R-22: COW vstore find-slot-and-write not atomic
- R-23: vput grow path without mutex during COW
- R-24: Post-growth slot double-claimed by concurrent threads
- R-25: Missing key_snapshot field for checkpoint serialization
- R-26: malloc(0) for WAL_CHECKPOINT entries
- R-27: Fallback to older snapshot with trimmed WAL
- R-28: hdr.term > ha->term + 1 too restrictive
- R-29: _Atomic on enum type (implementation-defined)
- R-30: handle_jobsubmit() ignores hook return value
- R-31: malloc NULL check missing in standby receiver

P1 fixes (5):
- R-32: No heartbeat during persist_recover() on new primary
- R-33: Catch-up from dead primary removed from promotion
- R-34: Added total_wal_bytes field to persist_t

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 12:55:47 +00:00
54bbfa5865 docs: fix 6 additional P0/P1 review findings for persistence-and-ha-design
P0 fixes (3):
- R-16: vstore COW growth re-check used OOB a->data[old_caps].inuse
- R-17: Standby WAL write return value unchecked before sending ACK
- R-18: Chained CRC validation absent from replication stream

P1 fixes (3):
- R-19: Replicated entry LSN handling unspecified
- R-20: seg_offset in-memory and lost on crash
- R-21: WAL segment rotation prev_crc handling at recovery

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 12:28:39 +00:00
bb66b9766d docs: fix remaining P0/P1 review findings for persistence-and-ha-design
- P0: Fix concurrent vstore race under READ lock during COW mode
  (add xzarray mutex serialization around grow-and-assign section)
- P0: Array job sync replication latency bound (batch mode for
  array submits to avoid O(array_size × sync_timeout_ms) blocking)
- P1: rtti library ABI break documented with two-repo dependency note
2026-04-29 12:02:53 +00:00