From 1bf008ac16949d003668887895c07824e31e6e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Mon, 30 Dec 2024 17:49:42 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=D0=B0-=D0=B2=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=B5=D0=BB=D1=8C=D1=86=D0=B0=20=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B7=D0=B0=D0=BA=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Теперь допускается commit/abort вложенных транзакций из любого треда в режиме MDBX_NOSTICKYTHREADS. 2. Более наглядные/явные проверки без зависимости от больше/меньше. Одна проверка внутри check_txn() для всех основных случаев (bad_bits != 0) и две проверки для abort/reset/break (bad_bits == 0). +-------------------------------------------------------------------------------------------------------+ | Три анализируемых txn->flags | Проверка txn->owner == osal_thread_self() | +-----------------+------------+--------------+-----------------------+---------------------------------+ | NOSTICKYTHREADS | TXN_RDONLY | TXN_FINISHED | usual (bad_bits != 0) | abort/reset/break (bad_bits==0) | | - | - | - | + | + | | - | - | + | + | + | | - | + | - | + | + | | - | + | + | + | - | | + | - | - | - | - | | + | - | + | + | + | | + | + | - | - | - | | + | + | + | + | - | +-------------------------------------------------------------------------------------------------------+ --- src/api-txn.c | 25 ++++++++++++++++--------- src/cogs.h | 25 ++++++++++++++----------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/api-txn.c b/src/api-txn.c index 3e930f04..24598992 100644 --- a/src/api-txn.c +++ b/src/api-txn.c @@ -385,6 +385,9 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) { const uint64_t ts_0 = latency ? osal_monotime() : 0; uint64_t ts_1 = 0, ts_2 = 0, ts_3 = 0, ts_4 = 0, ts_5 = 0, gc_cputime = 0; + /* txn_end() mode for a commit which writes nothing */ + unsigned end_mode = TXN_END_PURE_COMMIT | TXN_END_UPDATE | TXN_END_SLOT | TXN_END_FREE; + int rc = check_txn(txn, MDBX_TXN_FINISHED); if (unlikely(rc != MDBX_SUCCESS)) { if (rc == MDBX_BAD_TXN && (txn->flags & MDBX_TXN_RDONLY)) { @@ -404,18 +407,22 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) { goto bailout; } - if (unlikely(txn->flags & MDBX_TXN_ERROR)) { - rc = MDBX_RESULT_TRUE; - goto fail; + if (unlikely(txn->flags & MDBX_TXN_RDONLY)) { + if (txn->flags & MDBX_TXN_ERROR) { + rc = MDBX_RESULT_TRUE; + goto fail; + } + goto done; } - /* txn_end() mode for a commit which writes nothing */ - unsigned end_mode = TXN_END_PURE_COMMIT | TXN_END_UPDATE | TXN_END_SLOT | TXN_END_FREE; - if (unlikely(txn->flags & MDBX_TXN_RDONLY)) - goto done; - - if ((txn->flags & MDBX_NOSTICKYTHREADS) && unlikely(txn->owner != osal_thread_self())) { + if (!txn->parent && (txn->flags & MDBX_NOSTICKYTHREADS) && unlikely(txn->owner != osal_thread_self())) { + txn->flags |= MDBX_TXN_ERROR; rc = MDBX_THREAD_MISMATCH; + return LOG_IFERR(rc); + } + + if (unlikely(txn->flags & MDBX_TXN_ERROR)) { + rc = MDBX_RESULT_TRUE; goto fail; } diff --git a/src/cogs.h b/src/cogs.h index 41d79b40..5b8f20c7 100644 --- a/src/cogs.h +++ b/src/cogs.h @@ -400,32 +400,35 @@ static inline int check_env(const MDBX_env *env, const bool wanna_active) { return MDBX_SUCCESS; } -static inline int check_txn(const MDBX_txn *txn, int bad_bits) { +static __always_inline int check_txn(const MDBX_txn *txn, int bad_bits) { if (unlikely(!txn)) return MDBX_EINVAL; if (unlikely(txn->signature != txn_signature)) return MDBX_EBADSIGN; - if (bad_bits && unlikely(txn->flags & bad_bits)) { - if ((bad_bits & MDBX_TXN_PARKED) == 0) - return MDBX_BAD_TXN; - else - return txn_check_badbits_parked(txn, bad_bits); + if (bad_bits) { + if (unlikely(!txn->env->dxb_mmap.base)) + return MDBX_EPERM; + + if (unlikely(txn->flags & bad_bits)) { + if ((bad_bits & MDBX_TXN_PARKED) == 0) + return MDBX_BAD_TXN; + else + return txn_check_badbits_parked(txn, bad_bits); + } } tASSERT(txn, (txn->flags & MDBX_TXN_FINISHED) || (txn->flags & MDBX_NOSTICKYTHREADS) == (txn->env->flags & MDBX_NOSTICKYTHREADS)); #if MDBX_TXN_CHECKOWNER - STATIC_ASSERT((long)MDBX_NOSTICKYTHREADS > (long)MDBX_TXN_FINISHED); - if ((txn->flags & (MDBX_NOSTICKYTHREADS | MDBX_TXN_FINISHED)) < MDBX_TXN_FINISHED && + if ((txn->flags & (MDBX_NOSTICKYTHREADS | MDBX_TXN_FINISHED)) != MDBX_NOSTICKYTHREADS && + !(bad_bits /* abort/reset/txn-break */ == 0 && + ((txn->flags & (MDBX_TXN_RDONLY | MDBX_TXN_FINISHED)) == (MDBX_TXN_RDONLY | MDBX_TXN_FINISHED))) && unlikely(txn->owner != osal_thread_self())) return txn->owner ? MDBX_THREAD_MISMATCH : MDBX_BAD_TXN; #endif /* MDBX_TXN_CHECKOWNER */ - if (bad_bits && unlikely(!txn->env->dxb_mmap.base)) - return MDBX_EPERM; - return MDBX_SUCCESS; }