feat: wire persist_init/recover/start/stop into cluster lifecycle (P0-F)

- Add `persist_t persist` field to cluster_t (cluster_def.h includes persist.h)
- Add `workdir` and `name` fields to myconf_t; main.c passes them through
- cluster_init: call persist_set_workdir, persist_init, persist_recover after apiserver_init
- cluster_start: call persist_start (launches fsync thread + registers WAL hooks)
- cluster_fini: call persist_stop + persist_fini before delaymgr/vtaskmgr teardown
- persist_init: store cluster back-pointer (replaces (void)c stub)
- persist_start: register persist_job/queue/worker_hook_fun via xce_add_hook when cluster != NULL
- Add test_cluster_persist.c: compile-time struct check + config defaults + workdir path derivation
- Register test in controller_test.c and meson.build

All controller tests pass (1/1 OK, 50s).
This commit is contained in:
Rongsong Shen 2026-05-07 13:07:47 +00:00
parent 3030012f51
commit b52fbef36d
9 changed files with 159 additions and 2 deletions

View file

@ -13,6 +13,7 @@ extern void test_persist_recovery(void);
extern void test_hooks(void);
extern void test_persist_hooks(void);
extern void test_gc_retention(void);
extern void test_cluster_persist(void);
void setUp(void) { return; }
@ -95,6 +96,7 @@ int main(int argc, char* argv[])
TEST(test_hooks);
TEST(test_persist_hooks);
TEST(test_gc_retention);
TEST(test_cluster_persist);
return UNITY_END();
}

View file

@ -0,0 +1,103 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unity/unity.h>
#include "config.h"
#include "persist.h"
#include "xce/cluster_def.h"
/* ------------------------------------------------------------------ */
/* Compile-time structural checks */
/* ------------------------------------------------------------------ */
static void test_cluster_t_has_persist_field(void)
{
/* Verify cluster_t has a persist field — compile-time structural check.
* If persist_t persist is not in cluster_t, this will fail to compile. */
cluster_t c;
memset(&c, 0, sizeof(c));
/* Access the persist field to confirm it exists at compile time */
(void)c.persist.current_lsn;
TEST_PASS_MESSAGE("cluster_t has persist field");
}
/* ------------------------------------------------------------------ */
/* persist_config_defaults() correctness */
/* ------------------------------------------------------------------ */
static void test_persist_config_defaults_wal_sync_ms(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_WAL_SYNC_MS, cfg.wal_sync_ms);
}
static void test_persist_config_defaults_snap_interval_s(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_SNAP_INTERVAL_S, cfg.snap_interval_s);
}
static void test_persist_config_defaults_snap_wal_size_mb(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_SNAP_WAL_SIZE_MB, cfg.snap_wal_size_mb);
}
static void test_persist_config_defaults_snap_keep_n(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_SNAP_KEEP_N, cfg.snap_keep_n);
}
static void test_persist_config_defaults_finished_retain_s(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_FINISHED_RETAIN_S, cfg.finished_retain_s);
}
static void test_persist_config_defaults_sync_timeout_ms(void)
{
persist_config_t cfg = persist_config_defaults();
TEST_ASSERT_EQUAL_UINT32(DEFAULT_SYNC_TIMEOUT_MS, cfg.sync_timeout_ms);
}
/* ------------------------------------------------------------------ */
/* persist_set_workdir derives correct paths */
/* ------------------------------------------------------------------ */
static void test_persist_set_workdir_derives_wal_path(void)
{
persist_t p;
memset(&p, 0, sizeof(p));
persist_set_workdir(&p, "/tmp/xce", "ctrl1");
TEST_ASSERT_EQUAL_STRING("/tmp/xce/ctrl1/data/wal", p.wal_path);
}
static void test_persist_set_workdir_derives_snap_path(void)
{
persist_t p;
memset(&p, 0, sizeof(p));
persist_set_workdir(&p, "/tmp/xce", "ctrl1");
TEST_ASSERT_EQUAL_STRING("/tmp/xce/ctrl1/data/snap", p.snap_path);
}
/* ------------------------------------------------------------------ */
/* Suite entry point */
/* ------------------------------------------------------------------ */
void test_cluster_persist(void)
{
printf("\n>> cluster persist wiring tests (P0-F)\n\n");
RUN_TEST(test_cluster_t_has_persist_field);
RUN_TEST(test_persist_config_defaults_wal_sync_ms);
RUN_TEST(test_persist_config_defaults_snap_interval_s);
RUN_TEST(test_persist_config_defaults_snap_wal_size_mb);
RUN_TEST(test_persist_config_defaults_snap_keep_n);
RUN_TEST(test_persist_config_defaults_finished_retain_s);
RUN_TEST(test_persist_config_defaults_sync_timeout_ms);
RUN_TEST(test_persist_set_workdir_derives_wal_path);
RUN_TEST(test_persist_set_workdir_derives_snap_path);
}