Chain of fixes needed to get --force-snapshot soak to a real live PASS (raft-ha-core-safety task 5.10a / ha-entity-snapshots task 7.1): 1. WAL segment rotation was gated on a hardcoded 64MB compile-time constant; trim_wal_segments() never deletes the active (currently-open) segment. At soak job counts a segment never rotated, so nothing was ever physically trimmable and ha_evaluate_repl_action always chose STREAM_WAL over SEND_SNAPSHOT for an empty-rejoining node. Fixed by threading a wal_segment_bytes override through persist_config_t (mirrors the --max-wal-records pattern: config.h default, persist.h setter, persist.c 3 usage sites + minimum-floor enforcement, 6-point CLI wiring through main.c/myconf.h/myapp.c/cluster.c) plus a new --wal-segment-bytes CLI flag. run-ha-soak.sh's --force-snapshot mode now sets WAL_SEGMENT_BYTES=4096 to force real rotation at soak scale. 2. This unmasked a genuine heap-use-after-free in INVOKE_MSG_HANDLER (include/netio.h): the macro calls ep->msg_handler(ep) synchronously (not via the vtask dispatcher, so the bug-1298 vtask ref/unref pairing doesn't cover it) then writes ep->fsm_in.pkt = NULL. A stale vote-reply handler chain (raft_on_vote_reply -> raft_cb_become_follower -> endpoint_unref) could drop the endpoint's last ref and free it inside the handler call, so the trailing write hit freed memory. This is the first-ever live exercise of a node receiving a snapshot transfer while mid-election. Fixed by holding a ref across the synchronous call, same pattern task 5.8 established for the async path. With both fixes: --force-snapshot soak now PASSES live (committed divergence=0, job_loss=0, confirmed real "HA: snapshot" install on the restarted node) — first genuine live proof of this scenario. 3-round --chaotic regression clean. Full 217-test controller suite green before/after every fix in the chain. Builds on the delaymgr starvation fix (b9ad018) and walcompare checkpoint-floor fix (f3c86a6) from earlier in this investigation.
52 lines
2.1 KiB
C
52 lines
2.1 KiB
C
#if !defined(_MYCONF_H_)
|
|
|
|
#define _MYCONF_H_ 1
|
|
|
|
#define MAX_MASTER_CANDIDATES (64)
|
|
|
|
#include <time.h>
|
|
#include <stdint.h>
|
|
|
|
#include <tlog.h>
|
|
|
|
#include "clusterconfig.h"
|
|
#include "xce/cluster.h"
|
|
|
|
/* Forward declaration — avoids circular include with cluster_def.h */
|
|
typedef struct cluster_s cluster_t;
|
|
|
|
struct logging {
|
|
char* logdir;
|
|
char* loglevel;
|
|
};
|
|
|
|
typedef struct {
|
|
cluster_config_t* cluster_config;
|
|
char* conffile;
|
|
char* certfile;
|
|
char* keyfile;
|
|
char* workdir; /* working directory for WAL/snapshot storage */
|
|
char* name; /* controller name (hostname by default) */
|
|
xce_cluster_config_t peers_cfg; /* HA peer list parsed from --peers; count==0 = single-node */
|
|
uint64_t config_version_tag; /* first 8 bytes of SHA-256, host order */
|
|
uint8_t config_sha256[32]; /* full SHA-256 of conffile bytes */
|
|
int conf_keep_n; /* versioned file retention count (default 2) */
|
|
uint64_t config_generation; /* monotonic audit counter */
|
|
time_t conf_stale_timeout; /* seconds before saved config flagged stale (default 86400) */
|
|
int conf_stale; /* 1 when saved config older than conf_stale_timeout */
|
|
int vcpus; /* Req 4.3: --vcpus CLI value; 0 = use config default */
|
|
uint32_t sync_timeout_ms; /* --sync-timeout-ms; 0 = use persist default */
|
|
uint32_t wal_sync_ms; /* --wal-sync-ms; 0 = use persist default */
|
|
uint32_t max_wal_records; /* --max-wal-records; 0 = use persist default */
|
|
uint32_t wal_segment_bytes; /* --wal-segment-bytes; 0 = use persist default */
|
|
} myconf_t;
|
|
|
|
extern cluster_config_t* get_default_conf(void*);
|
|
extern int add_config(void*, char*, char*);
|
|
|
|
void myconf_fini(myconf_t *myconf);
|
|
|
|
int load_primary_config(cluster_t *c);
|
|
int fetch_config_from_primary(cluster_t *c);
|
|
|
|
#endif
|