Merge branch 'working' into job_peek_lchen

job_peek_lchen: Add fetchfile feature (job output/error peek proxy)
working: HA/Raft infrastructure (consensus, replication, config mgmt)

Conflict resolution summary:
- controller.capnp: fetchfile @41, fetchfilereply @18, fetchfilemsg @30
- cluster.c: bifurcated OPCode_reply for fetchfile + config-push ACK
- job.c: kept full fetchfile pending-request subsystem (~183 lines)
- request.c: kept both xce_fetchfile_req() and XCE_RETRY_DEFAULTS
- helper.c: added missing preVoteRequest/preVoteReply mappings
- All 15 new test registrations (test_cbuf.c + 14 HA tests)
This commit is contained in:
Lei Chen 2026-07-22 13:57:25 +08:00
commit 3a2094a461
529 changed files with 345174 additions and 5048 deletions

View file

@ -4,6 +4,7 @@
#include "config.h"
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include "hook.h"
@ -22,6 +23,10 @@
typedef int (*collect_check_fn_t)(void*);
extern int check_controller(void*);
extern int cluster_init_phase1(cluster_t*);
extern int cluster_open_listener(cluster_t*);
extern int cluster_register_listener(cluster_t*);
extern int cluster_init_phase2(cluster_t*);
extern int cluster_init(cluster_t*);
extern int cluster_start(cluster_t*);
extern int cluster_run(cluster_t*);
@ -39,6 +44,7 @@ extern int add_resource(void*, char*, char*, int, xce_order_t, int, int);
extern int update_resvals(cluster_t*, worker_t*, int, xce_resval_t*);
extern int load_jobs(void*);
extern int restore_job(cluster_t*, uint64_t, const void*, size_t, uint64_t);
extern int update_job(void*, uint64_t, xce_kv_list_t*);
extern int do_job_started(void*, uint64_t, int, int*, int, int*);
@ -73,11 +79,32 @@ extern int mark_worker_back(cluster_t*, worker_t*);
extern int handle_scheduler_leave(cluster_t*);
extern int handle_clusterconf(cluster_t*, endpoint_t*, xce_request_t*);
/* controller-status spec (task 2.1): read-only status query.
* ctrlstatus_fill snapshots local HA/config state into *st (no I/O, no state
* mutation); ctrlstatus_free_fields releases what fill allocated (the peer
* pointer array). handle_ctrlstatus is the dispatch entry point that fills,
* replies via xce_reply, then frees. */
extern void ctrlstatus_fill(cluster_t*, xce_ctrlstatus_t*);
extern void ctrlstatus_free_fields(xce_ctrlstatus_t*);
extern int handle_ctrlstatus(cluster_t*, endpoint_t*, xce_request_t*);
extern void collect_confvars(cluster_t*, collect_check_fn_t, xlist_t*);
extern void collect_queues(cluster_t*, collect_check_fn_t, xlist_t*);
extern void collect_resources(cluster_t*, collect_check_fn_t, xlist_t*);
extern void collect_jobs(cluster_t*, collect_check_fn_t, xlist_t*);
extern void collect_workers(cluster_t*, collect_check_fn_t, xlist_t*);
/* ha-convergence-recovery (3.1-3.3): commit-watermark egress gate for
* scheduler-bound job exports. Defined in dataex.c.
* job_submit_committed — true iff the job's submit entry is committed
* (submit_lsn == 0 || submit_lsn <= committed_lsn);
* one lock-free atomic load + compare.
* collect_jobs_committed — identical contract to collect_jobs, additionally
* excluding jobs whose submit entry is uncommitted.
* For scheduler-bound callers ONLY; status/API read
* paths keep plain collect_jobs (Req 3.4). */
extern bool job_submit_committed(cluster_t*, job_t*);
extern void collect_jobs_committed(cluster_t*, collect_check_fn_t, xlist_t*);
extern int get_queue_exec(cluster_t*, char*, char**, char**);
extern void unlock_collect_queues(xlist_t*);
extern void unlock_collect_jobs(xlist_t*);
@ -117,7 +144,7 @@ extern int on_task_finish(cluster_t*, xce_task_finish_t*);
extern int xce_controller_res_init(cluster_t*);
extern int map_resource_to_host(char*, cluster_t*);
extern int release_resource_from_worker(char*, cluster_t*);
extern int collect_resval_with_idx(zarray_t*, xlist_t*);
extern int collect_resval(var, zarray_t*, xlist_t*);
extern int do_set_preason(cluster_t*, endpoint_t*, xce_request_t*);
extern int do_clr_preason(cluster_t*, endpoint_t*, xce_request_t*);
extern int on_fetchfile(cluster_t*, endpoint_t*, xce_request_t*);

View file

@ -0,0 +1,79 @@
#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 */
/* ha-term-safety commit-ceiling-optA: the raft library's commit_index,
* recorded for OBSERVABILITY / TRACE / conformance-oracle ONLY. It does NOT
* gate commit-advance: majority_candidate_locked no longer folds it into the
* commit candidate. Commit-advance is authoritative via the durable-majority
* barrier + the own-term writable_lsn gate. Kept (and still fed by
* on_commit_advanced) so the library half keeps a sink and tooling can
* compare the library current-term commit point vs committed_lsn. Monotonic
* non-decreasing, set under ce->lock via commit_set_raft_commit_index. */
uint64_t raft_commit_index;
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);
/* ha-term-safety commit-ceiling-optA: record the raft library's commit_index
* for OBSERVABILITY / TRACE / conformance-oracle ONLY (monotonic max() — never
* regresses). This does NOT gate commit-advance: the durable-majority barrier +
* own-term writable gate are authoritative. Still fed by on_commit_advanced so
* the library half keeps a sink. Re-evaluates the (commit_index-independent)
* durable majority and wakes waiters as a convenient ACK-path wake point. Never
* blocks. */
void commit_set_raft_commit_index(commit_engine_t* ce, uint64_t commit_index);
/* 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);

View file

@ -7,6 +7,11 @@
#include "xce/types.h"
#include "zarray.h"
extern int add_worker(void*, endpoint_t*, const char*, hostattrs_t*);
extern int restore_worker(void*, xce_worker_t);
extern xce_hostconfig_t* find_matched_hostconfig(cluster_t*, const char*);
extern int init_worker(cluster_t*, endpoint_t*, const char*,
hostattrs_t*, xce_hostconfig_t*);
extern int rejoin_worker(cluster_t*, worker_t*, endpoint_t*,
hostattrs_t*, xce_hostconfig_t*);
extern int restore_worker(void*, xce_worker_t);
extern int worker_from_capnp(cluster_t*, const void*, size_t);
#endif