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

@ -2,6 +2,8 @@
#define _CLIENT_H_ 1
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "netio.h"
@ -11,6 +13,18 @@
typedef void* xcecli_ctx_t;
/*
* xcecli_reconnect_cb: consumer rejoin hook invoked once per transparent
* reconnect/failover, AFTER the reconnect/recovery and BEFORE the interrupted
* op resumes. The callback CONTENT (join handshake, worker job re-sync) belongs
* to the consumer; libxce owns only the mechanism + ordering. Runs on the
* calling thread. Return 0 to proceed with the interrupted op; <0 to treat the
* rejoin as failed (the new primary rejected the join) so the failover loop
* rotates/backs off again instead of resuming. Pure clients register NO hook
* (NULL) — the loop then resumes directly.
*/
typedef int (*xcecli_reconnect_cb)(xcecli_ctx_t ctx, void* arg);
#define N_MAX_MASTERS (3)
typedef struct {
@ -26,6 +40,8 @@ typedef struct {
extern int xcecli_ctx_init(xcecli_ctx_t*, xce_client_config_t*);
extern void xcecli_ctx_fini(xcecli_ctx_t);
extern int xcecli_set_handler(xcecli_ctx_t, xce_request_handler_t, void*);
extern int xcecli_set_reconnect_handler(xcecli_ctx_t, xcecli_reconnect_cb,
void*);
extern int xcecli_start(xcecli_ctx_t);
extern int xcecli_stop(xcecli_ctx_t);
extern int xcecli_wakeup(xcecli_ctx_t, int);
@ -39,6 +55,30 @@ extern int xcecli_workerlist(xcecli_ctx_t, xce_worker_t***);
extern int xcecli_jobdispatch(xcecli_ctx_t, xce_job_dispatch_t*);
extern int xcecli_joblist(xcecli_ctx_t, xce_job_t***);
extern int xcecli_clusterconf(xcecli_ctx_t, xce_clusterconf_t**);
extern int xcecli_ctrlstatus(xcecli_ctx_t, xce_ctrlstatus_t**);
/*
* xcecli_ctrlstatus_primary (controller-status task 3.2): AUTHORITATIVE
* controller status read. Returns ONLY a reply whose responder role is the
* primary. When the first answer is from a non-primary, it follows the redirect
* (targets the reported primary via the reply's peer list, else rotates the
* configured controller list) until the primary answers or the failover budget
* is exhausted. On budget exhaustion / no reachable primary it returns a typed
* negative and NEVER hands back a non-primary hint reply (Req 9.1, 9.2). The
* any-node hint view is still available via xcecli_ctrlstatus above.
*/
extern int xcecli_ctrlstatus_primary(xcecli_ctx_t, xce_ctrlstatus_t**);
/*
* Pure decision helpers backing the authoritative read (no I/O — unit-testable
* and exposed for tests). xcecli_ctrlstatus_is_authoritative returns true iff
* the reply's responderRole is the primary role (ctrl_role_t PRIMARY == 0).
* xcecli_ctrlstatus_primary_addr maps the reply's primaryName to its host:port
* via the reply's peers list: returns 0 and fills host/port on a hit, -ENOENT
* when the primary is unknown/absent from peers, -EINVAL on a bad argument.
*/
extern bool xcecli_ctrlstatus_is_authoritative(const xce_ctrlstatus_t*);
extern int xcecli_ctrlstatus_primary_addr(const xce_ctrlstatus_t*,
char* host_out, size_t host_sz,
uint16_t* port_out);
extern int xcecli_notify_jobfinish(xcecli_ctx_t, xce_jobfinish_t*);
extern int xcecli_notify_jobstart(xcecli_ctx_t, job_pidinfo_t*);
extern int xcecli_notify_jobfail(xcecli_ctx_t c, job_failinfo_t*);
@ -74,6 +114,10 @@ extern int xcecli_jobinfo(xcecli_ctx_t, uint64_t, xce_job_t**);
#define xcecli_free_queues(nqueues, queues) xce_free_queues(nqueues, queues)
#define xcecli_free_groups(ngroups, groups) xce_free_groups(ngroups, groups)
#define xcecli_free_clusterconf(conf) xce_free_clusterconf(conf)
/* ctrlstatus reply is freed by the generated codec free (free_CtrlStatus,
* declared in the generated controller.capnp.h). */
#define xce_free_ctrlstatus(s) free_CtrlStatus(s)
#define xcecli_free_ctrlstatus(s) xce_free_ctrlstatus(s)
extern int xcecli_reply_fetchfile(xcecli_ctx_t, xce_request_t*, xce_fetchfile_reply_t*);
extern int xcecli_fetchfile(xcecli_ctx_t, xce_fetchfile_t*, xce_fetchfile_reply_t**);