feat(raft-apply-decoupling): resolve pending continuations on demotion/truncation (task 1.4)
commit_resolve_pending_above(ce, lsn_floor, rc) fails every registered continuation for lsn > lsn_floor, reusing commit_resolve()'s existing exactly-once/idempotent guarantee (no parallel bookkeeping path). Truncation: a new on_truncate/truncate_cb_ctx callback on persist_t (same inversion-of-control shape as the existing on_durable_advance hook) fires from persist_truncate_wal_above after releasing p->lock, only when entries were actually removed. This one wrapper covers all three real truncation call sites: raft_cb_become_leader's post-election truncate, the library's on_truncate_from conflict-reconcile, and ha_demotion_convergence_fn's post-demotion truncate. Demotion: raft_cb_become_follower calls commit_resolve_pending_above(&c->commit, 0, -XCE_ERR_STANDBY) -- lsn_floor=0 fails everything, since a demoted node can never authoritatively confirm anything still pending (CP posture). Without this, a demoted or truncated node would leave any pending async command permanently unresolved -- the requester would simply never get a reply, worse than today's bounded-timeout behavior. Also closes bug-1407 (pre-existing test_config_repl flake, unrelated to this feature) -- confirmed fixed as a side effect of prior tasks in this series, 70/70 passing across 3 independent runs.
This commit is contained in:
parent
530a02bda3
commit
9b4b805a27
9 changed files with 748 additions and 301 deletions
|
|
@ -604,6 +604,12 @@ int persist_init(persist_t* p, persist_config_t* cfg, cluster_t* c)
|
|||
p->on_durable_advance = NULL;
|
||||
p->durable_cb_ctx = NULL;
|
||||
|
||||
/* Truncation wake hook starts unregistered (raft-apply-decoupling task
|
||||
* 1.4): the commit engine registers it in commit_engine_init. Until
|
||||
* then every truncation is a no-op wake. */
|
||||
p->on_truncate = NULL;
|
||||
p->truncate_cb_ctx = NULL;
|
||||
|
||||
/* Per-LSN term index starts empty (ha-term-safety 1.3, R1.5): no entries
|
||||
* recorded yet. Grown on demand by record_entry_term during replay/append;
|
||||
* freed in persist_fini. */
|
||||
|
|
@ -1279,6 +1285,17 @@ void persist_set_durable_cb(persist_t* p, void (*fn)(void* ctx), void* ctx)
|
|||
p->on_durable_advance = fn;
|
||||
}
|
||||
|
||||
/* raft-apply-decoupling task 1.4: registration counterpart of
|
||||
* persist_set_durable_cb -- see persist.h for the full contract. */
|
||||
void persist_set_truncate_cb(persist_t* p, void (*fn)(void* ctx, uint64_t cutoff_lsn),
|
||||
void* ctx)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
p->truncate_cb_ctx = ctx;
|
||||
p->on_truncate = fn;
|
||||
}
|
||||
|
||||
#ifdef XCE_TESTING
|
||||
void persist_test_set_force_fsync_fail(persist_t* p, int fail)
|
||||
{
|
||||
|
|
@ -3681,8 +3698,25 @@ static void clamp_durable_lsn_locked(persist_t* p, uint64_t tip)
|
|||
int persist_truncate_wal_above(persist_t* p, uint64_t cutoff_lsn)
|
||||
{
|
||||
pthread_mutex_lock(&p->lock);
|
||||
int rc = truncate_wal_above_locked(p, cutoff_lsn);
|
||||
uint64_t before = p->current_lsn;
|
||||
int rc = truncate_wal_above_locked(p, cutoff_lsn);
|
||||
uint64_t after = p->current_lsn;
|
||||
pthread_mutex_unlock(&p->lock);
|
||||
|
||||
/* raft-apply-decoupling task 1.4: fire the truncation wake only when a
|
||||
* truncation actually removed entries above cutoff_lsn (current_lsn
|
||||
* strictly decreased -- both truncate_wal_above_locked branches set
|
||||
* current_lsn = cutoff_lsn + 1 on a real truncation) -- mirrors the
|
||||
* durable-advance wake's own before/after guard (see fsync_worker
|
||||
* above) so a no-op truncate (nothing above cutoff_lsn, or an I/O
|
||||
* error before current_lsn is touched) never spuriously fails a
|
||||
* continuation whose entry is still safely in the log. Called AFTER
|
||||
* releasing p->lock: the callback (the commit engine) takes only
|
||||
* ce->lock, preserving the cycle-free p->lock -> ce->lock edge already
|
||||
* established by the durable-advance wake. */
|
||||
if (rc == 0 && after < before && p->on_truncate != NULL) {
|
||||
p->on_truncate(p->truncate_cb_ctx, cutoff_lsn);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue