feat(libxce-failover): reconnect recovery — ctx ERR->RUN reset + stale wbuf drain (fixes post-failover EINVAL) (task 3.2)

This commit is contained in:
Rongsong Shen 2026-06-17 03:36:24 +00:00
parent 84c5e32c2c
commit 12284bc3f5
5 changed files with 170 additions and 1 deletions

View file

@ -139,4 +139,25 @@ bool xcecli_retry_decide(api_ctx_t* ac, int* rc, bool is_write,
bool xcecli_retry_next(api_ctx_t* ac, int* rc, bool is_write,
xcecli_retry_t* st);
/*
* xcecli_ctx_recover (task 3.2) — repair the inner xce_ctx_t after a successful
* reconnect so the next xce_* attempt can proceed. Socket-free (no I/O, no
* sleep) so it is unit-testable; xcecli_retry_next invokes it after a successful
* xce_failover_rotate(), before re-sending the interrupted op.
*
* CI2 (state reset): the transport-error path left ctx->state = XCE_CTX_ERR
* (xcectx.c:174), which the per-op XCE_CTX_RUN guard rejects as -EINVAL
* (xceapi.c) — the reported bug. recover restores XCE_CTX_RUN, but ONLY from
* ERR: a DOWN/INIT ctx (deliberately stopped / not yet started) is left
* as-is, and a RUN ctx is already fine.
* CI1 (stale-reply drain): handle_disconnect may have injected a stale status
* into the single-slot ctx->wbuf (xcectx.c:180). recover drains any pending
* entry with a non-blocking cbuf_tryget so the next attempt's cbuf_get
* cannot consume a prior-attempt reply. Reconnect closes the old fd first,
* so the dead connection yields no further replies — this drain is enough.
*
* Returns 0 on success, -EINVAL on a NULL ac.
*/
int xcecli_ctx_recover(api_ctx_t* ac);
#endif