mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-01 22:34:13 +08:00
mdbx: simplify & fix mdbx_txn_keep()
and mdbx_cursor_keep()
.
1 of 2 fixes for https://github.com/erthink/libmdbx/issues/195
This commit is contained in:
parent
84b699a47c
commit
bc6a690733
63
src/core.c
63
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user