feat(ha-commit-durability): demand-driven group-commit flusher + durable_lsn watermark (task 2.1)

This commit is contained in:
Rongsong Shen 2026-06-18 06:06:55 +00:00
parent 7e6f09f804
commit cc83caf5a0
4 changed files with 567 additions and 27 deletions

View file

@ -87,6 +87,13 @@ struct persist_s {
uint32_t seg_offset;
uint64_t checkpoint_lsn;
_Atomic uint64_t committed_lsn; /* highest LSN known committed; invariant: <= current_lsn - 1 */
_Atomic uint64_t durable_lsn; /* highest LSN whose bytes are fdatasync'd locally (group-commit
* prefix watermark). Advanced ONLY by the flusher after a
* successful fdatasync. Invariants: monotonic non-decreasing
* (except clamp-on-truncate); durable_lsn <= current_lsn - 1.
* The commit majority counts self at this LSN, not the
* appended tip (ha-commit-durability Req 1.1/1.2; consumed by
* task 2.2). */
uint64_t total_wal_bytes;
char seg_path[4096];
@ -103,6 +110,14 @@ struct persist_s {
atomic_int checkpoint_in_progress; /* CAS guard: 0=idle, 1=scheduled/running */
atomic_int fsync_stop;
atomic_int fsync_thread_running;
#ifdef XCE_TESTING
/* Fault-injection seam (ha-commit-durability task 2.1 error-path test):
* when non-zero, every fdatasync site treats the sync as FAILED — it
* still calls the real fdatasync but forces a non-zero rc, so durable_lsn
* must NOT advance and the failure is logged loudly. Compiled out of
* production (xce_controller is built without -DXCE_TESTING). */
atomic_int test_force_fsync_fail;
#endif
pthread_t fsync_thread;
pthread_mutex_t fsync_mutex; /* guards the fsync timer wait */
pthread_cond_t fsync_cond; /* signaled by persist_stop for prompt join */
@ -184,6 +199,13 @@ int persist_commit_barrier(persist_t* p, uint32_t timeout_ms);
/* Force WAL fdatasync (for tests and clean shutdown) */
int persist_flush(persist_t* p);
/* Highest LSN whose bytes are durably fdatasync'd locally — the
* group-commit prefix watermark advanced by the demand-driven flusher
* (ha-commit-durability task 2.1). The commit majority self-contribution
* caps at this value (task 2.2 consumer). Lock-free atomic read; safe from
* any thread. Returns 0 when nothing is yet durable. */
uint64_t persist_durable_lsn(persist_t* p);
#ifdef XCE_TESTING
/* ============================================================
* Durability-verification test seam (ha-commit-durability Req 3.2, 3.3)
@ -211,6 +233,15 @@ int persist_flush(persist_t* p);
* without this symbol.
* ============================================================ */
uint64_t persist_test_durable_lsn_on_disk(persist_t* p);
/* Fault-injection toggle for the fdatasync error path (task 2.1).
* When `fail` is non-zero, every fdatasync site in persist.c forces a
* failed sync result: the real fdatasync still runs, but durable_lsn is
* left UNCHANGED and the failure is logged loudly — proving an acknowledged
* entry is never counted durable on a sync error (Req 1.1/1.2, fail-loud).
* Lock-free atomic write; safe to flip from a test thread at any time.
* Compiled out of production (xce_controller links without it). */
void persist_test_set_force_fsync_fail(persist_t* p, int fail);
#endif /* XCE_TESTING */
/* Checkpoint */