fix bug-1060 bug-1067

This commit is contained in:
Rongsong Shen 2026-06-24 17:05:43 +08:00
parent 6067ba6c94
commit 61e1391cd0
28 changed files with 7021 additions and 2926 deletions

View file

@ -2014,6 +2014,7 @@ static int send_wal_batch(endpoint_t *ep,
}
int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
const persist_t *p, uint64_t leader_term,
uint64_t standby_lsn, uint64_t committed_lsn)
{
if (!wal_path)
@ -2102,9 +2103,11 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
batch_bytes = 0;
}
/* Advance the prev tracker even on the OOM-skip so a later
* entry's prev tuple stays correct. */
* entry's prev tuple stays correct. bug-1028: term from the
* authoritative index, not raw hdr.term (see main tracker). */
prev_streamed_lsn = hdr.lsn;
prev_streamed_term = hdr.term;
prev_streamed_term = p ? persist_entry_term(p, hdr.lsn)
: hdr.term;
off += (uint32_t)(sizeof(hdr) + hdr.payload_len);
continue;
}
@ -2119,9 +2122,18 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
* the (lsn,term) of the immediately preceding WAL entry (0/0
* before the first), which IS the predecessor in contiguous LSN
* order. */
entry->term = hdr.term;
/* bug-1028: own term from the authoritative per-LSN index, not
* raw hdr.term. prev_streamed_term is already normalised above. */
entry->term = p ? persist_entry_term(p, hdr.lsn)
: hdr.term;
entry->prev_log_index = prev_streamed_lsn;
entry->prev_log_term = prev_streamed_term;
/* bug-1067: stamp the leader's CURRENT term as the AppendEntries
* header term. entry->term above is the entry's STORED term (may
* be a PRIOR leader's term for a historical catch-up entry); the
* standby intake must check the leader's current term, not the
* stored term, or it stale-rejects every cross-term entry. */
entry->leader_current_term = leader_term;
if (hdr.payload_len > 0) {
uint8_t *pbuf = malloc(hdr.payload_len);
@ -2157,9 +2169,16 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
* at/below standby_lsn that are not sent — so the first streamed
* entry's prev tuple references the entry the standby already holds
* (prev_log_index == standby_lsn). (Skips on the OOM path above set
* it inline before continuing.) */
* it inline before continuing.)
*
* bug-1028: source the term from the AUTHORITATIVE per-LSN term index
* (persist_entry_term), NOT the raw on-disk hdr.term. The standby's
* logOk and the library send path both normalise via persist_entry_term
* (legacy-0 → WAL_LEGACY_TERM); sending raw hdr.term (0 for a legacy
* entry) makes prev_log_term diverge from the standby's term → logOk
* rejects the catch-up forever. p may be NULL only in count-only tests. */
prev_streamed_lsn = hdr.lsn;
prev_streamed_term = hdr.term;
prev_streamed_term = p ? persist_entry_term(p, hdr.lsn) : hdr.term;
off += (uint32_t)(sizeof(hdr) + hdr.payload_len);
}
close(fd);
@ -2240,9 +2259,14 @@ static void catchup_stream_range(cluster_t *c, repl_ep_t ep,
return;
}
#endif
if (c && c->persist.wal_path[0])
if (c && c->persist.wal_path[0]) {
/* bug-1067: pass the leader's CURRENT term so historical catch-up entries
* carry the AE header term, not their (lower) stored term. */
uint64_t leader_term =
atomic_load_explicit(&c->ha.term, memory_order_acquire);
ha_stream_wal_to_standby((endpoint_t *)ep, c->persist.wal_path,
standby_lsn, target);
&c->persist, leader_term, standby_lsn, target);
}
}
/* ha_catchup_continuation_ctx_t — heap context for the one-shot delaymgr task.