mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-30 11:29:19 +08:00
mdbx: minor refine freelist_save().
Change-Id: Ifed9b8d363d45d24c44c1b0a803dad34aada96d3
This commit is contained in:
parent
3ba5bebec4
commit
ad48fd54fb
@ -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.
|
||||||
@ -503,7 +503,7 @@ struct MDBX_txn {
|
|||||||
/* The list of reclaimed txns from freeDB */
|
/* The list of reclaimed txns from freeDB */
|
||||||
MDBX_TXL mt_lifo_reclaimed;
|
MDBX_TXL mt_lifo_reclaimed;
|
||||||
/* The list of pages that became unused during this transaction. */
|
/* The list of pages that became unused during this transaction. */
|
||||||
MDBX_IDL mt_free_pages;
|
MDBX_IDL mt_befree_pages;
|
||||||
/* The list of loose pages that became unused and may be reused
|
/* The list of loose pages that became unused and may be reused
|
||||||
* in this transaction, linked through NEXT_LOOSE_PAGE(page). */
|
* in this transaction, linked through NEXT_LOOSE_PAGE(page). */
|
||||||
MDBX_page *mt_loose_pages;
|
MDBX_page *mt_loose_pages;
|
||||||
|
147
src/mdbx.c
147
src/mdbx.c
@ -1091,7 +1091,7 @@ static void __cold mdbx_kill_page(MDBX_env *env, pgno_t pgno) {
|
|||||||
* to this txn's free list. */
|
* to this txn's free list. */
|
||||||
static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
|
static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
|
||||||
int loose = 0;
|
int loose = 0;
|
||||||
pgno_t pgno = mp->mp_pgno;
|
const pgno_t pgno = mp->mp_pgno;
|
||||||
MDBX_txn *txn = mc->mc_txn;
|
MDBX_txn *txn = mc->mc_txn;
|
||||||
|
|
||||||
if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
|
if ((mp->mp_flags & P_DIRTY) && mc->mc_dbi != FREE_DBI) {
|
||||||
@ -1132,7 +1132,7 @@ static int mdbx_page_loose(MDBX_cursor *mc, MDBX_page *mp) {
|
|||||||
txn->mt_loose_count++;
|
txn->mt_loose_count++;
|
||||||
mp->mp_flags |= P_LOOSE;
|
mp->mp_flags |= P_LOOSE;
|
||||||
} else {
|
} else {
|
||||||
int rc = mdbx_midl_append(&txn->mt_free_pages, pgno);
|
int rc = mdbx_midl_append(&txn->mt_befree_pages, pgno);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -2083,14 +2083,14 @@ static int mdbx_page_touch(MDBX_cursor *mc) {
|
|||||||
if (likely(np))
|
if (likely(np))
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (unlikely((rc = mdbx_midl_need(&txn->mt_free_pages, 1)) ||
|
if (unlikely((rc = mdbx_midl_need(&txn->mt_befree_pages, 1)) ||
|
||||||
(rc = mdbx_page_alloc(mc, 1, &np, MDBX_ALLOC_ALL))))
|
(rc = mdbx_page_alloc(mc, 1, &np, MDBX_ALLOC_ALL))))
|
||||||
goto fail;
|
goto fail;
|
||||||
pgno = np->mp_pgno;
|
pgno = np->mp_pgno;
|
||||||
mdbx_debug("touched db %d page %" PRIaPGNO " -> %" PRIaPGNO, DDBI(mc),
|
mdbx_debug("touched db %d page %" PRIaPGNO " -> %" PRIaPGNO, DDBI(mc),
|
||||||
mp->mp_pgno, pgno);
|
mp->mp_pgno, pgno);
|
||||||
mdbx_cassert(mc, mp->mp_pgno != pgno);
|
mdbx_cassert(mc, mp->mp_pgno != pgno);
|
||||||
mdbx_midl_xappend(txn->mt_free_pages, mp->mp_pgno);
|
mdbx_midl_xappend(txn->mt_befree_pages, mp->mp_pgno);
|
||||||
/* Update the parent page, if any, to point to the new page */
|
/* Update the parent page, if any, to point to the new page */
|
||||||
if (mc->mc_top) {
|
if (mc->mc_top) {
|
||||||
MDBX_page *parent = mc->mc_pg[mc->mc_top - 1];
|
MDBX_page *parent = mc->mc_pg[mc->mc_top - 1];
|
||||||
@ -2484,8 +2484,8 @@ static int mdbx_txn_renew0(MDBX_txn *txn, unsigned flags) {
|
|||||||
txn->mt_dirtyroom = MDBX_IDL_UM_MAX;
|
txn->mt_dirtyroom = MDBX_IDL_UM_MAX;
|
||||||
txn->mt_rw_dirtylist = env->me_dirtylist;
|
txn->mt_rw_dirtylist = env->me_dirtylist;
|
||||||
txn->mt_rw_dirtylist[0].mid = 0;
|
txn->mt_rw_dirtylist[0].mid = 0;
|
||||||
txn->mt_free_pages = env->me_free_pgs;
|
txn->mt_befree_pages = env->me_free_pgs;
|
||||||
txn->mt_free_pages[0] = 0;
|
txn->mt_befree_pages[0] = 0;
|
||||||
txn->mt_spill_pages = NULL;
|
txn->mt_spill_pages = NULL;
|
||||||
if (txn->mt_lifo_reclaimed)
|
if (txn->mt_lifo_reclaimed)
|
||||||
txn->mt_lifo_reclaimed[0] = 0;
|
txn->mt_lifo_reclaimed[0] = 0;
|
||||||
@ -2626,7 +2626,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
|
|||||||
txn->mt_dbiseqs = parent->mt_dbiseqs;
|
txn->mt_dbiseqs = parent->mt_dbiseqs;
|
||||||
txn->mt_rw_dirtylist = malloc(sizeof(MDBX_ID2) * MDBX_IDL_UM_SIZE);
|
txn->mt_rw_dirtylist = malloc(sizeof(MDBX_ID2) * MDBX_IDL_UM_SIZE);
|
||||||
if (!txn->mt_rw_dirtylist ||
|
if (!txn->mt_rw_dirtylist ||
|
||||||
!(txn->mt_free_pages = mdbx_midl_alloc(MDBX_IDL_UM_MAX))) {
|
!(txn->mt_befree_pages = mdbx_midl_alloc(MDBX_IDL_UM_MAX))) {
|
||||||
free(txn->mt_rw_dirtylist);
|
free(txn->mt_rw_dirtylist);
|
||||||
free(txn);
|
free(txn);
|
||||||
return MDBX_ENOMEM;
|
return MDBX_ENOMEM;
|
||||||
@ -2782,8 +2782,8 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
|
|||||||
txn->mt_flags = MDBX_TXN_FINISHED;
|
txn->mt_flags = MDBX_TXN_FINISHED;
|
||||||
|
|
||||||
if (!txn->mt_parent) {
|
if (!txn->mt_parent) {
|
||||||
mdbx_midl_shrink(&txn->mt_free_pages);
|
mdbx_midl_shrink(&txn->mt_befree_pages);
|
||||||
env->me_free_pgs = txn->mt_free_pages;
|
env->me_free_pgs = txn->mt_befree_pages;
|
||||||
/* me_pgstate: */
|
/* me_pgstate: */
|
||||||
env->me_reclaimed_pglist = NULL;
|
env->me_reclaimed_pglist = NULL;
|
||||||
env->me_last_reclaimed = 0;
|
env->me_last_reclaimed = 0;
|
||||||
@ -2799,7 +2799,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
|
|||||||
txn->mt_parent->mt_child = NULL;
|
txn->mt_parent->mt_child = NULL;
|
||||||
txn->mt_parent->mt_flags &= ~MDBX_TXN_HAS_CHILD;
|
txn->mt_parent->mt_flags &= ~MDBX_TXN_HAS_CHILD;
|
||||||
env->me_pgstate = ((MDBX_ntxn *)txn)->mnt_pgstate;
|
env->me_pgstate = ((MDBX_ntxn *)txn)->mnt_pgstate;
|
||||||
mdbx_midl_free(txn->mt_free_pages);
|
mdbx_midl_free(txn->mt_befree_pages);
|
||||||
mdbx_midl_free(txn->mt_spill_pages);
|
mdbx_midl_free(txn->mt_spill_pages);
|
||||||
free(txn->mt_rw_dirtylist);
|
free(txn->mt_rw_dirtylist);
|
||||||
}
|
}
|
||||||
@ -2889,8 +2889,7 @@ static int mdbx_prep_backlog(MDBX_txn *txn, MDBX_cursor *mc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Save the freelist as of this transaction to the freeDB.
|
/* Save the freelist as of this transaction to the freeDB.
|
||||||
* This changes the freelist. Keep trying until it stabilizes.
|
* This changes the freelist. Keep trying until it stabilizes. */
|
||||||
*/
|
|
||||||
static int mdbx_freelist_save(MDBX_txn *txn) {
|
static int mdbx_freelist_save(MDBX_txn *txn) {
|
||||||
/* env->me_reclaimed_pglist[] can grow and shrink during this call.
|
/* env->me_reclaimed_pglist[] can grow and shrink during this call.
|
||||||
* env->me_last_reclaimed and txn->mt_free_pages[] can only grow.
|
* env->me_last_reclaimed and txn->mt_free_pages[] can only grow.
|
||||||
@ -2898,11 +2897,11 @@ static int mdbx_freelist_save(MDBX_txn *txn) {
|
|||||||
MDBX_cursor mc;
|
MDBX_cursor mc;
|
||||||
MDBX_env *env = txn->mt_env;
|
MDBX_env *env = txn->mt_env;
|
||||||
int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1;
|
int rc, maxfree_1pg = env->me_maxfree_1pg, more = 1;
|
||||||
txnid_t pglast = 0, head_id = 0;
|
txnid_t cleanup_reclaimed_id = 0, head_id = 0;
|
||||||
pgno_t freecnt = 0, *free_pgs, *mop;
|
pgno_t befree_count = 0, *mop;
|
||||||
ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
|
ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
|
||||||
unsigned cleanup_idx = 0, refill_idx = 0;
|
unsigned cleanup_reclaimed_pos = 0, refill_reclaimed_pos = 0;
|
||||||
const int lifo = (env->me_flags & MDBX_LIFORECLAIM) != 0;
|
const bool lifo = (env->me_flags & MDBX_LIFORECLAIM) != 0;
|
||||||
|
|
||||||
mdbx_cursor_init(&mc, txn, FREE_DBI, NULL);
|
mdbx_cursor_init(&mc, txn, FREE_DBI, NULL);
|
||||||
|
|
||||||
@ -2911,39 +2910,38 @@ static int mdbx_freelist_save(MDBX_txn *txn) {
|
|||||||
? SSIZE_MAX
|
? SSIZE_MAX
|
||||||
: maxfree_1pg;
|
: maxfree_1pg;
|
||||||
|
|
||||||
again:
|
again_on_freelist_change:
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Come back here after each Put() in case freelist changed */
|
/* Come back here after each Put() in case freelist changed */
|
||||||
MDBX_val key, data;
|
MDBX_val key, data;
|
||||||
pgno_t *pgs;
|
|
||||||
ssize_t j;
|
ssize_t j;
|
||||||
|
|
||||||
if (!lifo) {
|
if (!lifo) {
|
||||||
/* If using records from freeDB which we have not yet
|
/* If using records from freeDB which we have not yet deleted,
|
||||||
* deleted, delete them and any we reserved for me_reclaimed_pglist. */
|
* now delete them and any we reserved for me_reclaimed_pglist. */
|
||||||
while (pglast < env->me_last_reclaimed) {
|
while (cleanup_reclaimed_id < env->me_last_reclaimed) {
|
||||||
rc = mdbx_cursor_first(&mc, &key, NULL);
|
rc = mdbx_cursor_first(&mc, &key, NULL);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
rc = mdbx_prep_backlog(txn, &mc);
|
rc = mdbx_prep_backlog(txn, &mc);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
pglast = head_id = *(txnid_t *)key.iov_base;
|
cleanup_reclaimed_id = head_id = *(txnid_t *)key.iov_base;
|
||||||
total_room = head_room = 0;
|
total_room = head_room = 0;
|
||||||
more = 1;
|
more = 1;
|
||||||
mdbx_tassert(txn, pglast <= env->me_last_reclaimed);
|
mdbx_tassert(txn, cleanup_reclaimed_id <= env->me_last_reclaimed);
|
||||||
mc.mc_flags |= C_RECLAIMING;
|
mc.mc_flags |= C_RECLAIMING;
|
||||||
rc = mdbx_cursor_del(&mc, 0);
|
rc = mdbx_cursor_del(&mc, 0);
|
||||||
mc.mc_flags &= ~C_RECLAIMING;
|
mc.mc_flags ^= C_RECLAIMING;
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
} else if (txn->mt_lifo_reclaimed) {
|
} else if (txn->mt_lifo_reclaimed) {
|
||||||
/* LY: cleanup reclaimed records. */
|
/* LY: cleanup reclaimed records. */
|
||||||
while (cleanup_idx < txn->mt_lifo_reclaimed[0]) {
|
while (cleanup_reclaimed_pos < txn->mt_lifo_reclaimed[0]) {
|
||||||
pglast = txn->mt_lifo_reclaimed[++cleanup_idx];
|
cleanup_reclaimed_id = txn->mt_lifo_reclaimed[++cleanup_reclaimed_pos];
|
||||||
key.iov_base = &pglast;
|
key.iov_base = &cleanup_reclaimed_id;
|
||||||
key.iov_len = sizeof(pglast);
|
key.iov_len = sizeof(cleanup_reclaimed_id);
|
||||||
rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET);
|
rc = mdbx_cursor_get(&mc, &key, NULL, MDBX_SET);
|
||||||
if (likely(rc != MDBX_NOTFOUND)) {
|
if (likely(rc != MDBX_NOTFOUND)) {
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
@ -2953,7 +2951,7 @@ again:
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
mc.mc_flags |= C_RECLAIMING;
|
mc.mc_flags |= C_RECLAIMING;
|
||||||
rc = mdbx_cursor_del(&mc, 0);
|
rc = mdbx_cursor_del(&mc, 0);
|
||||||
mc.mc_flags &= ~C_RECLAIMING;
|
mc.mc_flags ^= C_RECLAIMING;
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
@ -2964,47 +2962,47 @@ again:
|
|||||||
/* Put loose page numbers in mt_free_pages, since
|
/* Put loose page numbers in mt_free_pages, since
|
||||||
* we may be unable to return them to me_reclaimed_pglist. */
|
* we may be unable to return them to me_reclaimed_pglist. */
|
||||||
MDBX_page *mp = txn->mt_loose_pages;
|
MDBX_page *mp = txn->mt_loose_pages;
|
||||||
if (unlikely((rc = mdbx_midl_need(&txn->mt_free_pages,
|
if (unlikely((rc = mdbx_midl_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 (; mp; mp = NEXT_LOOSE_PAGE(mp))
|
||||||
mdbx_midl_xappend(txn->mt_free_pages, mp->mp_pgno);
|
mdbx_midl_xappend(txn->mt_befree_pages, mp->mp_pgno);
|
||||||
txn->mt_loose_pages = NULL;
|
txn->mt_loose_pages = NULL;
|
||||||
txn->mt_loose_count = 0;
|
txn->mt_loose_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the IDL of pages freed by this txn, to a single record */
|
/* Save the IDL of pages freed by this txn, to a single record */
|
||||||
if (freecnt < txn->mt_free_pages[0]) {
|
if (befree_count < txn->mt_befree_pages[0]) {
|
||||||
if (unlikely(!freecnt)) {
|
if (unlikely(!befree_count)) {
|
||||||
/* Make sure last page of freeDB is touched and on freelist */
|
/* Make sure last page of freeDB is touched and on freelist */
|
||||||
rc = mdbx_page_search(&mc, NULL, MDBX_PS_LAST | MDBX_PS_MODIFY);
|
rc = mdbx_page_search(&mc, NULL, MDBX_PS_LAST | MDBX_PS_MODIFY);
|
||||||
if (unlikely(rc && rc != MDBX_NOTFOUND))
|
if (unlikely(rc && rc != MDBX_NOTFOUND))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
free_pgs = txn->mt_free_pages;
|
pgno_t *befree_pages = txn->mt_befree_pages;
|
||||||
/* Write to last page of freeDB */
|
/* Write to last page of freeDB */
|
||||||
key.iov_len = sizeof(txn->mt_txnid);
|
key.iov_len = sizeof(txn->mt_txnid);
|
||||||
key.iov_base = &txn->mt_txnid;
|
key.iov_base = &txn->mt_txnid;
|
||||||
do {
|
do {
|
||||||
freecnt = free_pgs[0];
|
befree_count = befree_pages[0];
|
||||||
data.iov_len = MDBX_IDL_SIZEOF(free_pgs);
|
data.iov_len = MDBX_IDL_SIZEOF(befree_pages);
|
||||||
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
|
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
/* Retry if mt_free_pages[] grew during the Put() */
|
/* Retry if mt_free_pages[] grew during the Put() */
|
||||||
free_pgs = txn->mt_free_pages;
|
befree_pages = txn->mt_befree_pages;
|
||||||
} while (freecnt < free_pgs[0]);
|
} while (befree_count < befree_pages[0]);
|
||||||
|
|
||||||
mdbx_midl_sort(free_pgs);
|
mdbx_midl_sort(befree_pages);
|
||||||
memcpy(data.iov_base, free_pgs, data.iov_len);
|
memcpy(data.iov_base, befree_pages, data.iov_len);
|
||||||
|
|
||||||
if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) {
|
if (mdbx_debug_enabled(MDBX_DBG_EXTRA)) {
|
||||||
unsigned i = free_pgs[0];
|
unsigned i = (unsigned)befree_pages[0];
|
||||||
mdbx_debug_extra("IDL write txn %" PRIaTXN " root %" PRIaPGNO
|
mdbx_debug_extra("IDL write txn %" PRIaTXN " root %" PRIaPGNO
|
||||||
" num %u, IDL",
|
" num %u, IDL",
|
||||||
txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i);
|
txn->mt_txnid, txn->mt_dbs[FREE_DBI].md_root, i);
|
||||||
for (; i; i--)
|
for (; i; i--)
|
||||||
mdbx_debug_extra_print(" %" PRIaPGNO "", free_pgs[i]);
|
mdbx_debug_extra_print(" %" PRIaPGNO "", befree_pages[i]);
|
||||||
mdbx_debug_extra_print("\n");
|
mdbx_debug_extra_print("\n");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -3013,8 +3011,8 @@ again:
|
|||||||
mop = env->me_reclaimed_pglist;
|
mop = env->me_reclaimed_pglist;
|
||||||
mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count;
|
mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count;
|
||||||
|
|
||||||
if (mop_len && refill_idx == 0)
|
if (mop_len && refill_reclaimed_pos == 0)
|
||||||
refill_idx = 1;
|
refill_reclaimed_pos = 1;
|
||||||
|
|
||||||
/* Reserve records for me_reclaimed_pglist[]. Split it if multi-page,
|
/* Reserve records for me_reclaimed_pglist[]. Split it if multi-page,
|
||||||
* to avoid searching freeDB for a page range. Use keys in
|
* to avoid searching freeDB for a page range. Use keys in
|
||||||
@ -3025,12 +3023,12 @@ again:
|
|||||||
} else if (head_room >= maxfree_1pg && head_id > 1) {
|
} else if (head_room >= maxfree_1pg && head_id > 1) {
|
||||||
/* Keep current record (overflow page), add a new one */
|
/* Keep current record (overflow page), add a new one */
|
||||||
head_id--;
|
head_id--;
|
||||||
refill_idx++;
|
refill_reclaimed_pos++;
|
||||||
head_room = 0;
|
head_room = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lifo) {
|
if (lifo) {
|
||||||
if (refill_idx >
|
if (refill_reclaimed_pos >
|
||||||
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0)) {
|
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0)) {
|
||||||
/* LY: need just a txn-id for save page list. */
|
/* LY: need just a txn-id for save page list. */
|
||||||
rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK);
|
rc = mdbx_page_alloc(&mc, 0, NULL, MDBX_ALLOC_GC | MDBX_ALLOC_KICK);
|
||||||
@ -3062,9 +3060,9 @@ again:
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
--env->me_last_reclaimed;
|
--env->me_last_reclaimed;
|
||||||
/* LY: note that freeDB cleanup is not needed. */
|
/* LY: note that freeDB cleanup is not needed. */
|
||||||
++cleanup_idx;
|
++cleanup_reclaimed_pos;
|
||||||
}
|
}
|
||||||
head_id = txn->mt_lifo_reclaimed[refill_idx];
|
head_id = txn->mt_lifo_reclaimed[refill_reclaimed_pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (Re)write {key = head_id, IDL length = head_room} */
|
/* (Re)write {key = head_id, IDL length = head_room} */
|
||||||
@ -3086,17 +3084,19 @@ again:
|
|||||||
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
|
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_RESERVE);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
|
|
||||||
/* IDL is initially empty, zero out at least the length */
|
/* IDL is initially empty, zero out at least the length */
|
||||||
pgs = (pgno_t *)data.iov_base;
|
pgno_t *pgs = (pgno_t *)data.iov_base;
|
||||||
j = head_room > clean_limit ? head_room : 0;
|
j = head_room > clean_limit ? head_room : 0;
|
||||||
do {
|
do {
|
||||||
pgs[j] = 0;
|
pgs[j] = 0;
|
||||||
} while (--j >= 0);
|
} while (--j >= 0);
|
||||||
total_room += head_room;
|
total_room += head_room;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mdbx_tassert(txn,
|
mdbx_tassert(txn,
|
||||||
cleanup_idx ==
|
cleanup_reclaimed_pos ==
|
||||||
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
||||||
|
|
||||||
/* Return loose page numbers to me_reclaimed_pglist, though usually none are
|
/* Return loose page numbers to me_reclaimed_pglist, though usually none are
|
||||||
@ -3144,8 +3144,9 @@ again:
|
|||||||
mdbx_tassert(txn, id <= env->me_last_reclaimed);
|
mdbx_tassert(txn, id <= env->me_last_reclaimed);
|
||||||
} else {
|
} else {
|
||||||
mdbx_tassert(txn,
|
mdbx_tassert(txn,
|
||||||
refill_idx > 0 && refill_idx <= txn->mt_lifo_reclaimed[0]);
|
refill_reclaimed_pos > 0 &&
|
||||||
id = txn->mt_lifo_reclaimed[refill_idx--];
|
refill_reclaimed_pos <= txn->mt_lifo_reclaimed[0]);
|
||||||
|
id = txn->mt_lifo_reclaimed[refill_reclaimed_pos--];
|
||||||
key.iov_base = &id;
|
key.iov_base = &id;
|
||||||
key.iov_len = sizeof(id);
|
key.iov_len = sizeof(id);
|
||||||
rc = mdbx_cursor_get(&mc, &key, &data, MDBX_SET);
|
rc = mdbx_cursor_get(&mc, &key, &data, MDBX_SET);
|
||||||
@ -3153,7 +3154,7 @@ again:
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
mdbx_tassert(
|
mdbx_tassert(
|
||||||
txn, cleanup_idx ==
|
txn, cleanup_reclaimed_pos ==
|
||||||
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
||||||
|
|
||||||
len = (ssize_t)(data.iov_len / sizeof(pgno_t)) - 1;
|
len = (ssize_t)(data.iov_len / sizeof(pgno_t)) - 1;
|
||||||
@ -3169,7 +3170,7 @@ again:
|
|||||||
mop[0] = (pgno_t)len;
|
mop[0] = (pgno_t)len;
|
||||||
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT);
|
rc = mdbx_cursor_put(&mc, &key, &data, MDBX_CURRENT);
|
||||||
mdbx_tassert(
|
mdbx_tassert(
|
||||||
txn, cleanup_idx ==
|
txn, cleanup_reclaimed_pos ==
|
||||||
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
(txn->mt_lifo_reclaimed ? txn->mt_lifo_reclaimed[0] : 0));
|
||||||
mop[0] = save;
|
mop[0] = save;
|
||||||
if (unlikely(rc || (mop_len -= len) == 0))
|
if (unlikely(rc || (mop_len -= len) == 0))
|
||||||
@ -3185,16 +3186,17 @@ again:
|
|||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
if (txn->mt_lifo_reclaimed) {
|
if (txn->mt_lifo_reclaimed) {
|
||||||
mdbx_tassert(txn, rc || cleanup_idx == txn->mt_lifo_reclaimed[0]);
|
mdbx_tassert(txn, rc || cleanup_reclaimed_pos == txn->mt_lifo_reclaimed[0]);
|
||||||
if (rc == 0 && cleanup_idx != txn->mt_lifo_reclaimed[0]) {
|
if (rc == MDBX_SUCCESS &&
|
||||||
mdbx_tassert(txn, cleanup_idx < txn->mt_lifo_reclaimed[0]);
|
cleanup_reclaimed_pos != txn->mt_lifo_reclaimed[0]) {
|
||||||
/* LY: zeroed cleanup_idx to force cleanup & refill created freeDB
|
mdbx_tassert(txn, cleanup_reclaimed_pos < txn->mt_lifo_reclaimed[0]);
|
||||||
* records. */
|
/* LY: zeroed cleanup_idx to force cleanup
|
||||||
cleanup_idx = 0;
|
* and refill created freeDB records. */
|
||||||
|
cleanup_reclaimed_pos = 0;
|
||||||
/* LY: restart filling */
|
/* LY: restart filling */
|
||||||
total_room = head_room = refill_idx = 0;
|
total_room = head_room = refill_reclaimed_pos = 0;
|
||||||
more = 1;
|
more = 1;
|
||||||
goto again;
|
goto again_on_freelist_change;
|
||||||
}
|
}
|
||||||
txn->mt_lifo_reclaimed[0] = 0;
|
txn->mt_lifo_reclaimed[0] = 0;
|
||||||
if (txn != env->me_txn0) {
|
if (txn != env->me_txn0) {
|
||||||
@ -3365,10 +3367,10 @@ int mdbx_txn_commit(MDBX_txn *txn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Append our free list to parent's */
|
/* Append our free list to parent's */
|
||||||
rc = mdbx_midl_append_list(&parent->mt_free_pages, txn->mt_free_pages);
|
rc = mdbx_midl_append_list(&parent->mt_befree_pages, txn->mt_befree_pages);
|
||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto fail;
|
goto fail;
|
||||||
mdbx_midl_free(txn->mt_free_pages);
|
mdbx_midl_free(txn->mt_befree_pages);
|
||||||
/* Failures after this must either undo the changes
|
/* Failures after this must either undo the changes
|
||||||
* to the parent or set MDBX_TXN_ERROR in the parent. */
|
* to the parent or set MDBX_TXN_ERROR in the parent. */
|
||||||
|
|
||||||
@ -3536,7 +3538,7 @@ int mdbx_txn_commit(MDBX_txn *txn) {
|
|||||||
|
|
||||||
mdbx_midl_free(env->me_reclaimed_pglist);
|
mdbx_midl_free(env->me_reclaimed_pglist);
|
||||||
env->me_reclaimed_pglist = NULL;
|
env->me_reclaimed_pglist = NULL;
|
||||||
mdbx_midl_shrink(&txn->mt_free_pages);
|
mdbx_midl_shrink(&txn->mt_befree_pages);
|
||||||
|
|
||||||
if (mdbx_audit_enabled())
|
if (mdbx_audit_enabled())
|
||||||
mdbx_audit(txn);
|
mdbx_audit(txn);
|
||||||
@ -5730,7 +5732,7 @@ static int mdbx_ovpage_free(MDBX_cursor *mc, MDBX_page *mp) {
|
|||||||
mop[j--] = pg++;
|
mop[j--] = pg++;
|
||||||
mop[0] += ovpages;
|
mop[0] += ovpages;
|
||||||
} else {
|
} else {
|
||||||
rc = mdbx_midl_append_range(&txn->mt_free_pages, pg, ovpages);
|
rc = mdbx_midl_append_range(&txn->mt_befree_pages, pg, ovpages);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -8363,7 +8365,7 @@ static int mdbx_rebalance(MDBX_cursor *mc) {
|
|||||||
mc->mc_db->md_root = P_INVALID;
|
mc->mc_db->md_root = P_INVALID;
|
||||||
mc->mc_db->md_depth = 0;
|
mc->mc_db->md_depth = 0;
|
||||||
mc->mc_db->md_leaf_pages = 0;
|
mc->mc_db->md_leaf_pages = 0;
|
||||||
rc = mdbx_midl_append(&mc->mc_txn->mt_free_pages, mp->mp_pgno);
|
rc = mdbx_midl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
/* Adjust cursors pointing to mp */
|
/* Adjust cursors pointing to mp */
|
||||||
@ -8391,7 +8393,7 @@ static int mdbx_rebalance(MDBX_cursor *mc) {
|
|||||||
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
||||||
int i;
|
int i;
|
||||||
mdbx_debug("collapsing root page!");
|
mdbx_debug("collapsing root page!");
|
||||||
rc = mdbx_midl_append(&mc->mc_txn->mt_free_pages, mp->mp_pgno);
|
rc = mdbx_midl_append(&mc->mc_txn->mt_befree_pages, mp->mp_pgno);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
return rc;
|
return rc;
|
||||||
mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
|
mc->mc_db->md_root = NODEPGNO(NODEPTR(mp, 0));
|
||||||
@ -10060,7 +10062,8 @@ static int mdbx_drop0(MDBX_cursor *mc, int subs) {
|
|||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto done;
|
goto done;
|
||||||
mdbx_cassert(mc, IS_OVERFLOW(omp));
|
mdbx_cassert(mc, IS_OVERFLOW(omp));
|
||||||
rc = mdbx_midl_append_range(&txn->mt_free_pages, pg, omp->mp_pages);
|
rc = mdbx_midl_append_range(&txn->mt_befree_pages, pg,
|
||||||
|
omp->mp_pages);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto done;
|
goto done;
|
||||||
mc->mc_db->md_overflow_pages -= omp->mp_pages;
|
mc->mc_db->md_overflow_pages -= omp->mp_pages;
|
||||||
@ -10076,14 +10079,14 @@ static int mdbx_drop0(MDBX_cursor *mc, int subs) {
|
|||||||
if (!subs && !mc->mc_db->md_overflow_pages)
|
if (!subs && !mc->mc_db->md_overflow_pages)
|
||||||
goto pop;
|
goto pop;
|
||||||
} else {
|
} else {
|
||||||
if (unlikely((rc = mdbx_midl_need(&txn->mt_free_pages, n)) != 0))
|
if (unlikely((rc = mdbx_midl_need(&txn->mt_befree_pages, n)) != 0))
|
||||||
goto done;
|
goto done;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
pgno_t pg;
|
pgno_t pg;
|
||||||
ni = NODEPTR(mp, i);
|
ni = NODEPTR(mp, i);
|
||||||
pg = NODEPGNO(ni);
|
pg = NODEPGNO(ni);
|
||||||
/* free it */
|
/* free it */
|
||||||
mdbx_midl_xappend(txn->mt_free_pages, pg);
|
mdbx_midl_xappend(txn->mt_befree_pages, pg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mc->mc_top)
|
if (!mc->mc_top)
|
||||||
@ -10106,7 +10109,7 @@ static int mdbx_drop0(MDBX_cursor *mc, int subs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* free it */
|
/* free it */
|
||||||
rc = mdbx_midl_append(&txn->mt_free_pages, mc->mc_db->md_root);
|
rc = mdbx_midl_append(&txn->mt_befree_pages, mc->mc_db->md_root);
|
||||||
done:
|
done:
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
txn->mt_flags |= MDBX_TXN_ERROR;
|
txn->mt_flags |= MDBX_TXN_ERROR;
|
||||||
|
Loading…
Reference in New Issue
Block a user