fix bug-1060 bug-1067
This commit is contained in:
parent
6067ba6c94
commit
61e1391cd0
28 changed files with 7021 additions and 2926 deletions
|
|
@ -2586,7 +2586,8 @@ static void test_wal_stream_500_entries_two_batches(void)
|
|||
g_wal_stream_last_n_entries = 0;
|
||||
|
||||
/* Stream entries [1..500]: standby_lsn=0, committed_lsn=500 */
|
||||
rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir,
|
||||
rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir, /*p=*/NULL,
|
||||
/*leader_term=*/7,
|
||||
/*standby_lsn=*/0,
|
||||
/*committed_lsn=*/500);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "ha_stream_wal_to_standby failed");
|
||||
|
|
@ -2627,7 +2628,8 @@ static void test_wal_stream_partial_batch(void)
|
|||
g_wal_stream_last_n_entries = 0;
|
||||
|
||||
/* Stream entries [6..14]: standby_lsn=5, committed_lsn=14 */
|
||||
rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir,
|
||||
rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir, /*p=*/NULL,
|
||||
/*leader_term=*/7,
|
||||
/*standby_lsn=*/5,
|
||||
/*committed_lsn=*/14);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "ha_stream_wal_to_standby failed");
|
||||
|
|
@ -2661,7 +2663,8 @@ static void test_wal_stream_empty_range_no_batches(void)
|
|||
g_wal_stream_total_entries = 0;
|
||||
|
||||
/* standby_lsn == committed_lsn: nothing to stream */
|
||||
int rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir,
|
||||
int rc = ha_stream_wal_to_standby(/*ep=*/NULL, tmpdir, /*p=*/NULL,
|
||||
/*leader_term=*/7,
|
||||
/*standby_lsn=*/100,
|
||||
/*committed_lsn=*/100);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "Empty range must return 0");
|
||||
|
|
@ -2676,6 +2679,89 @@ static void test_wal_stream_empty_range_no_batches(void)
|
|||
printf("test_wal_stream_empty_range_no_batches: PASS\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* bug-1028 — the catch-up streamer must source each streamed entry's term and
|
||||
* the AppendEntries prev_log_term from the AUTHORITATIVE per-LSN term index
|
||||
* (persist_entry_term), NOT the raw on-disk hdr.term. A legacy-0 entry has
|
||||
* hdr.term==0 on disk but persist_entry_term maps it to WAL_LEGACY_TERM(1) —
|
||||
* which is exactly what the standby's logOk and the library send path compute.
|
||||
* If the streamer sends the raw 0, prev_log_term(0) != standby's term(1) → logOk
|
||||
* rejects the new-term entry forever (the "stream WAL batches" wedge).
|
||||
*
|
||||
* Fixture: LSN 1 appended at term 0 (legacy), LSN 2 at term 3. Streaming
|
||||
* (standby_lsn=1, committed=2] must emit LSN 2 with term=3 and prev_log_term=1
|
||||
* (NOT 0). RED before the fix (streamer sent hdr.term=0 for the predecessor).
|
||||
*/
|
||||
static uint64_t g_cap_term_for_lsn2 = 0;
|
||||
static uint64_t g_cap_prevterm_for_lsn2 = 0;
|
||||
static int g_cap_saw_lsn2 = 0;
|
||||
|
||||
static int capture_terms_wal_stream_hook(endpoint_t *ep, xce_request_t *req)
|
||||
{
|
||||
(void)ep;
|
||||
if (!req || !req->body.walcatchupentrymsg) return 0;
|
||||
wal_catchup_entry_t *batch =
|
||||
(wal_catchup_entry_t *)req->body.walcatchupentrymsg;
|
||||
for (int i = 0; i < batch->n_entries; i++) {
|
||||
wal_catchup_entry_t *e = batch->entries[i];
|
||||
if (e && e->lsn == 2) {
|
||||
g_cap_saw_lsn2 = 1;
|
||||
g_cap_term_for_lsn2 = e->term;
|
||||
g_cap_prevterm_for_lsn2 = e->prev_log_term;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_wal_stream_term_from_index_not_raw_hdr(void)
|
||||
{
|
||||
char tmp[256];
|
||||
strcpy(tmp, "/tmp/xce_cr_streamterm_XXXXXX");
|
||||
TEST_ASSERT_NOT_NULL(mkdtemp(tmp));
|
||||
|
||||
cluster_t *c = t42_make_cluster(tmp);
|
||||
TEST_ASSERT_NOT_NULL(c);
|
||||
|
||||
/* LSN 1: legacy entry (term 0 on disk → persist_entry_term maps to 1). */
|
||||
persist_set_term(&c->persist, 0);
|
||||
TEST_ASSERT_EQUAL_INT(0, persist_wal_async(&c->persist, WAL_JOB_UPDATE,
|
||||
NULL, 0));
|
||||
/* LSN 2: real new-term entry (term 3). */
|
||||
persist_set_term(&c->persist, 3);
|
||||
TEST_ASSERT_EQUAL_INT(0, persist_wal_async(&c->persist, WAL_JOB_UPDATE,
|
||||
NULL, 0));
|
||||
|
||||
/* Sanity: the authoritative index normalises legacy-0 → 1, keeps 3. */
|
||||
TEST_ASSERT_EQUAL_UINT64(WAL_LEGACY_TERM, persist_entry_term(&c->persist, 1));
|
||||
TEST_ASSERT_EQUAL_UINT64(3, persist_entry_term(&c->persist, 2));
|
||||
|
||||
xce_wal_stream_request_hook = capture_terms_wal_stream_hook;
|
||||
g_cap_saw_lsn2 = 0; g_cap_term_for_lsn2 = 0; g_cap_prevterm_for_lsn2 = 0;
|
||||
|
||||
/* Standby holds LSN 1, catching up to committed 2 — streams just LSN 2,
|
||||
* whose prev tuple references LSN 1 (the legacy entry). */
|
||||
int rc = ha_stream_wal_to_standby(/*ep=*/NULL, c->persist.wal_path,
|
||||
&c->persist,
|
||||
/*leader_term=*/atomic_load_explicit(
|
||||
&c->ha.term, memory_order_acquire),
|
||||
/*standby_lsn=*/1, /*committed_lsn=*/2);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, rc, "ha_stream_wal_to_standby failed");
|
||||
xce_wal_stream_request_hook = NULL;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(g_cap_saw_lsn2, "LSN 2 must be streamed");
|
||||
TEST_ASSERT_EQUAL_UINT64_MESSAGE(3, g_cap_term_for_lsn2,
|
||||
"streamed entry term must come from persist_entry_term (3)");
|
||||
TEST_ASSERT_EQUAL_UINT64_MESSAGE(WAL_LEGACY_TERM, g_cap_prevterm_for_lsn2,
|
||||
"bug-1028: prev_log_term must be the index-normalised legacy term (1), "
|
||||
"NOT raw on-disk hdr.term (0) — else the standby's logOk rejects forever");
|
||||
|
||||
t42_teardown(c);
|
||||
char cmd[512];
|
||||
snprintf(cmd, sizeof(cmd), "rm -rf %s", tmp);
|
||||
system(cmd);
|
||||
printf("test_wal_stream_term_from_index_not_raw_hdr: PASS\n");
|
||||
}
|
||||
|
||||
/* ── Task 3.5: Snapshot chunk transfer ──────────────────────── */
|
||||
|
||||
static snapshot_transfer_t g_snaptest_chunks[16];
|
||||
|
|
@ -3363,6 +3449,7 @@ void test_config_repl(void)
|
|||
RUN_TEST(test_wal_stream_500_entries_two_batches);
|
||||
RUN_TEST(test_wal_stream_partial_batch);
|
||||
RUN_TEST(test_wal_stream_empty_range_no_batches);
|
||||
RUN_TEST(test_wal_stream_term_from_index_not_raw_hdr); /* bug-1028 */
|
||||
/* Task 3.5: snapshot chunk transfer (sender side) */
|
||||
RUN_TEST(test_snapshot_transfer_two_chunks);
|
||||
RUN_TEST(test_snapshot_transfer_small_less_than_one_chunk);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue