forked from lei.chen/myxce
feat(ha-term-safety): retire term-0 repl_broadcast live send; carry leader term on replication (task 3.4)
Closes bug-990: the live replicator repl_broadcast wire-encoded term=0 (entry.term was never set), so standbys persisted hdr.term=0 and took the legacy direct-apply path instead of the library (term,lsn) intake. Now the live broadcast and catch-up streamer carry the leader's real term + AE prev tuple; ha_apply_wal_catchup_entry routes every term-carrying entry through raft_on_append_entries_request -> on_persist_entry (leader term stamped), retiring the term-0 direct-apply. Standbys now persist the leader's real term and reconcile by (term,lsn); the live commit chain is end-to-end. 848/849/850 + persist-before-ACK + commit-barrier + bug-960 preserved. Proven at integration level; the definitive live STRICT_TERM failover run is env-blocked here (bug-924 overlayfs) and recommended on a real fs.
This commit is contained in:
parent
87242aa8e9
commit
efe621c124
11 changed files with 307 additions and 45 deletions
|
|
@ -2055,6 +2055,16 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
|
|||
int batch_n = 0;
|
||||
size_t batch_bytes = 0;
|
||||
|
||||
/* ha-term-safety task 3.4: track the previous streamed entry's
|
||||
* (lsn, term) so each catch-up entry carries the AppendEntries prev tuple
|
||||
* (prev_log_index, prev_log_term) + its own term. The standby intake routes
|
||||
* every term-carrying sub-entry through raft_on_append_entries_request so it
|
||||
* persists the LEADER's term (not a local substitute). Entries are streamed
|
||||
* in strict ascending LSN order, so the prev tuple of entry N is exactly the
|
||||
* (lsn, term) of the entry emitted just before it (0/0 before the first). */
|
||||
uint64_t prev_streamed_lsn = 0;
|
||||
uint64_t prev_streamed_term = 0;
|
||||
|
||||
for (int si = 0; si < nseg; si++) {
|
||||
/* Skip segments whose entire range is at or below standby_lsn */
|
||||
if (si + 1 < nseg && seg_lsns[si + 1] <= standby_lsn)
|
||||
|
|
@ -2091,6 +2101,10 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
|
|||
batch_n = 0;
|
||||
batch_bytes = 0;
|
||||
}
|
||||
/* Advance the prev tracker even on the OOM-skip so a later
|
||||
* entry's prev tuple stays correct. */
|
||||
prev_streamed_lsn = hdr.lsn;
|
||||
prev_streamed_term = hdr.term;
|
||||
off += (uint32_t)(sizeof(hdr) + hdr.payload_len);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2099,6 +2113,15 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
|
|||
entry->n_entries = 0;
|
||||
entry->entries = NULL;
|
||||
entry->payload = NULL;
|
||||
/* ha-term-safety task 3.4: carry the leader's term + prev tuple
|
||||
* so the standby intake routes this through the library and
|
||||
* persists the LEADER's term (R1.3/R1.4). prev_streamed_* holds
|
||||
* 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;
|
||||
entry->prev_log_index = prev_streamed_lsn;
|
||||
entry->prev_log_term = prev_streamed_term;
|
||||
|
||||
if (hdr.payload_len > 0) {
|
||||
uint8_t *pbuf = malloc(hdr.payload_len);
|
||||
|
|
@ -2130,6 +2153,13 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path,
|
|||
batch_bytes = 0;
|
||||
}
|
||||
}
|
||||
/* Advance the prev tracker for EVERY scanned entry — including those
|
||||
* 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.) */
|
||||
prev_streamed_lsn = hdr.lsn;
|
||||
prev_streamed_term = hdr.term;
|
||||
off += (uint32_t)(sizeof(hdr) + hdr.payload_len);
|
||||
}
|
||||
close(fd);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue