mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-21 21:58:20 +08:00
mdbx: cleanup freelist_save().
Change-Id: I552e6d7edac61e66b8954f6b58485d6b07194ab5
This commit is contained in:
parent
1babb0a4f7
commit
4fa4129add
91
src/mdbx.c
91
src/mdbx.c
@ -2896,25 +2896,24 @@ static int mdbx_freelist_save(MDBX_txn *txn) {
|
|||||||
* Page numbers cannot disappear from txn->mt_free_pages[]. */
|
* Page numbers cannot disappear from txn->mt_free_pages[]. */
|
||||||
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, more = 1;
|
||||||
txnid_t cleanup_reclaimed_id = 0, head_id = 0;
|
txnid_t cleanup_reclaimed_id = 0, head_id = 0;
|
||||||
pgno_t befree_count = 0, *mop;
|
pgno_t befree_count = 0;
|
||||||
ssize_t head_room = 0, total_room = 0, mop_len, clean_limit;
|
ssize_t head_room = 0, total_room = 0;
|
||||||
unsigned cleanup_reclaimed_pos = 0, refill_reclaimed_pos = 0;
|
unsigned cleanup_reclaimed_pos = 0, refill_reclaimed_pos = 0;
|
||||||
const bool 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);
|
||||||
|
|
||||||
/* MDBX_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */
|
/* MDBX_RESERVE cancels meminit in ovpage malloc (when no WRITEMAP) */
|
||||||
clean_limit = (env->me_flags & (MDBX_NOMEMINIT | MDBX_WRITEMAP))
|
const ssize_t clean_limit = (env->me_flags & (MDBX_NOMEMINIT | MDBX_WRITEMAP))
|
||||||
? SSIZE_MAX
|
? SSIZE_MAX
|
||||||
: maxfree_1pg;
|
: env->me_maxfree_1pg;
|
||||||
|
|
||||||
again_on_freelist_change:
|
again_on_freelist_change:
|
||||||
for (;;) {
|
while (1) {
|
||||||
/* 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;
|
||||||
ssize_t j;
|
|
||||||
|
|
||||||
if (!lifo) {
|
if (!lifo) {
|
||||||
/* If using records from freeDB which we have not yet deleted,
|
/* If using records from freeDB which we have not yet deleted,
|
||||||
@ -3009,19 +3008,19 @@ again_on_freelist_change:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mop = env->me_reclaimed_pglist;
|
const ssize_t rpl_len =
|
||||||
mop_len = (mop ? mop[0] : 0) + txn->mt_loose_count;
|
(env->me_reclaimed_pglist ? env->me_reclaimed_pglist[0] : 0) +
|
||||||
|
txn->mt_loose_count;
|
||||||
if (mop_len && refill_reclaimed_pos == 0)
|
if (rpl_len && refill_reclaimed_pos == 0)
|
||||||
refill_reclaimed_pos = 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
|
||||||
* range [1,me_last_reclaimed]: Smaller than txnid of oldest reader. */
|
* range [1,me_last_reclaimed]: Smaller than txnid of oldest reader. */
|
||||||
if (total_room >= mop_len) {
|
if (total_room >= rpl_len) {
|
||||||
if (total_room == mop_len || --more < 0)
|
if (total_room == rpl_len || --more < 0)
|
||||||
break;
|
break;
|
||||||
} else if (head_room >= maxfree_1pg && head_id > 1) {
|
} else if (head_room >= env->me_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_reclaimed_pos++;
|
refill_reclaimed_pos++;
|
||||||
@ -3068,12 +3067,12 @@ again_on_freelist_change:
|
|||||||
|
|
||||||
/* (Re)write {key = head_id, IDL length = head_room} */
|
/* (Re)write {key = head_id, IDL length = head_room} */
|
||||||
total_room -= head_room;
|
total_room -= head_room;
|
||||||
head_room = mop_len - total_room;
|
head_room = rpl_len - total_room;
|
||||||
if (head_room > maxfree_1pg && head_id > 1) {
|
if (head_room > env->me_maxfree_1pg && head_id > 1) {
|
||||||
/* Overflow multi-page for part of me_reclaimed_pglist */
|
/* Overflow multi-page for part of me_reclaimed_pglist */
|
||||||
head_room /= (head_id < INT16_MAX) ? (pgno_t)head_id
|
head_room /= (head_id < INT16_MAX) ? (pgno_t)head_id
|
||||||
: INT16_MAX; /* amortize page sizes */
|
: INT16_MAX; /* amortize page sizes */
|
||||||
head_room += maxfree_1pg - head_room % (maxfree_1pg + 1);
|
head_room += env->me_maxfree_1pg - head_room % (env->me_maxfree_1pg + 1);
|
||||||
} else if (head_room < 0) {
|
} else if (head_room < 0) {
|
||||||
/* Rare case, not bothering to delete this record */
|
/* Rare case, not bothering to delete this record */
|
||||||
head_room = 0;
|
head_room = 0;
|
||||||
@ -3088,10 +3087,10 @@ again_on_freelist_change:
|
|||||||
|
|
||||||
/* IDL is initially empty, zero out at least the length */
|
/* IDL is initially empty, zero out at least the length */
|
||||||
pgno_t *pgs = (pgno_t *)data.iov_base;
|
pgno_t *pgs = (pgno_t *)data.iov_base;
|
||||||
j = head_room > clean_limit ? head_room : 0;
|
ssize_t i = head_room > clean_limit ? head_room : 0;
|
||||||
do {
|
do {
|
||||||
pgs[j] = 0;
|
pgs[i] = 0;
|
||||||
} while (--j >= 0);
|
} while (--i >= 0);
|
||||||
total_room += head_room;
|
total_room += head_room;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -3103,43 +3102,40 @@ again_on_freelist_change:
|
|||||||
/* Return loose page numbers to me_reclaimed_pglist, though usually none are
|
/* Return loose page numbers to me_reclaimed_pglist, though usually none are
|
||||||
* left at this point. The pages themselves remain in dirtylist. */
|
* left at this point. The pages themselves remain in dirtylist. */
|
||||||
if (txn->mt_loose_pages) {
|
if (txn->mt_loose_pages) {
|
||||||
MDBX_page *mp = txn->mt_loose_pages;
|
|
||||||
unsigned count = txn->mt_loose_count;
|
|
||||||
MDBX_IDL loose;
|
|
||||||
/* Room for loose pages + temp IDL with same */
|
/* Room for loose pages + temp IDL with same */
|
||||||
if ((rc = mdbx_midl_need(&env->me_reclaimed_pglist, 2 * count + 1)) != 0)
|
if ((rc = mdbx_midl_need(&env->me_reclaimed_pglist,
|
||||||
|
2 * txn->mt_loose_count + 1)) != 0)
|
||||||
goto bailout;
|
goto bailout;
|
||||||
mop = env->me_reclaimed_pglist;
|
MDBX_IDL loose = env->me_reclaimed_pglist +
|
||||||
loose = mop + MDBX_IDL_ALLOCLEN(mop) - count;
|
MDBX_IDL_ALLOCLEN(env->me_reclaimed_pglist) -
|
||||||
for (count = 0; mp; mp = NEXT_LOOSE_PAGE(mp))
|
txn->mt_loose_count;
|
||||||
|
unsigned count = 0;
|
||||||
|
for (MDBX_page *mp = txn->mt_loose_pages; mp; mp = NEXT_LOOSE_PAGE(mp))
|
||||||
loose[++count] = mp->mp_pgno;
|
loose[++count] = mp->mp_pgno;
|
||||||
loose[0] = count;
|
loose[0] = count;
|
||||||
mdbx_midl_sort(loose);
|
mdbx_midl_sort(loose);
|
||||||
mdbx_midl_xmerge(mop, loose);
|
mdbx_midl_xmerge(env->me_reclaimed_pglist, loose);
|
||||||
txn->mt_loose_pages = NULL;
|
txn->mt_loose_pages = NULL;
|
||||||
txn->mt_loose_count = 0;
|
txn->mt_loose_count = 0;
|
||||||
mop_len = mop[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in the reserved me_reclaimed_pglist records */
|
/* Fill in the reserved me_reclaimed_pglist records */
|
||||||
rc = MDBX_SUCCESS;
|
rc = MDBX_SUCCESS;
|
||||||
if (mop_len) {
|
if (env->me_reclaimed_pglist && env->me_reclaimed_pglist[0]) {
|
||||||
MDBX_val key, data;
|
MDBX_val key, data;
|
||||||
key.iov_len = data.iov_len = 0; /* avoid MSVC warning */
|
key.iov_len = data.iov_len = 0; /* avoid MSVC warning */
|
||||||
key.iov_base = data.iov_base = NULL;
|
key.iov_base = data.iov_base = NULL;
|
||||||
|
|
||||||
mop += mop_len;
|
size_t rpl_left = env->me_reclaimed_pglist[0];
|
||||||
|
pgno_t *rpl_end = env->me_reclaimed_pglist + rpl_left;
|
||||||
if (!lifo) {
|
if (!lifo) {
|
||||||
rc = mdbx_cursor_first(&mc, &key, &data);
|
rc = mdbx_cursor_first(&mc, &key, &data);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
while (1) {
|
||||||
txnid_t id;
|
txnid_t id;
|
||||||
ssize_t len;
|
|
||||||
pgno_t save;
|
|
||||||
|
|
||||||
if (!lifo) {
|
if (!lifo) {
|
||||||
id = *(txnid_t *)key.iov_base;
|
id = *(txnid_t *)key.iov_base;
|
||||||
mdbx_tassert(txn, id <= env->me_last_reclaimed);
|
mdbx_tassert(txn, id <= env->me_last_reclaimed);
|
||||||
@ -3158,25 +3154,30 @@ again_on_freelist_change:
|
|||||||
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));
|
||||||
|
|
||||||
len = (ssize_t)(data.iov_len / sizeof(pgno_t)) - 1;
|
mdbx_tassert(txn, data.iov_len >= sizeof(pgno_t) * 2);
|
||||||
mdbx_tassert(txn, len >= 0);
|
size_t chunk_len = (data.iov_len / sizeof(pgno_t)) - 1;
|
||||||
if (len > mop_len)
|
if (chunk_len > rpl_left)
|
||||||
len = mop_len;
|
chunk_len = rpl_left;
|
||||||
data.iov_len = (len + 1) * sizeof(pgno_t);
|
data.iov_len = (chunk_len + 1) * sizeof(pgno_t);
|
||||||
key.iov_base = &id;
|
key.iov_base = &id;
|
||||||
key.iov_len = sizeof(id);
|
key.iov_len = sizeof(id);
|
||||||
data.iov_base = mop -= len;
|
|
||||||
|
|
||||||
save = mop[0];
|
rpl_end -= chunk_len;
|
||||||
mop[0] = (pgno_t)len;
|
data.iov_base = rpl_end;
|
||||||
|
pgno_t save = rpl_end[0];
|
||||||
|
rpl_end[0] = (pgno_t)chunk_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_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));
|
||||||
mop[0] = save;
|
rpl_end[0] = save;
|
||||||
if (unlikely(rc || (mop_len -= len) == 0))
|
if (unlikely(rc))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
|
|
||||||
|
rpl_left -= chunk_len;
|
||||||
|
if (rpl_left == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (!lifo) {
|
if (!lifo) {
|
||||||
rc = mdbx_cursor_next(&mc, &key, &data, MDBX_NEXT);
|
rc = mdbx_cursor_next(&mc, &key, &data, MDBX_NEXT);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user