forked from lei.chen/myxce
feat(election-iomgr-refactor): extend handle_request_vote with role-based deny gate — task 3.2
This commit is contained in:
parent
e6135ea828
commit
6de4b3ff0e
4 changed files with 286 additions and 1 deletions
|
|
@ -824,11 +824,34 @@ int ha_restore_term(ha_state_t *ha, const char *workdir)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ── Vote Handler (Req 2.2–2.6, 9.1) ───────────────────────────────────────
|
||||
/* ── ha_heartbeat_is_fresh (Req 6.2) ────────────────────────────────────────
|
||||
*
|
||||
* Returns 1 if the elapsed time since ha->last_heartbeat is strictly less than
|
||||
* ha->config.heartbeat_timeout_ms (i.e. the primary is still alive).
|
||||
* Returns 0 if the heartbeat is stale (timeout has expired).
|
||||
*
|
||||
* Uses CLOCK_MONOTONIC to avoid wall-clock skew.
|
||||
*/
|
||||
static int ha_heartbeat_is_fresh(ha_state_t *ha)
|
||||
{
|
||||
struct timespec now, last;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
pthread_mutex_lock(&ha->lock);
|
||||
last = ha->last_heartbeat;
|
||||
pthread_mutex_unlock(&ha->lock);
|
||||
long ms = (now.tv_sec - last.tv_sec) * 1000L
|
||||
+ (now.tv_nsec - last.tv_nsec) / 1000000L;
|
||||
return ms < (long)ha->config.heartbeat_timeout_ms;
|
||||
}
|
||||
|
||||
/* ── Vote Handler (Req 2.2–2.6, 6.1, 6.2, 6.4, 9.1) ────────────────────────
|
||||
*
|
||||
* handle_request_vote: process an incoming OP_requestVote RPC.
|
||||
*
|
||||
* Decision order (fail-fast):
|
||||
* 0. role gate (Req 6.1, 6.2):
|
||||
* - CTRL_PRIMARY or CTRL_PRIMARY_COMMITTING → deny
|
||||
* - CTRL_STANDBY with fresh heartbeat → deny
|
||||
* 1. in_catch_up → deny (Req 2.5)
|
||||
* 2. req term < my term → deny (Req 2.2)
|
||||
* 3. req term > my term → update term, clear voted_for (Req 2.3)
|
||||
|
|
@ -847,6 +870,17 @@ int handle_request_vote(ha_state_t *ha,
|
|||
uint64_t my_last_lsn,
|
||||
int in_catch_up_flag)
|
||||
{
|
||||
/* Req 6.1, 6.2: role-based deny gate — checked before any Raft state mutation.
|
||||
* PRIMARY and PRIMARY_COMMITTING never grant votes (protect the live primary).
|
||||
* STANDBY with a fresh heartbeat also denies (primary is alive, no new election
|
||||
* needed). CTRL_INIT and CTRL_ELECTING fall through to Raft evaluation. */
|
||||
ctrl_role_t my_role = (ctrl_role_t)atomic_load_explicit(&ha->role,
|
||||
memory_order_acquire);
|
||||
if (my_role == CTRL_PRIMARY || my_role == CTRL_PRIMARY_COMMITTING)
|
||||
return 0; /* deny — I am primary (or committing); protect against challengers */
|
||||
if (my_role == CTRL_STANDBY && ha_heartbeat_is_fresh(ha))
|
||||
return 0; /* deny — my primary is alive */
|
||||
|
||||
/* Req 2.5: catching-up standbys deny all votes */
|
||||
if (in_catch_up_flag)
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue