mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 17:04:13 +08:00
mdbx: fix loose/dirty bug.
Change-Id: I725b640cfc29e1c0710abb155e05d44bb7bb3cc3
This commit is contained in:
parent
f4ca6ed6b9
commit
9fd7056b4f
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
|
* Copyright 2015-2017 Leonid Yuriev <leo@yuriev.ru>
|
||||||
* and other libmdbx authors: please see AUTHORS file.
|
* and other libmdbx authors: please see AUTHORS file.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
53
src/mdbx.c
53
src/mdbx.c
@ -203,7 +203,8 @@ static bool mdbx_pnl_check(MDBX_PNL pl) {
|
|||||||
if (pl) {
|
if (pl) {
|
||||||
for (const pgno_t *ptr = pl + pl[0]; --ptr > pl;) {
|
for (const pgno_t *ptr = pl + pl[0]; --ptr > pl;) {
|
||||||
assert(MDBX_PNL_ORDERED(ptr[0], ptr[1]));
|
assert(MDBX_PNL_ORDERED(ptr[0], ptr[1]));
|
||||||
if (unlikely(MDBX_PNL_DISORDERED(ptr[0], ptr[1])))
|
assert(ptr[0] >= NUM_METAS);
|
||||||
|
if (unlikely(MDBX_PNL_DISORDERED(ptr[0], ptr[1]) || ptr[0] < NUM_METAS))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,6 +500,13 @@ static unsigned __hot mdbx_mid2l_search(MDBX_ID2L pnl, pgno_t id) {
|
|||||||
int val = 0;
|
int val = 0;
|
||||||
unsigned n = (unsigned)pnl[0].mid;
|
unsigned n = (unsigned)pnl[0].mid;
|
||||||
|
|
||||||
|
#if MDBX_DEBUG
|
||||||
|
for (const MDBX_ID2 *ptr = pnl + pnl[0].mid; --ptr > pnl;) {
|
||||||
|
assert(ptr[0].mid < ptr[1].mid);
|
||||||
|
assert(ptr[0].mid >= NUM_METAS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
unsigned pivot = n >> 1;
|
unsigned pivot = n >> 1;
|
||||||
cursor = base + pivot + 1;
|
cursor = base + pivot + 1;
|
||||||
@ -548,6 +556,14 @@ static int mdbx_mid2l_insert(MDBX_ID2L pnl, MDBX_ID2 *id) {
|
|||||||
* [in] id The ID2 to append.
|
* [in] id The ID2 to append.
|
||||||
* Returns 0 on success, -2 if the ID2L is too big. */
|
* Returns 0 on success, -2 if the ID2L is too big. */
|
||||||
static int mdbx_mid2l_append(MDBX_ID2L pnl, MDBX_ID2 *id) {
|
static int mdbx_mid2l_append(MDBX_ID2L pnl, MDBX_ID2 *id) {
|
||||||
|
#if MDBX_DEBUG
|
||||||
|
for (unsigned i = pnl[0].mid; i > 0; --i) {
|
||||||
|
assert(pnl[i].mid != id->mid);
|
||||||
|
if (unlikely(pnl[i].mid == id->mid))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Too big? */
|
/* Too big? */
|
||||||
if (unlikely(pnl[0].mid >= MDBX_PNL_UM_MAX))
|
if (unlikely(pnl[0].mid >= MDBX_PNL_UM_MAX))
|
||||||
return -2;
|
return -2;
|
||||||
@ -1035,6 +1051,9 @@ static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) {
|
|||||||
skip += pgno2bytes(env, num - 1);
|
skip += pgno2bytes(env, num - 1);
|
||||||
memset((char *)np + skip, 0, size - skip);
|
memset((char *)np + skip, 0, size - skip);
|
||||||
}
|
}
|
||||||
|
#if MDBX_DEBUG
|
||||||
|
np->mp_pgno = 0;
|
||||||
|
#endif
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED(np, size);
|
VALGRIND_MAKE_MEM_UNDEFINED(np, size);
|
||||||
np->mp_flags = 0;
|
np->mp_flags = 0;
|
||||||
np->mp_pages = num;
|
np->mp_pages = num;
|
||||||
@ -1045,6 +1064,9 @@ static MDBX_page *mdbx_page_malloc(MDBX_txn *txn, unsigned num) {
|
|||||||
* Saves single pages to a list, for future reuse.
|
* Saves single pages to a list, for future reuse.
|
||||||
* (This is not used for multi-page overflow pages.) */
|
* (This is not used for multi-page overflow pages.) */
|
||||||
static __inline void mdbx_page_free(MDBX_env *env, MDBX_page *mp) {
|
static __inline void mdbx_page_free(MDBX_env *env, MDBX_page *mp) {
|
||||||
|
#if MDBX_DEBUG
|
||||||
|
mp->mp_pgno = MAX_PAGENO;
|
||||||
|
#endif
|
||||||
mp->mp_next = env->me_dpages;
|
mp->mp_next = env->me_dpages;
|
||||||
VALGRIND_MEMPOOL_FREE(env, mp);
|
VALGRIND_MEMPOOL_FREE(env, mp);
|
||||||
env->me_dpages = mp;
|
env->me_dpages = mp;
|
||||||
@ -1067,9 +1089,9 @@ static void mdbx_dlist_free(MDBX_txn *txn) {
|
|||||||
MDBX_ID2L dl = txn->mt_rw_dirtylist;
|
MDBX_ID2L dl = txn->mt_rw_dirtylist;
|
||||||
size_t i, n = dl[0].mid;
|
size_t i, n = dl[0].mid;
|
||||||
|
|
||||||
for (i = 1; i <= n; i++) {
|
for (i = 1; i <= n; i++)
|
||||||
mdbx_dpage_free(env, dl[i].mptr);
|
mdbx_dpage_free(env, dl[i].mptr);
|
||||||
}
|
|
||||||
dl[0].mid = 0;
|
dl[0].mid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1111,6 +1133,7 @@ static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
|
|||||||
|
|
||||||
if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
|
if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
|
||||||
if (txn->mt_parent) {
|
if (txn->mt_parent) {
|
||||||
|
mdbx_cassert(mc, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0);
|
||||||
MDBX_ID2 *dl = txn->mt_rw_dirtylist;
|
MDBX_ID2 *dl = txn->mt_rw_dirtylist;
|
||||||
/* If txn has a parent,
|
/* If txn has a parent,
|
||||||
* make sure the page is in our dirty list. */
|
* make sure the page is in our dirty list. */
|
||||||
@ -2177,6 +2200,7 @@ static int mdbx_page_touch(MDBX_cursor *mc) {
|
|||||||
mc->mc_db->md_root = pgno;
|
mc->mc_db->md_root = pgno;
|
||||||
}
|
}
|
||||||
} else if (txn->mt_parent && !IS_SUBP(mp)) {
|
} else if (txn->mt_parent && !IS_SUBP(mp)) {
|
||||||
|
mdbx_tassert(txn, (txn->mt_env->me_flags & MDBX_WRITEMAP) == 0);
|
||||||
MDBX_ID2 mid, *dl = txn->mt_rw_dirtylist;
|
MDBX_ID2 mid, *dl = txn->mt_rw_dirtylist;
|
||||||
pgno = mp->mp_pgno;
|
pgno = mp->mp_pgno;
|
||||||
/* If txn has a parent, make sure the page is in our dirty list. */
|
/* If txn has a parent, make sure the page is in our dirty list. */
|
||||||
@ -3047,11 +3071,10 @@ again_on_freelist_change:
|
|||||||
!(lifo && env->me_last_reclaimed > 1)) {
|
!(lifo && env->me_last_reclaimed > 1)) {
|
||||||
/* Put loose page numbers in mt_free_pages,
|
/* Put loose page numbers in mt_free_pages,
|
||||||
* since unable to return them to me_reclaimed_pglist. */
|
* since unable to return them to me_reclaimed_pglist. */
|
||||||
MDBX_page *mp = txn->mt_loose_pages;
|
|
||||||
if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages,
|
if (unlikely((rc = mdbx_pnl_need(&txn->mt_befree_pages,
|
||||||
txn->mt_loose_count)) != 0))
|
txn->mt_loose_count)) != 0))
|
||||||
return rc;
|
return rc;
|
||||||
for (; mp; mp = NEXT_LOOSE_PAGE(mp))
|
for (MDBX_page *mp = txn->mt_loose_pages; mp; mp = NEXT_LOOSE_PAGE(mp))
|
||||||
mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno);
|
mdbx_pnl_xappend(txn->mt_befree_pages, mp->mp_pgno);
|
||||||
} else {
|
} else {
|
||||||
/* Room for loose pages + temp PNL with same */
|
/* Room for loose pages + temp PNL with same */
|
||||||
@ -3069,6 +3092,25 @@ again_on_freelist_change:
|
|||||||
mdbx_pnl_xmerge(env->me_reclaimed_pglist, loose);
|
mdbx_pnl_xmerge(env->me_reclaimed_pglist, loose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDBX_ID2L dl = txn->mt_rw_dirtylist;
|
||||||
|
for (MDBX_page *mp = txn->mt_loose_pages; mp;) {
|
||||||
|
mdbx_tassert(txn, mp->mp_pgno < txn->mt_next_pgno);
|
||||||
|
mdbx_ensure(env, mp->mp_pgno >= NUM_METAS);
|
||||||
|
|
||||||
|
unsigned s, d;
|
||||||
|
for (s = d = 0; ++s <= dl[0].mid;)
|
||||||
|
if (dl[s].mid != mp->mp_pgno)
|
||||||
|
dl[++d] = dl[s];
|
||||||
|
|
||||||
|
dl[0].mid -= 1;
|
||||||
|
mdbx_tassert(txn, dl[0].mid == d);
|
||||||
|
|
||||||
|
MDBX_page *dp = mp;
|
||||||
|
mp = NEXT_LOOSE_PAGE(mp);
|
||||||
|
if ((env->me_flags & MDBX_WRITEMAP) == 0)
|
||||||
|
mdbx_dpage_free(env, dp);
|
||||||
|
}
|
||||||
|
|
||||||
txn->mt_loose_pages = NULL;
|
txn->mt_loose_pages = NULL;
|
||||||
txn->mt_loose_count = 0;
|
txn->mt_loose_count = 0;
|
||||||
}
|
}
|
||||||
@ -3295,6 +3337,7 @@ again_on_freelist_change:
|
|||||||
mc.mc_flags |= C_RECLAIMING;
|
mc.mc_flags |= C_RECLAIMING;
|
||||||
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT);
|
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT);
|
||||||
mc.mc_flags ^= C_RECLAIMING;
|
mc.mc_flags ^= C_RECLAIMING;
|
||||||
|
mdbx_tassert(txn, mdbx_pnl_check(rpl_end));
|
||||||
mdbx_tassert(
|
mdbx_tassert(
|
||||||
txn, cleanup_reclaimed_pos ==
|
txn, cleanup_reclaimed_pos ==
|
||||||
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user