myxce/src/controller/myapp.c

129 lines
3.7 KiB
C

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#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;
}