diff --git a/src/core.c b/src/core.c index fb5822a7..db3d080f 100644 --- a/src/core.c +++ b/src/core.c @@ -3275,8 +3275,6 @@ static void mdbx_dpl_free(MDBX_txn *txn) { } static MDBX_dpl *mdbx_dpl_reserve(MDBX_txn *txn, size_t size) { - mdbx_tassert(txn, - txn->tw.dirtylist == NULL || txn->tw.dirtylist->length <= size); size_t bytes = dpl2bytes((size < MDBX_PGL_LIMIT) ? size : MDBX_PGL_LIMIT); MDBX_dpl *const dl = mdbx_realloc(txn->tw.dirtylist, bytes); if (likely(dl)) { @@ -3291,15 +3289,18 @@ static MDBX_dpl *mdbx_dpl_reserve(MDBX_txn *txn, size_t size) { } static int mdbx_dpl_alloc(MDBX_txn *txn) { - mdbx_tassert(txn, - (txn->mt_flags & MDBX_TXN_RDONLY) == 0 && !txn->tw.dirtylist); - const size_t len = (txn->mt_env->me_options.dp_initial < txn->mt_geo.upper) - ? txn->mt_env->me_options.dp_initial - : txn->mt_geo.upper; - MDBX_dpl *const dl = mdbx_dpl_reserve(txn, len); - if (unlikely(!dl)) - return MDBX_ENOMEM; - mdbx_dpl_clear(dl); + mdbx_tassert(txn, (txn->mt_flags & MDBX_TXN_RDONLY) == 0); + const int wanna = (txn->mt_env->me_options.dp_initial < txn->mt_geo.upper) + ? txn->mt_env->me_options.dp_initial + : txn->mt_geo.upper; + const int realloc_threshold = 64; + if (!txn->tw.dirtylist || + (int)txn->tw.dirtylist->detent - wanna > realloc_threshold || + (int)txn->tw.dirtylist->detent - wanna < -realloc_threshold) { + if (unlikely(!mdbx_dpl_reserve(txn, wanna))) + return MDBX_ENOMEM; + } + mdbx_dpl_clear(txn->tw.dirtylist); return MDBX_SUCCESS; } @@ -7040,8 +7041,6 @@ static int mdbx_txn_renew0(MDBX_txn *txn, const unsigned flags) { #if MDBX_ENABLE_REFUND txn->tw.loose_refund_wl = 0; #endif /* MDBX_ENABLE_REFUND */ - txn->tw.dirtyroom = txn->mt_env->me_options.dp_limit; - mdbx_dpl_clear(txn->tw.dirtylist); MDBX_PNL_SIZE(txn->tw.retired_pages) = 0; txn->tw.spill_pages = NULL; txn->tw.spill_least_removed = 0; @@ -7055,6 +7054,11 @@ static int mdbx_txn_renew0(MDBX_txn *txn, const unsigned flags) { memcpy(txn->mt_dbs, meta->mm_dbs, CORE_DBS * sizeof(MDBX_db)); /* Moved to here to avoid a data race in read TXNs */ txn->mt_geo = meta->mm_geo; + + rc = mdbx_dpl_alloc(txn); + if (unlikely(rc != MDBX_SUCCESS)) + goto bailout; + txn->tw.dirtyroom = txn->mt_env->me_options.dp_limit; } /* Setup db info */ @@ -7285,6 +7289,7 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, mdbx_tassert(parent, mdbx_dirtylist_check(parent)); txn->tw.cursors = (MDBX_cursor **)(txn->mt_dbs + env->me_maxdbs); txn->mt_dbiseqs = parent->mt_dbiseqs; + txn->mt_geo = parent->mt_geo; rc = mdbx_dpl_alloc(txn); if (likely(rc == MDBX_SUCCESS)) { const unsigned len = @@ -7352,7 +7357,6 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, (void *)(intptr_t)MDBX_PNL_SIZE(parent->tw.retired_pages); txn->mt_txnid = parent->mt_txnid; - txn->mt_geo = parent->mt_geo; #if MDBX_ENABLE_REFUND txn->tw.loose_refund_wl = 0; #endif /* MDBX_ENABLE_REFUND */ @@ -12025,13 +12029,10 @@ __cold int mdbx_env_open(MDBX_env *env, const char *pathname, txn->mt_dbxs = env->me_dbxs; txn->mt_flags = MDBX_TXN_FINISHED; env->me_txn0 = txn; - rc = mdbx_dpl_alloc(txn); - if (likely(rc == MDBX_SUCCESS)) { - txn->tw.retired_pages = mdbx_pnl_alloc(MDBX_PNL_INITIAL); - txn->tw.reclaimed_pglist = mdbx_pnl_alloc(MDBX_PNL_INITIAL); - if (unlikely(!txn->tw.retired_pages || !txn->tw.reclaimed_pglist)) - rc = MDBX_ENOMEM; - } + txn->tw.retired_pages = mdbx_pnl_alloc(MDBX_PNL_INITIAL); + txn->tw.reclaimed_pglist = mdbx_pnl_alloc(MDBX_PNL_INITIAL); + if (unlikely(!txn->tw.retired_pages || !txn->tw.reclaimed_pglist)) + rc = MDBX_ENOMEM; } else rc = MDBX_ENOMEM; }