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:
commit
3a2094a461
529 changed files with 345174 additions and 5048 deletions
|
|
@ -6,6 +6,20 @@
|
|||
#include "clusterconfig.h"
|
||||
#include "xce/types.h"
|
||||
|
||||
/* Forward declarations for config-replication types used in
|
||||
* xce_reply_t and xce_request_t unions below. */
|
||||
typedef struct repl_config_reply_s repl_config_reply_t;
|
||||
typedef struct repl_config_push_reply_s repl_config_push_reply_t;
|
||||
typedef struct upgrade_config_reply_s upgrade_config_reply_t;
|
||||
typedef struct repl_config_req_s repl_config_req_t;
|
||||
typedef struct repl_config_push_req_s repl_config_push_req_t;
|
||||
typedef struct upgrade_config_req_s upgrade_config_req_t;
|
||||
typedef struct heartbeat_msg_s heartbeat_msg_t;
|
||||
typedef struct ctrl_hello_req_s ctrl_hello_req_t;
|
||||
typedef struct ctrl_hello_reply_s ctrl_hello_reply_t;
|
||||
typedef struct wal_catchup_entry wal_catchup_entry_t;
|
||||
typedef struct snapshot_transfer_s snapshot_transfer_t;
|
||||
|
||||
typedef struct {
|
||||
char* resname;
|
||||
char* hostname;
|
||||
|
|
@ -46,8 +60,8 @@ typedef struct {
|
|||
xce_group_config_t** ugroups;
|
||||
int n_hgroups;
|
||||
xce_group_config_t** hgroups;
|
||||
int nresvals;
|
||||
xce_val_with_idx_t** resvals;
|
||||
int nresvals;
|
||||
xce_name_val_t** resvals;
|
||||
int nlimits;
|
||||
xce_limit_config_t** limits;
|
||||
int nhproviders;
|
||||
|
|
@ -160,18 +174,93 @@ typedef struct {
|
|||
} data;
|
||||
} xce_update_data_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
char *candidate_id;
|
||||
uint64_t config_tag;
|
||||
uint64_t last_log_lsn;
|
||||
/* Raft (lastLogTerm, lastLogIndex) freshness tuple (ha-term-safety task 1.2):
|
||||
* feeds the library logOk gate, distinct from config_tag/last_log_lsn which
|
||||
* drive the application freshness gate. last_log_index == candidate log_len. */
|
||||
uint64_t last_log_term;
|
||||
uint64_t last_log_index;
|
||||
} request_vote_req_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
int vote_granted;
|
||||
uint64_t peer_config_tag;
|
||||
uint64_t peer_last_log_lsn;
|
||||
} request_vote_reply_t;
|
||||
|
||||
/* Heartbeat reply state report — carries standby's applied_lsn and config_tag */
|
||||
typedef struct {
|
||||
uint64_t applied_lsn;
|
||||
uint64_t config_tag;
|
||||
} state_report_t;
|
||||
|
||||
/* WAL apply ACK — sent by standby to primary after applying a WAL catch-up
|
||||
* entry (Task 3.1, ha-wal-replication). Must be declared before xce_reply_t
|
||||
* so the walackreplymsg union arm compiles correctly. */
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
uint64_t lsn;
|
||||
int success;
|
||||
} wal_ack_reply_t;
|
||||
|
||||
/* ctrlstatus reply payload (controller-status spec): one configured
|
||||
* controller (CtrlPeer) and the lean identity/health snapshot (CtrlStatus).
|
||||
* The peers list maps via $C.mapname("peers.list")/$C.maplistcount("peers.count")
|
||||
* to the nested { count, list } member below. */
|
||||
typedef struct {
|
||||
char* name;
|
||||
char* host;
|
||||
uint32_t port;
|
||||
} xce_ctrlpeer_t;
|
||||
|
||||
typedef struct {
|
||||
char* clusterName;
|
||||
char* primaryName;
|
||||
char* responderName;
|
||||
uint8_t responderRole;
|
||||
uint64_t term;
|
||||
uint64_t configVersion;
|
||||
char* configChecksum;
|
||||
uint64_t committedConfigVersion;
|
||||
uint64_t committedLsn;
|
||||
uint64_t appliedLsn;
|
||||
unsigned fenced;
|
||||
struct {
|
||||
int count;
|
||||
xce_ctrlpeer_t** list;
|
||||
} peers;
|
||||
uint32_t peerCount;
|
||||
uint64_t responder_time_ms; /* @13: responder wall-clock at sample time (epoch ms) */
|
||||
} xce_ctrlstatus_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t seq;
|
||||
uint32_t opcode;
|
||||
int32_t status;
|
||||
int data_which;
|
||||
union {
|
||||
char* debugmsg;
|
||||
uint64_t jobid;
|
||||
xce_data_t* getdata;
|
||||
xce_clusterconf_t* clusterconf;
|
||||
xce_fetchfile_reply_t* fetchfilereply;
|
||||
char* debugmsg;
|
||||
uint64_t jobid;
|
||||
xce_data_t* getdata;
|
||||
xce_clusterconf_t* clusterconf;
|
||||
repl_config_reply_t* replconfigreplymsg;
|
||||
repl_config_push_reply_t* replconfigpushreplymsg;
|
||||
upgrade_config_reply_t* upgradeconfigreplymsg;
|
||||
ctrl_hello_reply_t* ctrlhelloreplymsg;
|
||||
request_vote_reply_t* requestvotereplymsg;
|
||||
state_report_t* state_report;
|
||||
wal_ack_reply_t* walackreplymsg;
|
||||
xce_ctrlstatus_t* ctrlstatus;
|
||||
xce_fetchfile_reply_t* fetchfilereply;
|
||||
} data;
|
||||
/* Req 7: standby redirect fields — populated when status == XCE_ERR_STANDBY */
|
||||
char *redirect_host;
|
||||
uint16_t redirect_port;
|
||||
} xce_reply_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -195,11 +284,209 @@ typedef struct {
|
|||
xce_jobctrl_t* jobctrlmsg;
|
||||
xce_queuectrl_t* queuectrlmsg;
|
||||
xce_taskrun_t* runtaskmsg;
|
||||
xce_preason_set_t* preasonmsg;
|
||||
xce_clear_reason_t* clrpreasonmsg;
|
||||
xce_hostctrl_t* hostctrlmsg;
|
||||
xce_fetchfile_t* fetchfilemsg;
|
||||
xce_preason_set_t* preasonmsg;
|
||||
xce_clear_reason_t* clrpreasonmsg;
|
||||
xce_hostctrl_t* hostctrlmsg;
|
||||
repl_config_req_t* replconfigrequestmsg;
|
||||
repl_config_push_req_t* replconfigpushrequestmsg;
|
||||
upgrade_config_req_t* upgradeconfigrequestmsg;
|
||||
heartbeat_msg_t* heartbeatmsg;
|
||||
ctrl_hello_req_t* ctrlhellomsg;
|
||||
request_vote_req_t* requestvotemsg;
|
||||
wal_catchup_entry_t* walcatchupentrymsg;
|
||||
snapshot_transfer_t* snapshottransfermsg;
|
||||
xce_fetchfile_t* fetchfilemsg;
|
||||
} body;
|
||||
} xce_request_t;
|
||||
|
||||
/* ── HA election and replication Cap'n Proto mapped types ────────────────
|
||||
* C-side counterparts for the HA protocol capnp structs added in the
|
||||
* ha-config-bootstrap spec (controller.capnp structs with $C.mapname).
|
||||
* Must be declared here so controller.capnp.h can reference them.
|
||||
* request_vote_req_t and request_vote_reply_t are defined above
|
||||
* xce_reply_t so they can be used in the xce_request_t body union. */
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
} probe_config_tag_req_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t config_tag;
|
||||
} probe_config_tag_reply_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
uint64_t lsn;
|
||||
} wal_ack_req_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
uint64_t acked_tag;
|
||||
int success;
|
||||
} upgrade_config_ack_t;
|
||||
|
||||
struct snapshot_transfer_s {
|
||||
uint64_t snapshot_lsn; /* checkpoint LSN this snapshot corresponds to */
|
||||
xce_data_t *payload; /* legacy decoded field — broken for raw bytes
|
||||
* (decode_Data_ptr misinterprets List(UInt8));
|
||||
* kept NULL on send, do not use */
|
||||
uint32_t chunk_index; /* 0-based chunk number */
|
||||
uint64_t chunk_offset; /* byte offset in the full snapshot */
|
||||
uint64_t total_size; /* total snapshot size in bytes */
|
||||
int is_last; /* true (non-zero) for the final chunk */
|
||||
/* Raw chunk bytes — same pattern as repl_config_push_req_t.
|
||||
* Send side: filled by the sender, encoded by xce_snapshot_chunk_req_raw.
|
||||
* Receive side: extracted by xce_decode() before capn_free(); malloc'd,
|
||||
* owned by the struct, freed by xce_free_request(). */
|
||||
uint8_t *raw_payload;
|
||||
size_t raw_payload_len;
|
||||
};
|
||||
|
||||
struct wal_catchup_entry {
|
||||
uint64_t lsn;
|
||||
uint8_t entry_type;
|
||||
xce_data_t *payload; /* legacy decoded field — broken for
|
||||
* raw bytes; kept NULL, do not use */
|
||||
int n_entries; /* batch: number of sub-entries */
|
||||
struct wal_catchup_entry **entries; /* batch: array of sub-entry pointers */
|
||||
/* Raw WAL entry payload bytes — same pattern as repl_config_push_req_t.
|
||||
* Send side: filled from the WAL segment file, encoded per sub-entry by
|
||||
* xce_wal_batch_req_raw. Receive side: extracted by xce_decode() before
|
||||
* capn_free(); malloc'd, owned, freed by xce_free_request(). */
|
||||
uint8_t *raw_payload;
|
||||
size_t raw_payload_len;
|
||||
/* Raft AppendEntries term fields (ha-term-safety task 1.1, Req 1.3/1.4).
|
||||
* term == this entry's term stamp; prev_log_index == lsn-1; prev_log_term ==
|
||||
* term of the entry at prev_log_index (0 if absent). Consumed by the log
|
||||
* callbacks (tasks 2.x) for the AppendEntries logOk / truncation decision. */
|
||||
uint64_t term;
|
||||
uint64_t prev_log_index;
|
||||
uint64_t prev_log_term;
|
||||
/* ha-term-safety task 3.2 (Req 2.5/4.1): the leader's commit index carried on
|
||||
* the AppendEntries so the standby intake passes it into
|
||||
* raft_on_append_entries_request. Wire field leaderCommit @7. */
|
||||
uint64_t leader_commit;
|
||||
/* bug-1067: the streaming leader's CURRENT term — the Raft AppendEntries
|
||||
* HEADER term, DISTINCT from `term` above (the entry's STORED term). Equal for
|
||||
* a live append; for a HISTORICAL catch-up entry the stored term is lower than
|
||||
* the leader's current term. The standby intake uses this as the AE header
|
||||
* term (UpdateTerm/stale-check) so cross-term catch-up is not stale-rejected;
|
||||
* 0 = unset (legacy sender) → fall back to the stored term. Wire field
|
||||
* leaderCurrentTerm @8. */
|
||||
uint64_t leader_current_term;
|
||||
};
|
||||
|
||||
/* ── Persistence Cap'n Proto mapped types (P0-9) ─────────────────────
|
||||
* These are the C-side counterparts for the capnp encode/decode shims.
|
||||
* Named with capnp_ prefix to avoid collision with the plain-C structs
|
||||
* in persist.h (persist_config_t) and the on-disk binary formats. */
|
||||
typedef struct {
|
||||
uint32_t walSyncMs;
|
||||
uint32_t snapIntervalS;
|
||||
uint32_t snapWalSizeMb;
|
||||
uint32_t finishedRetainS;
|
||||
uint32_t workerRetainS;
|
||||
uint32_t syncTimeoutMs;
|
||||
uint32_t snapKeepN;
|
||||
uint32_t transientJobTimeoutS;
|
||||
} capnp_persist_cfg_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t lsn;
|
||||
uint64_t term;
|
||||
uint64_t timestamp;
|
||||
uint32_t version;
|
||||
uint32_t nJobs;
|
||||
uint32_t nQueues;
|
||||
uint32_t nWorkers;
|
||||
uint32_t checksum;
|
||||
uint32_t headerChecksum;
|
||||
} capnp_snap_hdr_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t term;
|
||||
uint64_t lsn;
|
||||
uint32_t entryType;
|
||||
xce_data_t* payload; /* owned; decoded via decode_Data_ptr */
|
||||
uint32_t crc;
|
||||
uint32_t prevCrc;
|
||||
} capnp_repl_envelope_t;
|
||||
|
||||
/* ── Config replication Cap'n Proto mapped types (Phase 1) ──────────────
|
||||
* C-side counterparts for the capnp encode/decode shims for config sync.
|
||||
* Struct tags match the forward declarations near the top of this file. */
|
||||
|
||||
struct repl_config_req_s {
|
||||
uint64_t version_tag; /* local config version tag */
|
||||
};
|
||||
|
||||
struct repl_config_reply_s {
|
||||
int up_to_date; /* 1 if standby is current */
|
||||
uint64_t version_tag; /* primary's current version tag */
|
||||
xce_data_t *sha256; /* 32-byte SHA-256 of config blob (may be NULL) */
|
||||
xce_data_t *bytes; /* serialised ClusterConfig blob (may be NULL) */
|
||||
};
|
||||
|
||||
struct repl_config_push_req_s {
|
||||
uint64_t version_tag; /* version tag of the pushed config */
|
||||
xce_data_t *sha256; /* 32-byte SHA-256 (decoded, not usable as raw bytes) */
|
||||
xce_data_t *bytes; /* serialised ClusterConfig blob (decoded, not usable) */
|
||||
/* Pre-extracted raw fields populated by xce_decode() before capn_free(),
|
||||
* mirroring the same pattern as upgrade_config_req_t. Owned by the struct. */
|
||||
uint8_t *raw_sha256; /* 32-byte SHA-256, malloc'd, or NULL */
|
||||
uint8_t *raw_bytes; /* serialised ClusterConfig blob, malloc'd, or NULL */
|
||||
size_t raw_bytes_len; /* length of raw_bytes */
|
||||
};
|
||||
|
||||
struct repl_config_push_reply_s {
|
||||
int accepted; /* 1 if standby accepted the push */
|
||||
uint64_t version_tag; /* standby's current version tag after decision */
|
||||
};
|
||||
|
||||
struct upgrade_config_req_s {
|
||||
/* Legacy decoded fields — populated by generated decode_UpgradeConfigRequest()
|
||||
* via decode_Data_ptr. These are structurally broken for List(UInt8) wire
|
||||
* fields (decode_Data_ptr reads a discriminant and misinterprets the bytes),
|
||||
* but must remain for the generated code to compile. Do NOT use these for
|
||||
* actual byte extraction. */
|
||||
xce_data_t *sha256; /* broken: always a bogus xce_jobs_data_t */
|
||||
xce_data_t *bytes; /* broken: always a bogus xce_jobs_data_t */
|
||||
|
||||
/* Correct raw bytes extracted by xce_decode() before capn_free() runs,
|
||||
* using UpgradeConfigRequest_get_sha256/bytes + capn_getv8.
|
||||
* Both are malloc'd and owned here; freed by free_upgrade_config_req_raw()
|
||||
* called from free_Request() after free_UpgradeConfigRequest().
|
||||
* raw_sha256 is exactly 32 bytes when non-NULL. */
|
||||
uint8_t *raw_sha256; /* 32-byte SHA-256, malloc'd, or NULL */
|
||||
uint8_t *raw_bytes; /* serialised ClusterConfig blob, malloc'd, or NULL */
|
||||
size_t raw_bytes_len; /* length of raw_bytes */
|
||||
};
|
||||
|
||||
struct upgrade_config_reply_s {
|
||||
uint64_t version_tag; /* new version tag after upgrade */
|
||||
char *error; /* NULL on success; error message on failure */
|
||||
uint32_t acked_count; /* number of standbys that acknowledged */
|
||||
};
|
||||
|
||||
struct heartbeat_msg_s {
|
||||
uint32_t sender_priority; /* sender's HA priority */
|
||||
uint64_t term; /* sender's current term */
|
||||
uint64_t committed_lsn; /* Req 5: primary's committed WAL LSN */
|
||||
uint64_t committed_config_tag; /* Req 8: primary's committed config tag */
|
||||
};
|
||||
|
||||
/* CtrlHello state sync (Req 6.5, 6.6, 6.7) */
|
||||
struct ctrl_hello_req_s {
|
||||
char *name; /* standby's logical name */
|
||||
xce_data_t *key; /* SHA-256(cluster_name + shared_secret) auth key */
|
||||
uint64_t applied_lsn; /* standby's last applied WAL LSN */
|
||||
uint64_t config_tag; /* standby's current config tag */
|
||||
};
|
||||
|
||||
struct ctrl_hello_reply_s {
|
||||
uint64_t committed_lsn; /* primary's committed WAL LSN */
|
||||
int needs_snapshot; /* 1 if standby LSN < oldest WAL segment */
|
||||
uint64_t config_tag; /* primary's current config tag */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue