xce_cluster_config_to_client_config() converts a validated candidate list into a fully-populated xce_client_config_t, copying candidates in order with no special-casing for a single candidate. The truncate-with-warning safety net stays in place as a defensive guard now that N_MAX_MASTERS and MAX_HA_CANDIDATES match. Also removes a WARN check in xce_cluster_config_validate() that became unreachable dead code once task 1.1 reconciled the two candidate-count constants (both checks tested the same field against the same constant with no mutation between them). Task 1.2 of component-failover-adoption (Requirement 1 AC1-AC7).
144 lines
4.9 KiB
C
144 lines
4.9 KiB
C
/* src/include/xce/cluster.h — cluster discovery and reconnect API (P2.5-1)
|
|
*
|
|
* xce_connect_cluster() returns endpoint_t* (cast to void*).
|
|
* The SSL* is accessible as ((endpoint_t*)result)->ssl.
|
|
*/
|
|
#ifndef XCE_CLUSTER_H
|
|
#define XCE_CLUSTER_H
|
|
|
|
#include <stddef.h>
|
|
#include "client.h" /* xce_client_config_t, N_MAX_MASTERS */
|
|
#include "config.h" /* MAX_HA_CANDIDATES, XCE_MAXHOSTNAME_LEN */
|
|
|
|
/**
|
|
* A single controller candidate.
|
|
* name: logical name from "name=host:port" syntax (empty if omitted).
|
|
* Matching against myconf->name allows multiple controllers on the same
|
|
* dev host to distinguish themselves by name rather than IP address.
|
|
*/
|
|
typedef struct {
|
|
char name[XCE_MAXNAME_LEN];
|
|
char hostname[XCE_MAXHOSTNAME_LEN];
|
|
int port;
|
|
} xce_candidate_t;
|
|
|
|
/**
|
|
* Cluster connection configuration.
|
|
* Populated by each caller (worker/scheduler/apiserver) from the --peers
|
|
* CLI flag. libxce never reads config files. TLS is handled server-side
|
|
* (encryption without client-side peer certificate verification).
|
|
*
|
|
* candidates_count must be in [1, MAX_HA_CANDIDATES].
|
|
*/
|
|
typedef struct {
|
|
xce_candidate_t candidates[MAX_HA_CANDIDATES];
|
|
int candidates_count;
|
|
char identity[256]; /* "from" name sent to controller */
|
|
char key[256]; /* authentication key */
|
|
} xce_cluster_config_t;
|
|
|
|
/**
|
|
* Reconnect state machine states.
|
|
*/
|
|
typedef enum {
|
|
XCE_RECONNECT_IDLE = 0,
|
|
XCE_RECONNECT_CONNECTING,
|
|
XCE_RECONNECT_BACKOFF,
|
|
XCE_RECONNECT_CONNECTED,
|
|
XCE_RECONNECT_FAILED
|
|
} xce_reconnect_state_t;
|
|
|
|
/**
|
|
* Reconnect context (use xce_reconnect_* functions to operate).
|
|
*/
|
|
typedef struct {
|
|
xce_cluster_config_t* config;
|
|
xce_reconnect_state_t state;
|
|
int attempt;
|
|
int backoff_ms; /* current backoff delay in ms */
|
|
void* endpoint; /* endpoint_t* when CONNECTED */
|
|
} xce_reconnect_ctx_t;
|
|
|
|
/* Redirect follow limit */
|
|
#define XCE_MAX_REDIRECTS 4
|
|
|
|
/* Backoff parameters — initial kept short so tests stay fast */
|
|
#define XCE_RECONNECT_INITIAL_BACKOFF_MS 100
|
|
#define XCE_RECONNECT_MAX_BACKOFF_MS 30000
|
|
#define XCE_RECONNECT_BACKOFF_MULTIPLIER 2
|
|
|
|
/* --- Public API --- */
|
|
|
|
/**
|
|
* xce_cluster_config_validate() — validate a populated xce_cluster_config_t.
|
|
*
|
|
* Returns 0 on success, -EINVAL if:
|
|
* - candidates_count < 1 or > MAX_HA_CANDIDATES
|
|
* - any candidate has empty hostname or port <= 0
|
|
* - identity is empty
|
|
*/
|
|
int xce_cluster_config_validate(const xce_cluster_config_t* cfg);
|
|
|
|
/**
|
|
* xce_cluster_config_to_client_config() — convert a validated candidate list
|
|
* into an xce_client_config_t's master fields (nmasters/masters/master_ports).
|
|
*
|
|
* Copies up to N_MAX_MASTERS candidates from cfg->candidates[] in order.
|
|
* If cfg->candidates_count > N_MAX_MASTERS, copies the first N_MAX_MASTERS and
|
|
* logs a WARN identifying the truncated count (mirrors xce_test's existing
|
|
* clamp behavior).
|
|
*
|
|
* Does NOT set out->from / out->key — caller sets those separately.
|
|
* Does NOT validate cfg — caller must have already called
|
|
* xce_cluster_config_validate() successfully.
|
|
*
|
|
* Returns 0 on success, -EINVAL if cfg or out is NULL or cfg->candidates_count < 1.
|
|
*/
|
|
int xce_cluster_config_to_client_config(const xce_cluster_config_t* cfg,
|
|
xce_client_config_t* out);
|
|
|
|
/**
|
|
* xce_connect_cluster() — connect to the cluster via candidate list.
|
|
*
|
|
* Iterates candidates in order, attempting a TLS connection to each.
|
|
* Returns endpoint_t* (cast to void*) on success, NULL if all fail.
|
|
*/
|
|
void* xce_connect_cluster(xce_cluster_config_t* cfg);
|
|
|
|
/**
|
|
* xce_reconnect_init() — initialise a reconnect context.
|
|
* Returns 0 on success, -EINVAL on bad arguments.
|
|
*/
|
|
int xce_reconnect_init(xce_reconnect_ctx_t* rctx, xce_cluster_config_t* cfg);
|
|
|
|
/**
|
|
* xce_reconnect_step() — drive one step of the reconnect state machine.
|
|
*
|
|
* Call in a loop until state == XCE_RECONNECT_CONNECTED or FAILED.
|
|
* Sleeps backoff_ms in BACKOFF state (skipped when mock connect is set).
|
|
*
|
|
* Returns 0 to continue, -1 when in terminal state.
|
|
*/
|
|
int xce_reconnect_step(xce_reconnect_ctx_t* rctx);
|
|
|
|
/**
|
|
* xce_reconnect_fini() — release resources held by a reconnect context.
|
|
*/
|
|
void xce_reconnect_fini(xce_reconnect_ctx_t* rctx);
|
|
|
|
/**
|
|
* xce_parse_peers() — parse "--peers name=host:port,..." into cfg->candidates[].
|
|
*
|
|
* Each token may be "name=host:port" or bare "host:port".
|
|
* The name field is stored when present; it allows multiple daemons on the
|
|
* same host to identify themselves by logical name rather than IP address.
|
|
*
|
|
* Returns 0 on success, -1 on empty/NULL input or any parse error.
|
|
*/
|
|
int xce_parse_peers(const char* peers_str, xce_cluster_config_t* cfg);
|
|
|
|
/* Test seam: set to non-NULL to override the real connect (unit tests only) */
|
|
typedef void* (*xce_connect_fn_t)(const char* host, int port);
|
|
void xce_cluster_set_connect_fn(xce_connect_fn_t fn);
|
|
|
|
#endif /* XCE_CLUSTER_H */
|