feat: add config_repl Phase 1 — HEAD-file storage, SHA-256, trim, stale check, sanitise_cn
- config_repl.h/.c: atomic versioned file save, pointer file, trim, stale check - test_config_repl.c: 17 Unity tests covering all Phase 1 storage functions - typemap.h: add repl/heartbeat types + union members for xce_request_t/xce_reply_t - clusterconfig.h: add config_generation field to cluster_config_t (capnp schema ref) - meson.build: add config_repl.c and test_config_repl.c to build targets - controller_test.c: register test_config_repl dispatch function
This commit is contained in:
parent
1c4a103a66
commit
491c2550c2
7 changed files with 926 additions and 7 deletions
92
src/controller/config_repl.h
Normal file
92
src/controller/config_repl.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
/* config_repl.h — config storage, SHA-256, and replication functions */
|
||||
#define _GNU_SOURCE
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "myconf.h"
|
||||
#include "clusterconfig.h"
|
||||
|
||||
/* Max config blob size — reject before allocating */
|
||||
#define CONF_MAX_SIZE (1 * 1024 * 1024) /* 1 MiB */
|
||||
|
||||
/* Compile-time gate for OP_upgradeConfig (Phase 2, default disabled) */
|
||||
#ifndef CONF_ENABLE_UPGRADE_CONFIG
|
||||
#define CONF_ENABLE_UPGRADE_CONFIG 0
|
||||
#endif
|
||||
|
||||
/* Push timeout for standby fan-out (ms) */
|
||||
#ifndef CONF_PUSH_TIMEOUT_MS
|
||||
#define CONF_PUSH_TIMEOUT_MS 500
|
||||
#endif
|
||||
|
||||
/* Certificate expiry warning threshold (days) */
|
||||
#define CERT_WARN_DAYS 30
|
||||
|
||||
/* ── Phase 1: Storage ────────────────────────────────────────── */
|
||||
|
||||
/*
|
||||
* conf_read_current_filename: read HEAD-style pointer file at
|
||||
* <workdir>/conf/current. Strips trailing newline. Validates format:
|
||||
* must start with "cluster.bin." followed by exactly 12 hex chars.
|
||||
* Returns 0 on success; -ENOENT if absent; -ENODATA if empty (zero-length);
|
||||
* -EINVAL if malformed (path separator, wrong prefix, wrong hex length).
|
||||
* out must be at least NAME_MAX bytes.
|
||||
*/
|
||||
int conf_read_current_filename(const char *workdir, char *out, size_t outsz);
|
||||
|
||||
/*
|
||||
* conf_save_config: atomically write versioned file and update HEAD pointer.
|
||||
* 1. Writes <conf_dir>/cluster.bin.<hex>.tmp, fsyncs, renames to versioned path.
|
||||
* 2. Writes <conf_dir>/current.<tid>.tmp, fsyncs, renames to conf/current.
|
||||
* 3. fsyncs the conf/ directory.
|
||||
* 4. Trims old versions.
|
||||
* 5. Updates myconf->conffile (heap-allocated via asprintf; caller must free).
|
||||
* 6. Updates myconf->config_version_tag and myconf->config_sha256.
|
||||
* Returns 0 on success, -errno on failure.
|
||||
*/
|
||||
int conf_save_config(myconf_t *myconf, const uint8_t *bytes, size_t len,
|
||||
const uint8_t sha256[32]);
|
||||
|
||||
/*
|
||||
* conf_read_raw: read versioned file at conffile path.
|
||||
* Allocates *bytes (caller must free). Enforces CONF_MAX_SIZE.
|
||||
* Returns 0 on success; -EFBIG if exceeds limit; -errno on I/O error.
|
||||
*/
|
||||
int conf_read_raw(const char *conffile, uint8_t **bytes, size_t *len);
|
||||
|
||||
/*
|
||||
* conf_get_saved_tag: return first 8 bytes of SHA-256 of the current
|
||||
* versioned file in host byte order. Returns 0 if conf/current absent.
|
||||
* This is the "no config saved" zero-tag sentinel.
|
||||
*/
|
||||
uint64_t conf_get_saved_tag(const char *workdir);
|
||||
|
||||
/*
|
||||
* conf_check_stale: returns 1 if the current versioned file's mtime is
|
||||
* older than stale_timeout_s seconds. Returns 0 if within timeout or
|
||||
* if stale_timeout_s == 0 (disabled). Returns 0 if conf/current absent.
|
||||
*/
|
||||
int conf_check_stale(const char *workdir, time_t stale_timeout_s);
|
||||
|
||||
/*
|
||||
* conf_trim_old_versions: keep at most keep_n versioned cluster.bin.* files
|
||||
* sorted by mtime (newest first). Always preserves the file named by the
|
||||
* current conf/current pointer. Also removes stale .tmp files.
|
||||
*/
|
||||
void conf_trim_old_versions(const char *workdir, int keep_n);
|
||||
|
||||
/*
|
||||
* config_contains_reserved_name: returns 1 if ClusterConfig contains a
|
||||
* queue or host named "lost_and_found". Returns 0 for NULL config.
|
||||
* Checks queues[i]->queue (queue name) and hconfigs[i]->name (host name).
|
||||
*/
|
||||
int config_contains_reserved_name(cluster_config_t *cfg);
|
||||
|
||||
/*
|
||||
* sanitise_cn: copy at most maxlen printable ASCII chars from src to a
|
||||
* static buffer, replacing non-printable/control chars with '?'.
|
||||
* Returns pointer to the static buffer. NOT thread-safe (static storage).
|
||||
*/
|
||||
char *sanitise_cn(const char *src, size_t maxlen);
|
||||
Loading…
Add table
Add a link
Reference in a new issue