mdbx: add txnid-list functions.

This commit is contained in:
Leo Yuriev 2017-06-05 14:02:44 +03:00
parent 52f52de2d5
commit 1343b46466
2 changed files with 73 additions and 18 deletions

View File

@ -394,6 +394,9 @@ typedef struct MDBX_lockinfo {
* descending order. */
typedef pgno_t *MDBX_IDL;
/* List of txnid, only for MDBX_env.mt_lifo_reclaimed */
typedef txnid_t *MDBX_TXL;
/* An ID2 is an ID/pointer pair. */
typedef struct MDBX_ID2 {
pgno_t mid; /* The ID */
@ -451,7 +454,7 @@ struct MDBX_txn {
txnid_t mt_txnid;
MDBX_env *mt_env; /* the DB environment */
/* The list of reclaimed txns from freeDB */
MDBX_IDL mt_lifo_reclaimed;
MDBX_TXL mt_lifo_reclaimed;
/* The list of pages that became unused during this transaction. */
MDBX_IDL mt_free_pages;
/* The list of loose pages that became unused and may be reused

View File

@ -168,13 +168,27 @@ static MDBX_IDL mdbx_midl_alloc(unsigned size) {
return ids;
}
static MDBX_TXL mdbx_txl_alloc(unsigned size) {
MDBX_TXL ptr = malloc((size + 2) * sizeof(txnid_t));
if (likely(ptr)) {
*ptr++ = size;
*ptr = 0;
}
return ptr;
}
/* Free an IDL.
* [in] ids The IDL to free. */
static void mdbx_midl_free(MDBX_IDL ids) {
if (ids)
if (likely(ids))
free(ids - 1);
}
static void mdbx_txl_free(MDBX_TXL list) {
if (likely(list))
free(list - 1);
}
/* Append ID to IDL. The IDL must be big enough. */
static __inline void mdbx_midl_xappend(MDBX_IDL idl, pgno_t id) {
assert(idl[0] + (size_t)1 < MDBX_IDL_ALLOCLEN(idl));
@ -244,6 +258,17 @@ static int mdbx_midl_grow(MDBX_IDL *idp, unsigned num) {
return 0;
}
static int mdbx_txl_grow(MDBX_TXL *ptr, unsigned num) {
MDBX_TXL list = *ptr - 1;
/* grow it */
list = realloc(list, (*list + num + 2) * sizeof(txnid_t));
if (unlikely(!list))
return MDBX_ENOMEM;
*list++ += num;
*ptr = list;
return 0;
}
/* Make room for num additional elements in an IDL.
* [in,out] idp Address of the IDL.
* [in] num Number of elements to make room for.
@ -251,7 +276,7 @@ static int mdbx_midl_grow(MDBX_IDL *idp, unsigned num) {
static int mdbx_midl_need(MDBX_IDL *idp, unsigned num) {
MDBX_IDL ids = *idp;
num += ids[0];
if (num > ids[-1]) {
if (unlikely(num > ids[-1])) {
num = (num + num / 4 + (256 + 2)) & -256;
ids = realloc(ids - 1, num * sizeof(pgno_t));
if (unlikely(!ids))
@ -269,7 +294,7 @@ static int mdbx_midl_need(MDBX_IDL *idp, unsigned num) {
static int mdbx_midl_append(MDBX_IDL *idp, pgno_t id) {
MDBX_IDL ids = *idp;
/* Too big? */
if (ids[0] >= ids[-1]) {
if (unlikely(ids[0] >= ids[-1])) {
if (mdbx_midl_grow(idp, MDBX_IDL_UM_MAX))
return MDBX_ENOMEM;
ids = *idp;
@ -279,6 +304,19 @@ static int mdbx_midl_append(MDBX_IDL *idp, pgno_t id) {
return 0;
}
static int mdbx_txl_append(MDBX_TXL *ptr, txnid_t id) {
MDBX_TXL list = *ptr;
/* Too big? */
if (unlikely(list[0] >= list[-1])) {
if (mdbx_txl_grow(ptr, list[0]))
return MDBX_ENOMEM;
list = *ptr;
}
list[0]++;
list[list[0]] = id;
return 0;
}
/* Append an IDL onto an IDL.
* [in,out] idp Address of the IDL to append to.
* [in] app The IDL to append.
@ -286,7 +324,7 @@ static int mdbx_midl_append(MDBX_IDL *idp, pgno_t id) {
static int mdbx_midl_append_list(MDBX_IDL *idp, MDBX_IDL app) {
MDBX_IDL ids = *idp;
/* Too big? */
if (ids[0] + app[0] >= ids[-1]) {
if (unlikely(ids[0] + app[0] >= ids[-1])) {
if (mdbx_midl_grow(idp, app[0]))
return MDBX_ENOMEM;
ids = *idp;
@ -296,6 +334,19 @@ static int mdbx_midl_append_list(MDBX_IDL *idp, MDBX_IDL app) {
return 0;
}
static int mdbx_txl_append_list(MDBX_TXL *ptr, MDBX_TXL append) {
MDBX_TXL list = *ptr;
/* Too big? */
if (unlikely(list[0] + append[0] >= list[-1])) {
if (mdbx_txl_grow(ptr, append[0]))
return MDBX_ENOMEM;
list = *ptr;
}
memcpy(&list[list[0] + 1], &append[1], append[0] * sizeof(txnid_t));
list[0] += append[0];
return 0;
}
/* Append an ID range onto an IDL.
* [in,out] idp Address of the IDL to append to.
* [in] id The lowest ID to append.
@ -304,7 +355,7 @@ static int mdbx_midl_append_list(MDBX_IDL *idp, MDBX_IDL app) {
static int mdbx_midl_append_range(MDBX_IDL *idp, pgno_t id, unsigned n) {
pgno_t *ids = *idp, len = ids[0];
/* Too big? */
if (len + n > ids[-1]) {
if (unlikely(len + n > ids[-1])) {
if (mdbx_midl_grow(idp, n | MDBX_IDL_UM_MAX))
return MDBX_ENOMEM;
ids = *idp;
@ -1644,7 +1695,7 @@ static int mdbx_page_alloc(MDBX_cursor *mc, int num, MDBX_page **mp,
goto fail;
if ((flags & MDBX_LIFORECLAIM) && !txn->mt_lifo_reclaimed) {
txn->mt_lifo_reclaimed = mdbx_midl_alloc(env->me_maxfree_1pg);
txn->mt_lifo_reclaimed = mdbx_txl_alloc(env->me_maxfree_1pg);
if (unlikely(!txn->mt_lifo_reclaimed)) {
rc = MDBX_ENOMEM;
goto fail;
@ -1666,7 +1717,7 @@ static int mdbx_page_alloc(MDBX_cursor *mc, int num, MDBX_page **mp,
mop = env->me_pghead;
}
if (flags & MDBX_LIFORECLAIM) {
if ((rc = mdbx_midl_append(&txn->mt_lifo_reclaimed, last)) != 0)
if ((rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, last)) != 0)
goto fail;
}
env->me_pglast = last;
@ -2559,7 +2610,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
if (txn->mt_lifo_reclaimed) {
txn->mt_lifo_reclaimed[0] = 0;
if (txn != env->me_txn0) {
mdbx_midl_free(txn->mt_lifo_reclaimed);
mdbx_txl_free(txn->mt_lifo_reclaimed);
txn->mt_lifo_reclaimed = NULL;
}
}
@ -2823,14 +2874,14 @@ again:
}
if (unlikely(!txn->mt_lifo_reclaimed)) {
txn->mt_lifo_reclaimed = mdbx_midl_alloc(env->me_maxfree_1pg);
txn->mt_lifo_reclaimed = mdbx_txl_alloc(env->me_maxfree_1pg);
if (unlikely(!txn->mt_lifo_reclaimed)) {
rc = MDBX_ENOMEM;
goto bailout;
}
}
/* LY: append the list. */
rc = mdbx_midl_append(&txn->mt_lifo_reclaimed, env->me_pglast - 1);
rc = mdbx_txl_append(&txn->mt_lifo_reclaimed, env->me_pglast - 1);
if (unlikely(rc))
goto bailout;
--env->me_pglast;
@ -2970,7 +3021,7 @@ bailout:
}
txn->mt_lifo_reclaimed[0] = 0;
if (txn != env->me_txn0) {
mdbx_midl_free(txn->mt_lifo_reclaimed);
mdbx_txl_free(txn->mt_lifo_reclaimed);
txn->mt_lifo_reclaimed = NULL;
}
}
@ -3122,11 +3173,11 @@ int mdbx_txn_commit(MDBX_txn *txn) {
/* Append our reclaim list to parent's */
if (txn->mt_lifo_reclaimed) {
if (parent->mt_lifo_reclaimed) {
rc = mdbx_midl_append_list(&parent->mt_lifo_reclaimed,
txn->mt_lifo_reclaimed);
rc = mdbx_txl_append_list(&parent->mt_lifo_reclaimed,
txn->mt_lifo_reclaimed);
if (unlikely(rc != MDBX_SUCCESS))
goto fail;
mdbx_midl_free(txn->mt_lifo_reclaimed);
mdbx_txl_free(txn->mt_lifo_reclaimed);
} else
parent->mt_lifo_reclaimed = txn->mt_lifo_reclaimed;
txn->mt_lifo_reclaimed = NULL;
@ -4457,9 +4508,10 @@ static void __cold mdbx_env_close0(MDBX_env *env) {
free(env->me_dbflags);
free(env->me_path);
free(env->me_dirtylist);
if (env->me_txn0)
mdbx_midl_free(env->me_txn0->mt_lifo_reclaimed);
free(env->me_txn0);
if (env->me_txn0) {
mdbx_txl_free(env->me_txn0->mt_lifo_reclaimed);
free(env->me_txn0);
}
mdbx_midl_free(env->me_free_pgs);
if (env->me_flags & MDBX_ENV_TXKEY) {