mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-06 18:54:14 +08:00
mdbx: fix wrong freeDB search.
Avoid search freeDB while tree is updating. This resolves https://github.com/leo-yuriev/libmdbx/issues/31 Bug was inherited from LMDB. Change-Id: I0b12f8d9b88bca5aa26ca27db81df9b72c6a19b7
This commit is contained in:
parent
47cc2b1c10
commit
f1edd1579a
29
src/mdbx.c
29
src/mdbx.c
@ -2109,6 +2109,10 @@ static int mdbx_page_alloc(MDBX_cursor *mc, unsigned num, MDBX_page **mp,
|
|||||||
* catch-up with itself by growing while trying to save it. */
|
* catch-up with itself by growing while trying to save it. */
|
||||||
flags &=
|
flags &=
|
||||||
~(MDBX_ALLOC_GC | MDBX_ALLOC_KICK | MDBX_COALESCE | MDBX_LIFORECLAIM);
|
~(MDBX_ALLOC_GC | MDBX_ALLOC_KICK | MDBX_COALESCE | MDBX_LIFORECLAIM);
|
||||||
|
} else if (unlikely(txn->mt_dbs[FREE_DBI].md_entries == 0)) {
|
||||||
|
/* avoid (recursive) search inside empty tree and while tree is updating,
|
||||||
|
* https://github.com/leo-yuriev/libmdbx/issues/31 */
|
||||||
|
flags &= ~MDBX_ALLOC_GC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7965,6 +7969,8 @@ int mdbx_cursor_del(MDBX_cursor *mc, unsigned flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mc->mc_db->md_entries--;
|
mc->mc_db->md_entries--;
|
||||||
|
mdbx_cassert(mc, mc->mc_db->md_entries > 0 && mc->mc_db->md_depth > 0 &&
|
||||||
|
mc->mc_db->md_root != P_INVALID);
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
|
mc->mc_xcursor->mx_cursor.mc_flags &= ~C_INITIALIZED;
|
||||||
@ -9052,6 +9058,7 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
|
|||||||
rc = mdbx_page_loose(csrc, psrc);
|
rc = mdbx_page_loose(csrc, psrc);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (IS_LEAF(psrc))
|
if (IS_LEAF(psrc))
|
||||||
csrc->mc_db->md_leaf_pages--;
|
csrc->mc_db->md_leaf_pages--;
|
||||||
else
|
else
|
||||||
@ -9089,6 +9096,10 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
|
|||||||
uint16_t depth = cdst->mc_db->md_depth;
|
uint16_t depth = cdst->mc_db->md_depth;
|
||||||
mdbx_cursor_pop(cdst);
|
mdbx_cursor_pop(cdst);
|
||||||
rc = mdbx_rebalance(cdst);
|
rc = mdbx_rebalance(cdst);
|
||||||
|
if (unlikely(rc))
|
||||||
|
return rc;
|
||||||
|
mdbx_cassert(cdst, cdst->mc_db->md_entries > 0);
|
||||||
|
|
||||||
/* Did the tree height change? */
|
/* Did the tree height change? */
|
||||||
if (depth != cdst->mc_db->md_depth)
|
if (depth != cdst->mc_db->md_depth)
|
||||||
snum += cdst->mc_db->md_depth - depth;
|
snum += cdst->mc_db->md_depth - depth;
|
||||||
@ -9096,7 +9107,7 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) {
|
|||||||
cdst->mc_snum = (uint16_t)snum;
|
cdst->mc_snum = (uint16_t)snum;
|
||||||
cdst->mc_top = (uint16_t)(snum - 1);
|
cdst->mc_top = (uint16_t)(snum - 1);
|
||||||
}
|
}
|
||||||
return rc;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the contents of a cursor.
|
/* Copy the contents of a cursor.
|
||||||
@ -9147,12 +9158,14 @@ static int mdbx_rebalance(MDBX_cursor *mc) {
|
|||||||
NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
|
NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
|
||||||
mdbx_debug("no need to rebalance page %" PRIaPGNO ", above fill threshold",
|
mdbx_debug("no need to rebalance page %" PRIaPGNO ", above fill threshold",
|
||||||
mc->mc_pg[mc->mc_top]->mp_pgno);
|
mc->mc_pg[mc->mc_top]->mp_pgno);
|
||||||
|
mdbx_cassert(mc, mc->mc_db->md_entries > 0);
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mc->mc_snum < 2) {
|
if (mc->mc_snum < 2) {
|
||||||
MDBX_page *mp = mc->mc_pg[0];
|
MDBX_page *const mp = mc->mc_pg[0];
|
||||||
unsigned nkeys = NUMKEYS(mp);
|
const unsigned nkeys = NUMKEYS(mp);
|
||||||
|
mdbx_cassert(mc, (mc->mc_db->md_entries == 0) == (nkeys == 0));
|
||||||
if (IS_SUBP(mp)) {
|
if (IS_SUBP(mp)) {
|
||||||
mdbx_debug("Can't rebalance a subpage, ignoring");
|
mdbx_debug("Can't rebalance a subpage, ignoring");
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
@ -9182,7 +9195,7 @@ static int mdbx_rebalance(MDBX_cursor *mc) {
|
|||||||
mc->mc_snum = 0;
|
mc->mc_snum = 0;
|
||||||
mc->mc_top = 0;
|
mc->mc_top = 0;
|
||||||
mc->mc_flags &= ~C_INITIALIZED;
|
mc->mc_flags &= ~C_INITIALIZED;
|
||||||
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
} else if (IS_BRANCH(mp) && nkeys == 1) {
|
||||||
int i;
|
int i;
|
||||||
mdbx_debug("collapsing root page!");
|
mdbx_debug("collapsing root page!");
|
||||||
rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
|
rc = mdbx_pnl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
|
||||||
@ -9343,12 +9356,17 @@ static int mdbx_cursor_del0(MDBX_cursor *mc) {
|
|||||||
* Other cursors adjustments were already done
|
* Other cursors adjustments were already done
|
||||||
* by mdbx_rebalance and aren't needed here. */
|
* by mdbx_rebalance and aren't needed here. */
|
||||||
if (!mc->mc_snum) {
|
if (!mc->mc_snum) {
|
||||||
|
mdbx_cassert(mc, mc->mc_db->md_entries == 0 && mc->mc_db->md_depth == 0 &&
|
||||||
|
mc->mc_db->md_root == P_INVALID);
|
||||||
mc->mc_flags |= C_DEL | C_EOF;
|
mc->mc_flags |= C_DEL | C_EOF;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp = mc->mc_pg[mc->mc_top];
|
mp = mc->mc_pg[mc->mc_top];
|
||||||
nkeys = NUMKEYS(mp);
|
nkeys = NUMKEYS(mp);
|
||||||
|
mdbx_cassert(mc, (mc->mc_db->md_entries > 0 && nkeys > 0) ||
|
||||||
|
((mc->mc_flags & C_SUB) &&
|
||||||
|
mc->mc_db->md_entries == 0 && nkeys == 0));
|
||||||
|
|
||||||
/* Adjust other cursors pointing to mp */
|
/* Adjust other cursors pointing to mp */
|
||||||
for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2 = m2->mc_next) {
|
for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2 = m2->mc_next) {
|
||||||
@ -9366,7 +9384,8 @@ static int mdbx_cursor_del0(MDBX_cursor *mc) {
|
|||||||
m3->mc_flags |= C_EOF;
|
m3->mc_flags |= C_EOF;
|
||||||
rc = MDBX_SUCCESS;
|
rc = MDBX_SUCCESS;
|
||||||
continue;
|
continue;
|
||||||
}
|
} else if (unlikely(rc != MDBX_SUCCESS))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (mc->mc_db->md_flags & MDBX_DUPSORT) {
|
if (mc->mc_db->md_flags & MDBX_DUPSORT) {
|
||||||
MDBX_node *node =
|
MDBX_node *node =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user