From bc6a69073357c3bc9c4bde690da0c56f6002eada Mon Sep 17 00:00:00 2001 From: Leonid Yuriev Date: Thu, 20 May 2021 12:29:59 +0300 Subject: [PATCH] mdbx: simplify & fix `mdbx_txn_keep()` and `mdbx_cursor_keep()`. 1 of 2 fixes for https://github.com/erthink/libmdbx/issues/195 --- src/core.c | 63 ++++++++++++++++-------------------------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/src/core.c b/src/core.c index 8ae47b79..1afd3e01 100644 --- a/src/core.c +++ b/src/core.c @@ -4976,58 +4976,33 @@ static int spill_page(MDBX_txn *txn, struct mdbx_iov_ctx *ctx, MDBX_page *dp, * Returns the number of pages marked as unspillable. */ static unsigned mdbx_cursor_keep(MDBX_txn *txn, MDBX_cursor *mc) { unsigned keep = 0; - if (!(mc->mc_flags & C_INITIALIZED)) - return keep; - -loop:; - const MDBX_page *mp = NULL; - for (unsigned i = 0; i < mc->mc_snum; i++) { - mp = mc->mc_pg[i]; - if (IS_MODIFIABLE(txn, mp)) { - unsigned const n = mdbx_dpl_search(txn, mp->mp_pgno); - if (txn->tw.dirtylist->items[n].pgno == mp->mp_pgno && - txn->tw.dirtylist->items[n].lru != txn->tw.dirtylru) { - txn->tw.dirtylist->items[n].lru = txn->tw.dirtylru; - keep++; + while (mc->mc_flags & C_INITIALIZED) { + for (unsigned i = 0; i < mc->mc_snum; i++) { + const MDBX_page *mp = mc->mc_pg[i]; + if (IS_MODIFIABLE(txn, mp) && !IS_SUBP(mp)) { + unsigned const n = mdbx_dpl_search(txn, mp->mp_pgno); + if (txn->tw.dirtylist->items[n].pgno == mp->mp_pgno && + txn->tw.dirtylist->items[n].lru != txn->tw.dirtylru) { + txn->tw.dirtylist->items[n].lru = txn->tw.dirtylru; + keep++; + } } } - } - if (!(mp && IS_LEAF(mp))) - return keep; - - /* Proceed to mx if it is at a sub-database */ - MDBX_xcursor *mx = mc->mc_xcursor; - if (!(mx && (mx->mx_cursor.mc_flags & C_INITIALIZED))) - return keep; - - const unsigned nkeys = page_numkeys(mp); - unsigned ki = mc->mc_ki[mc->mc_top]; - mdbx_cassert(mc, nkeys > 0 && - (ki < nkeys || - (ki == nkeys && (mx->mx_cursor.mc_flags & C_EOF)))); - ki -= ki >= nkeys; - if ((node_flags(page_node(mp, ki)) & F_SUBDATA)) { - mc = &mx->mx_cursor; - goto loop; + if (!mc->mc_xcursor) + break; + mc = &mc->mc_xcursor->mx_cursor; } return keep; } static unsigned mdbx_txn_keep(MDBX_txn *txn, MDBX_cursor *m0) { unsigned keep = m0 ? mdbx_cursor_keep(txn, m0) : 0; - - for (unsigned i = FREE_DBI; i < txn->mt_numdbs; ++i) { - const pgno_t pgno = txn->mt_dbs[i].md_root; - if ((txn->mt_dbistate[i] & DBI_DIRTY) && pgno != P_INVALID) { - unsigned const n = mdbx_dpl_search(txn, pgno); - if (likely(txn->tw.dirtylist->items[n].pgno == pgno)) { - txn->tw.dirtylist->items[n].lru = txn->tw.dirtylru; - for (MDBX_cursor *mc = txn->tw.cursors[i]; mc; mc = mc->mc_next) - if (mc != m0) - keep += mdbx_cursor_keep(txn, mc); - } - } - } + for (unsigned i = FREE_DBI; i < txn->mt_numdbs; ++i) + if (F_ISSET(txn->mt_dbistate[i], DBI_DIRTY | DBI_VALID) && + txn->mt_dbs[i].md_root != P_INVALID) + for (MDBX_cursor *mc = txn->tw.cursors[i]; mc; mc = mc->mc_next) + if (mc != m0) + keep += mdbx_cursor_keep(txn, mc); return keep; }