From c4a5325aafd3f03ce7520731b9da7253d7d178f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Mon, 7 Mar 2022 14:42:17 +0300 Subject: [PATCH] mdbx: check-and-retry against page arrival as a workaround for unified page/buffer cache incoherency. Part 2 of 2 of the workaround for https://github.com/erthink/libmdbx/issues/269. --- src/core.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/core.c b/src/core.c index 0aa83ddf..3f25c37e 100644 --- a/src/core.c +++ b/src/core.c @@ -5046,9 +5046,37 @@ static int mdbx_iov_write(MDBX_txn *const txn, struct mdbx_iov_ctx *ctx) { ctx->iov_bytes); } - for (unsigned i = 0; i < ctx->iov_items; i++) - mdbx_dpage_free(env, (MDBX_page *)ctx->iov[i].iov_base, - bytes2pgno(env, ctx->iov[i].iov_len)); + uint64_t timestamp = 0; + for (unsigned i = 0; i < ctx->iov_items; i++) { + MDBX_page *wp = (MDBX_page *)ctx->iov[i].iov_base; + const MDBX_page *rp = pgno2page(txn->mt_env, wp->mp_pgno); + /* check with timeout as the workaround + * for https://github.com/erthink/libmdbx/issues/269 */ + while (unlikely(memcmp(wp, rp, ctx->iov[i].iov_len) != 0)) { + if (!timestamp) { + timestamp = mdbx_osal_monotime(); + mdbx_iov_done(txn, ctx); + mdbx_warning( + "catch delayed/non-arrived page %" PRIaPGNO " %s", wp->mp_pgno, + "(workaround for incoherent flaw of unified page/buffer cache)"); + } else if (unlikely(mdbx_osal_monotime() - timestamp > 65536 / 10)) { + mdbx_error( + "bailout waiting for %" PRIaPGNO " page arrival %s", wp->mp_pgno, + "(workaround for incoherent flaw of unified page/buffer cache)"); + return MDBX_CORRUPTED; + } +#if defined(_WIN32) || defined(_WIN64) + SwitchToThread(); +#elif defined(__linux__) || defined(__gnu_linux__) || defined(_UNIX03_SOURCE) + sched_yield(); +#elif (defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 1)) || defined(_OPEN_THREADS) + pthread_yield(); +#else + usleep(42); +#endif + } + mdbx_dpage_free(env, wp, bytes2pgno(env, ctx->iov[i].iov_len)); + } #if MDBX_ENABLE_PGOP_STAT txn->mt_env->me_lck->mti_pgop_stat.wops.weak += ctx->iov_items;