mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-15 23:04:30 +08:00
mdbx: доработка контроля потока-владельца транзакции.
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) | | - | - | - | + | + | | - | - | + | + | + | | - | + | - | + | + | | - | + | + | + | - | | + | - | - | - | - | | + | - | + | + | + | | + | + | - | - | - | | + | + | + | + | - | +-------------------------------------------------------------------------------------------------------+
This commit is contained in:
parent
1e4e2eb3c8
commit
1bf008ac16
@ -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;
|
||||
}
|
||||
|
||||
|
25
src/cogs.h
25
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user