feat: ha_state_t, ha_config_t, ha_init/fini, role enum + config validation (P1-2)
- Full ha.h: ctrl_role_t enum (CTRL_PRIMARY/CTRL_STANDBY), ha_config_t, ha_state_t with _Atomic fields (term, role, applied_lsn, promotion counters, watchdog_stop), pthread_mutex_t lock, and public API. - endpoint_t* omitted from ha_state_t — including netio.h would pull OpenSSL headers and risk circular deps; watchdog (P1-3) includes netio.h directly where needed. - ha_init validates: heartbeat_interval_ms >= 2000, heartbeat_timeout_ms >= heartbeat_interval_ms, election_timeout_ms >= 500; returns -EINVAL on bad config; zeros struct and sets initial role to CTRL_STANDBY. - ha_fini destroys mutex; watchdog thread join deferred to P1-3. - am_i_primary / ha_promote_to_primary / ha_demote_to_standby are no-op stubs; cluster_t->ha field not yet wired (P1-5), so these avoid incomplete-type dereferences until then. - TDD: 5 new tests in test_ha_role.c confirmed RED before implementation, all 5 GREEN after; all prior controller tests remain green.
This commit is contained in:
parent
f155b1ef97
commit
a289edb777
5 changed files with 255 additions and 2 deletions
|
|
@ -1,3 +1,76 @@
|
|||
#define _GNU_SOURCE
|
||||
#include "ha.h"
|
||||
|
||||
/* P1-2: implementation added in next task */
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int ha_init(ha_state_t *ha, const ha_config_t *cfg, int my_priority)
|
||||
{
|
||||
if (!ha || !cfg)
|
||||
return -EINVAL;
|
||||
|
||||
if (cfg->heartbeat_interval_ms < 2000)
|
||||
return -EINVAL;
|
||||
if (cfg->heartbeat_timeout_ms < cfg->heartbeat_interval_ms)
|
||||
return -EINVAL;
|
||||
if (cfg->election_timeout_ms < 500)
|
||||
return -EINVAL;
|
||||
|
||||
memset(ha, 0, sizeof(*ha));
|
||||
ha->config = *cfg;
|
||||
ha->my_priority = my_priority;
|
||||
|
||||
atomic_store_explicit(&ha->role, (int32_t)CTRL_STANDBY, memory_order_release);
|
||||
atomic_store_explicit(&ha->term, 0ULL, memory_order_release);
|
||||
atomic_store_explicit(&ha->applied_lsn, 0ULL, memory_order_release);
|
||||
atomic_store_explicit(&ha->promotion_failed, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&ha->promotion_retry_count, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&ha->in_catch_up, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&ha->failover_requested, 0, memory_order_relaxed);
|
||||
atomic_store_explicit(&ha->watchdog_stop, 0, memory_order_relaxed);
|
||||
|
||||
pthread_mutex_init(&ha->lock, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ha_fini(ha_state_t *ha)
|
||||
{
|
||||
if (!ha)
|
||||
return;
|
||||
/* Watchdog thread join added in P1-3 */
|
||||
pthread_mutex_destroy(&ha->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The three cluster_t-dependent stubs below cannot dereference c->ha until
|
||||
* P1-5 adds `ha_state_t ha` to cluster_t. They compile as no-ops now and
|
||||
* will be fleshed out in P1-3a after P1-5 wires the field in.
|
||||
*/
|
||||
|
||||
int am_i_primary(cluster_t *c)
|
||||
{
|
||||
(void)c;
|
||||
/* P1-3 adds real election probing.
|
||||
* Stub: always report not-primary until cluster wiring is in place. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ha_promote_to_primary(cluster_t *c)
|
||||
{
|
||||
(void)c;
|
||||
/* Full sequence in P1-3a (WAL flush, hook calls, peer notify).
|
||||
* Stub: no-op — role management moved to P1-3a. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ha_demote_to_standby(cluster_t *c)
|
||||
{
|
||||
(void)c;
|
||||
/* Full sequence in P1-3a.
|
||||
* Stub: no-op — role management moved to P1-3a. */
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue