#include #include #include #include #include #include #include "cluster.h" #include "ha.h" #include "myconf.h" #include "netio.h" #include "xce/cluster_def.h" #include "request.h" #include "utils.h" /* forward declaration — implemented in startup_validation.c */ int validate_startup_config(const char *config_path, char *warn_buf, size_t warn_len); time_t last_print_time = 0; unsigned long npkts = 0; unsigned long npkts_old = 0; int myapp_run(myconf_t* myconf) { cluster_t c; int rc; memset(&c, 0x0, sizeof(c)); c.myconf = myconf; /* Phase 1: pre-config init (hooks, HA priority, standby_endpoints, cbuf) */ rc = cluster_init_phase1(&c); if (rc < 0) { ERROR("cluster_init_phase1: %s", strerror(-rc)); cluster_fini(&c); return rc; } /* SSL context — created after Phase 1, used by election probing and Phase 2 */ initialize_openssl(); SSL_CTX* ssl_ctx = create_ssl_context(myconf->certfile, myconf->keyfile); if (!ssl_ctx) { ERROR("create_ssl_context failed"); cluster_fini(&c); return -EINVAL; } c.ha.ssl_ctx = ssl_ctx; /* Req 1.1: open the listener socket before any election probe so that * concurrent-startup peers can reach this node's vote handler. */ rc = cluster_open_listener(&c); if (rc < 0) { ERROR("cluster_open_listener: %s", strerror(-rc)); cluster_fini(&c); return rc; } /* Req 1.2: initialise the I/O manager and virtual task manager before * election so that incoming vote requests are handled by the normal * dispatch loop once it starts. */ iomgr_init(&(c.iomgr)); iomgr_set_ssl_ctx(&(c.iomgr), ssl_ctx); { int nvcpus = (myconf->vcpus > 0) ? myconf->vcpus : 8; vtaskmgr_init(&(c.vtaskmgr), nvcpus); } /* Election: determine role before loading config. * Capture result once — am_i_primary() probes peers and is expensive. */ int is_primary = am_i_primary(&c); if (is_primary) { /* Primary: load config from conf/current (FATAL if missing) */ rc = load_primary_config(&c); if (rc != 0) { cluster_fini(&c); myconf_fini(myconf); return rc; } /* Record election outcome so cluster_init_phase2() sees CTRL_PRIMARY. * ha_init() unconditionally defaults ha->role to CTRL_STANDBY. */ atomic_store_explicit(&c.ha.role, (int32_t)CTRL_PRIMARY, memory_order_release); } else { /* Standby: fetch config from primary before Phase 2 */ rc = fetch_config_from_primary(&c); if (rc != 0) { cluster_fini(&c); myconf_fini(myconf); return rc; } /* Role stays CTRL_STANDBY — already set by ha_init(). */ } /* Req 4.4: warn if config file contains deprecated 'vcpus' key */ { char warn_buf[256] = {0}; validate_startup_config(myconf->conffile, warn_buf, sizeof(warn_buf)); if (warn_buf[0]) { WARN("startup: %s", warn_buf); } } /* Phase 2: full init (requires cluster_config) */ rc = cluster_init_phase2(&c); if (rc < 0) { ERROR("cluster_init_phase2: %s", strerror(-rc)); cluster_fini(&c); myconf_fini(myconf); return rc; } rc = cluster_start(&c); if (rc < 0) { SET_ERROR(-rc); perror("cluster_start"); cluster_fini(&c); myconf_fini(myconf); return rc; } rc = cluster_run(&c); cluster_fini(&c); myconf_fini(myconf); return rc; }