feat: implement handle_config_request(), fetch_config_from_primary(), handle_controller_join()
- handle_config_request(): primary-side handler sends up-to-date flag or version_tag; SHA-256 integrity check guards against in-place file changes; sha256/bytes fields left NULL pending Task 11 typemap shims - fetch_config_from_primary(): standby fetch with exponential backoff retry (20 attempts, 500ms..5s); falls back to saved config via load_primary_config(); do_one_config_fetch() stubbed (-ENOSYS) until Task 11 wires capnp over SSL - handle_controller_join(): registers standby endpoint in ha.standby_endpoints via zarray_store() for OP_upgradeConfig fan-out; sends success reply - Moved load_primary_config() from myconf.c to config_repl.c so the unit test binary (which links config_repl.c but not myconf.c) can resolve it
This commit is contained in:
parent
93b8616f11
commit
8f4db308da
3 changed files with 331 additions and 122 deletions
|
|
@ -152,119 +152,6 @@ cluster_config_t* get_default_conf(void* cl)
|
|||
return cfg;
|
||||
}
|
||||
|
||||
/* ── load_primary_config ────────────────────────── */
|
||||
|
||||
int load_primary_config(cluster_t *c)
|
||||
{
|
||||
myconf_t *myconf = c->myconf;
|
||||
|
||||
/* Build conf dir path: <workdir>/<name> */
|
||||
char conf_dir[4096];
|
||||
snprintf(conf_dir, sizeof(conf_dir), "%s/%s", myconf->workdir, myconf->name);
|
||||
|
||||
/* Resolve conf/current → versioned filename */
|
||||
char fname[256] = {0};
|
||||
int rc = conf_read_current_filename(conf_dir, fname, sizeof(fname));
|
||||
if (rc != 0) {
|
||||
ERROR("Primary has no config at '%s/conf/current' (rc=%d) — "
|
||||
"provision the config before starting",
|
||||
conf_dir, rc);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Heap-allocate conffile so it survives past this stack frame */
|
||||
free(myconf->conffile);
|
||||
myconf->conffile = NULL;
|
||||
if (asprintf(&myconf->conffile, "%s/conf/%s", conf_dir, fname) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Read raw bytes and check size */
|
||||
uint8_t *bytes = NULL;
|
||||
size_t blen = 0;
|
||||
rc = conf_read_raw(myconf->conffile, &bytes, &blen);
|
||||
if (rc != 0) {
|
||||
ERROR("Primary config '%s' unreadable: %d", myconf->conffile, rc);
|
||||
free(myconf->conffile);
|
||||
myconf->conffile = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Compute and cache SHA-256 */
|
||||
SHA256(bytes, blen, myconf->config_sha256);
|
||||
uint64_t tag;
|
||||
memcpy(&tag, myconf->config_sha256, 8);
|
||||
myconf->config_version_tag = be64toh(tag);
|
||||
|
||||
/* Free any prior decoded config before overwriting the pointer */
|
||||
if (myconf->cluster_config) {
|
||||
free_ClusterConfig(myconf->cluster_config);
|
||||
free(myconf->cluster_config);
|
||||
myconf->cluster_config = NULL;
|
||||
}
|
||||
|
||||
/* Decode Cap'n Proto directly into myconf->cluster_config */
|
||||
rc = load_cluster_config_from_file(myconf->conffile, &myconf->cluster_config);
|
||||
if (rc != 0) {
|
||||
ERROR("Primary config '%s' failed Cap'n Proto decode: %d",
|
||||
myconf->conffile, rc);
|
||||
free(bytes);
|
||||
free(myconf->conffile);
|
||||
myconf->conffile = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (myconf->cluster_config == NULL) {
|
||||
ERROR("Primary config '%s' decoded to NULL", myconf->conffile);
|
||||
free(bytes);
|
||||
free(myconf->conffile);
|
||||
myconf->conffile = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
free(bytes);
|
||||
|
||||
fill_default_cluster_config(myconf->cluster_config);
|
||||
|
||||
/* Check for reserved lost_and_found name */
|
||||
if (config_contains_reserved_name(myconf->cluster_config)) {
|
||||
ERROR("Config '%s' contains reserved name 'lost_and_found'",
|
||||
myconf->conffile);
|
||||
free_ClusterConfig(myconf->cluster_config);
|
||||
free(myconf->cluster_config);
|
||||
myconf->cluster_config = NULL;
|
||||
free(myconf->conffile);
|
||||
myconf->conffile = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Default generation to 1 if not set */
|
||||
if (myconf->cluster_config->config_generation == 0)
|
||||
myconf->cluster_config->config_generation = 1;
|
||||
myconf->config_generation = myconf->cluster_config->config_generation;
|
||||
|
||||
/* Check staleness */
|
||||
myconf->conf_stale = conf_check_stale(conf_dir, myconf->conf_stale_timeout);
|
||||
if (myconf->conf_stale)
|
||||
WARN("Primary config appears stale (age > %lds)",
|
||||
(long)myconf->conf_stale_timeout);
|
||||
|
||||
INFO("Primary config loaded: tag=%016" PRIx64 " gen=%" PRIu64,
|
||||
myconf->config_version_tag, myconf->config_generation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ── fetch_config_from_primary ──────────────────── */
|
||||
|
||||
int fetch_config_from_primary(cluster_t *c)
|
||||
{
|
||||
(void)c;
|
||||
/* Task 9: full implementation — connect to primary, send OP_replConfig,
|
||||
* receive blob, verify SHA-256, call conf_save_config(), decode into
|
||||
* myconf->cluster_config. */
|
||||
ERROR("fetch_config_from_primary: not yet implemented (Task 9)");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* ── myconf_fini ────────────────────────────────── */
|
||||
|
||||
void myconf_fini(myconf_t *myconf)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue