fix(controller): record standby state under its absolute peer index (bug-1891)
A promoted vote endpoint carries a peer index relative to the votes array (which leaves out the primary); a late-joiner's heartbeat endpoint carries the absolute index. repl_ack_decode_and_dispatch recorded state reports under the raw index, so with ctrl-1 primary, ctrl-3's vote endpoint (relative 1) and a rejoined ctrl-2's heartbeat endpoint (absolute 1) shared standby_reported_*[1]. Each handler then acted on the other's position over its own endpoint: the snapshot meant for the empty, rejoining ctrl-2 went to the caught-up ctrl-3, and ctrl-2 never caught up. Resolve the absolute index with ha_repl_ack_abs_peer_idx (as the WAL-ack branch already did) for the state report and for ha_walack_on_ack, and size catchup_inflight by MAX_HA_CANDIDATES so every absolute index fits. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1922ac803e
commit
4922f6c844
6 changed files with 188 additions and 10 deletions
|
|
@ -2929,7 +2929,7 @@ static void catchup_lane_fn(void *arg)
|
|||
clear_and_done:
|
||||
/* Req 5.2: release the single-flight slot so the next lagging ACK schedules
|
||||
* again. release order so the decision path's acquire load observes it. */
|
||||
if (peer_idx >= 0 && peer_idx < MAX_STANDBYS)
|
||||
if (peer_idx >= 0 && peer_idx < MAX_HA_CANDIDATES)
|
||||
atomic_store_explicit(&c->ha.catchup_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
free(ctx);
|
||||
|
|
@ -2990,7 +2990,7 @@ int ha_catchup_continuation_fn(void *arg)
|
|||
* but whose key the lane has not yet removed. Release the guard so
|
||||
* the next WAL ack retries cleanly (mirrors ha_connect_to_peer's
|
||||
* -EEXIST handling in ha.c). */
|
||||
if (peer_idx >= 0 && peer_idx < MAX_STANDBYS)
|
||||
if (peer_idx >= 0 && peer_idx < MAX_HA_CANDIDATES)
|
||||
atomic_store_explicit(&c->ha.catchup_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
free(ctx);
|
||||
|
|
@ -3004,7 +3004,7 @@ int ha_catchup_continuation_fn(void *arg)
|
|||
* ack, unlike the one-shot demotion-convergence task). */
|
||||
WARN("HA catch-up continuation: slowlane_submit failed for "
|
||||
"standby[%d]: %d — retry next ack", peer_idx, srv);
|
||||
if (peer_idx >= 0 && peer_idx < MAX_STANDBYS)
|
||||
if (peer_idx >= 0 && peer_idx < MAX_HA_CANDIDATES)
|
||||
atomic_store_explicit(&c->ha.catchup_inflight[peer_idx], 0,
|
||||
memory_order_release);
|
||||
free(ctx);
|
||||
|
|
@ -3061,7 +3061,7 @@ int ha_walack_on_ack(cluster_t *c, void *ep, int peer_idx, uint64_t acked_lsn)
|
|||
{
|
||||
if (c == NULL || ep == NULL)
|
||||
return -EINVAL;
|
||||
if (peer_idx < 0 || peer_idx >= MAX_STANDBYS)
|
||||
if (peer_idx < 0 || peer_idx >= MAX_HA_CANDIDATES)
|
||||
return -EINVAL;
|
||||
|
||||
uint64_t target = catchup_derive_target(c);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue