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. */ * descending order. */
typedef pgno_t *MDBX_IDL; 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. */ /* An ID2 is an ID/pointer pair. */
typedef struct MDBX_ID2 { typedef struct MDBX_ID2 {
pgno_t mid; /* The ID */ pgno_t mid; /* The ID */
@ -451,7 +454,7 @@ struct MDBX_txn {
txnid_t mt_txnid; txnid_t mt_txnid;
MDBX_env *mt_env; /* the DB environment */ MDBX_env *mt_env; /* the DB environment */
/* The list of reclaimed txns from freeDB */ /* 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. */ /* The list of pages that became unused during this transaction. */
MDBX_IDL mt_free_pages; MDBX_IDL mt_free_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

View File

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