From 12ed2bcfbd77598f45ebcc2eda83840a35c9df82 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, 21 Nov 2022 17:09:31 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B5=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BA=D1=83=D1=80=D1=81=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B2=20GC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core.c | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/core.c b/src/core.c index 625c291a..e7d00a15 100644 --- a/src/core.c +++ b/src/core.c @@ -6617,15 +6617,6 @@ static __inline bool is_gc_usable(const MDBX_txn *txn) { return true; } -static int gc_cursor_init(MDBX_cursor *mc, MDBX_txn *txn) { - if (unlikely(txn->mt_dbs[FREE_DBI].md_flags != MDBX_INTEGERKEY)) { - ERROR("unexpected/invalid db-flags 0x%u for GC/FreeDB", - txn->mt_dbs[FREE_DBI].md_flags); - return MDBX_CORRUPTED; - } - return cursor_init(mc, txn, FREE_DBI); -} - __hot static bool is_already_reclaimed(const MDBX_txn *txn, txnid_t id) { const size_t len = MDBX_PNL_GETSIZE(txn->tw.lifo_reclaimed); for (size_t i = 1; i <= len; ++i) @@ -6635,7 +6626,7 @@ __hot static bool is_already_reclaimed(const MDBX_txn *txn, txnid_t id) { } static pgr_t page_alloc_slowpath(const MDBX_cursor *mc, const size_t num, - char flags) { + uint8_t flags) { #if MDBX_ENABLE_PROFGC const uint64_t monotime_before = osal_monotime(); size_t majflt_before; @@ -6706,10 +6697,10 @@ static pgr_t page_alloc_slowpath(const MDBX_cursor *mc, const size_t num, flags += MDBX_ALLOC_COALESCE; } - MDBX_cursor recur; - ret.err = gc_cursor_init(&recur, txn); - if (unlikely(ret.err != MDBX_SUCCESS)) - goto fail; + MDBX_cursor *const gc = + (MDBX_cursor *)((char *)env->me_txn0 + sizeof(MDBX_txn)); + gc->mc_txn = txn; + gc->mc_flags = 0; retry_gc_refresh_oldest:; txnid_t oldest = txn_oldest_reader(txn); @@ -6754,7 +6745,7 @@ next_gc:; #endif /* MDBX_ENABLE_PROFGC */ /* Seek first/next GC record */ - ret.err = mdbx_cursor_get(&recur, &key, NULL, op); + ret.err = mdbx_cursor_get(gc, &key, NULL, op); if (unlikely(ret.err != MDBX_SUCCESS)) { if (unlikely(ret.err != MDBX_NOTFOUND)) goto fail; @@ -6781,10 +6772,9 @@ next_gc:; /* Reading next GC record */ MDBX_val data; - MDBX_page *const mp = recur.mc_pg[recur.mc_top]; - if (unlikely( - (ret.err = node_read(&recur, page_node(mp, recur.mc_ki[recur.mc_top]), - &data, mp)) != MDBX_SUCCESS)) + MDBX_page *const mp = gc->mc_pg[gc->mc_top]; + if (unlikely((ret.err = node_read(gc, page_node(mp, gc->mc_ki[gc->mc_top]), + &data, mp)) != MDBX_SUCCESS)) goto fail; eASSERT(env, (txn->mt_flags & MDBX_TXN_FROZEN_RE) == 0); @@ -7712,7 +7702,9 @@ __cold int mdbx_env_sync_poll(MDBX_env *env) { /* Back up parent txn's cursors, then grab the originals for tracking */ static int cursor_shadow(MDBX_txn *parent, MDBX_txn *nested) { - for (int i = parent->mt_numdbs; --i >= 0;) { + tASSERT(parent, parent->mt_cursors[FREE_DBI] == nullptr); + nested->mt_cursors[FREE_DBI] = nullptr; + for (int i = parent->mt_numdbs; --i > FREE_DBI;) { nested->mt_cursors[i] = NULL; MDBX_cursor *mc = parent->mt_cursors[i]; if (mc != NULL) { @@ -7757,7 +7749,8 @@ static int cursor_shadow(MDBX_txn *parent, MDBX_txn *nested) { * * Returns 0 on success, non-zero on failure. */ static void cursors_eot(MDBX_txn *txn, const bool merge) { - for (intptr_t i = txn->mt_numdbs; --i >= 0;) { + tASSERT(txn, txn->mt_cursors[FREE_DBI] == nullptr); + for (intptr_t i = txn->mt_numdbs; --i > FREE_DBI;) { MDBX_cursor *next, *mc = txn->mt_cursors[i]; if (!mc) continue; @@ -8468,6 +8461,19 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { osal_srwlock_AcquireShared(&env->me_remap_guard); } #endif /* Windows */ + } else { + if (unlikely(txn->mt_dbs[FREE_DBI].md_flags != MDBX_INTEGERKEY)) { + ERROR("unexpected/invalid db-flags 0x%u for GC/FreeDB", + txn->mt_dbs[FREE_DBI].md_flags); + rc = MDBX_INCOMPATIBLE; + goto bailout; + } + + tASSERT(txn, txn == env->me_txn0); + MDBX_cursor *const gc = (MDBX_cursor *)((char *)txn + sizeof(MDBX_txn)); + rc = cursor_init(gc, txn, FREE_DBI); + if (rc != MDBX_SUCCESS) + goto bailout; } #if defined(MDBX_USE_VALGRIND) || defined(__SANITIZE_ADDRESS__) txn_valgrind(env, txn); @@ -9462,7 +9468,7 @@ static __inline int gcu_context_init(MDBX_txn *txn, gcu_context_t *ctx) { #if MDBX_ENABLE_BIGFOOT ctx->bigfoot = txn->mt_txnid; #endif /* MDBX_ENABLE_BIGFOOT */ - return gc_cursor_init(&ctx->cursor, txn); + return cursor_init(&ctx->cursor, txn, FREE_DBI); } static __always_inline size_t gcu_backlog_size(MDBX_txn *txn) { @@ -9543,7 +9549,7 @@ static int gcu_prepare_backlog(MDBX_txn *txn, gcu_context_t *ctx, err = gcu_clean_stored_retired(txn, ctx); if (unlikely(err != MDBX_SUCCESS)) return err; - err = page_alloc_slowpath(&ctx->cursor, (pgno_t)pages4retiredlist, + err = page_alloc_slowpath(&ctx->cursor, pages4retiredlist, MDBX_ALLOC_GC | MDBX_ALLOC_RESERVE) .err; TRACE("== after-4linear, backlog %zu, err %d", gcu_backlog_size(txn), err); @@ -14180,7 +14186,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname, } if ((flags & MDBX_RDONLY) == 0) { - const size_t tsize = sizeof(MDBX_txn), + const size_t tsize = sizeof(MDBX_txn) + sizeof(MDBX_cursor), size = tsize + env->me_maxdbs * (sizeof(MDBX_db) + sizeof(MDBX_cursor *) + sizeof(MDBX_atomic_uint32_t) + 1);