forked from lei.chen/myxce
test(ha-commit-engine): RED tests for per-LSN majority evaluation (task 1.1)
commit.h umbrella-verbatim interface + inert stub commit.c (test target only); 7 Unity tests covering per-LSN vs acked_lsn>0 counting, majority median, monotonicity, append clamp, lagging standby, RETAIN immediacy. All 7 fail RED as intended. Documented 3 pre-existing masked suite failures (bug-411) and the per-group exit-code masking root cause.
This commit is contained in:
parent
06135954ff
commit
d5a0f9c64d
10 changed files with 757 additions and 283 deletions
61
src/controller/include/commit.h
Normal file
61
src/controller/include/commit.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
/*
|
||||
* commit.h — Commit engine: single authority for per-entry commit evaluation,
|
||||
* committed_lsn advancement, and waiter completion.
|
||||
*
|
||||
* Service interface is umbrella-verbatim from
|
||||
* .kiro/specs/ha-consistency-invariants/design.md (sliced by ha-commit-engine).
|
||||
*
|
||||
* All functions thread-safe; commit_on_ack callable from iomgr (non-blocking).
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "persist.h" /* persist_t (owns committed_lsn atomic + replicator_t registry) */
|
||||
|
||||
/* Headroom kept free of blocking commit waits; cap = max(1, n_vcpus - reserved) */
|
||||
#define COMMIT_WAIT_RESERVED 2
|
||||
|
||||
typedef enum { COMMIT_MODE_WAIT, COMMIT_MODE_RETAIN } commit_mode_t;
|
||||
|
||||
/*
|
||||
* Commit engine state — in-memory only (commit state volatile, Raft-conformant).
|
||||
* Per-standby view delegated to standby_conn_t.acked_lsn / in_catch_up via
|
||||
* p->repl (no duplication).
|
||||
*/
|
||||
typedef struct commit_engine {
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond; /* broadcast on committed_lsn advance / membership change */
|
||||
persist_t* p; /* back-reference: committed_lsn store + repl registry */
|
||||
int n_peers;
|
||||
int n_vcpus;
|
||||
int inflight_waits; /* <= max(1, n_vcpus - COMMIT_WAIT_RESERVED) */
|
||||
uint64_t writable_lsn; /* own-term gate; 0 = no gate */
|
||||
uint64_t scratch[MAX_STANDBYS]; /* sorted matchIndex scratch array */
|
||||
} commit_engine_t;
|
||||
|
||||
/* Lifecycle. init validates n_peers >= 0, n_vcpus >= 1, non-NULL persist_t;
|
||||
* returns -EINVAL otherwise. Call after n_peers and n_vcpus are final. */
|
||||
int commit_engine_init(commit_engine_t* ce, persist_t* p, int n_peers, int n_vcpus);
|
||||
void commit_engine_fini(commit_engine_t* ce);
|
||||
|
||||
/* Register entry at append time. RETAIN returns 0 immediately.
|
||||
* WAIT blocks up to timeout_ms: 0 = committed; -ETIMEDOUT = not committed
|
||||
* (entry remains in log; outcome resolves per umbrella 2.5); -XCE_ERR_NOT_READY =
|
||||
* admission cap exhausted (only cause). An unmet own-term gate does NOT fail
|
||||
* fast: the gate is part of the completion predicate, so WAIT blocks within
|
||||
* timeout_ms until the gate opens, surfacing -ETIMEDOUT if it never does. */
|
||||
int commit_submit(commit_engine_t* ce, uint64_t lsn, commit_mode_t mode,
|
||||
uint32_t timeout_ms);
|
||||
|
||||
/* iomgr path: record standby ACK, evaluate majority, advance committed_lsn
|
||||
* contiguously, wake satisfied waiters. Never blocks. */
|
||||
void commit_on_ack(commit_engine_t* ce, int standby_idx, uint64_t acked_lsn);
|
||||
|
||||
/* Promotion: set own-term gate to the no-op entry's LSN.
|
||||
* (API ships here; no caller in this spec — unset = no gate.) */
|
||||
void commit_set_writable_lsn(commit_engine_t* ce, uint64_t noop_lsn);
|
||||
|
||||
/* Quorum-membership change (standby add/remove/catch-up transition):
|
||||
* re-evaluate pending entries; standbys in catch-up are excluded. */
|
||||
void commit_on_membership_change(commit_engine_t* ce);
|
||||
Loading…
Add table
Add a link
Reference in a new issue