mdbx: add MDBX_txn.mt_owner and MDBX_THREAD_MISMATCH.

This commit is contained in:
Leo Yuriev 2017-06-06 17:05:30 +03:00
parent 3bf3a08f96
commit 465459dc58
6 changed files with 104 additions and 16 deletions

View File

@ -2,6 +2,7 @@ AUTHORS
LICENSE LICENSE
Makefile Makefile
README.md README.md
TODO.md
mdbx.h mdbx.h
src/bits.h src/bits.h
src/defs.h src/defs.h

8
mdbx.h
View File

@ -414,10 +414,14 @@ typedef enum MDBX_cursor_op {
* when mdbx_cursor_put() called with MDBX_CURRENT option. */ * when mdbx_cursor_put() called with MDBX_CURRENT option. */
#define MDBX_EKEYMISMATCH (-30418) #define MDBX_EKEYMISMATCH (-30418)
/* Database is too large for current system, i.e. could NOT be mapped into RAM. /* Database is too large for current system,
*/ * e.g. could NOT be mapped into RAM. */
#define MDBX_TOO_LARGE (-30417) #define MDBX_TOO_LARGE (-30417)
/* A thread has attempted to use a not owned object,
* e.g. a transaction that started by another thread. */
#define MDBX_THREAD_MISMATCH (-30416)
/* Statistics for a database in the environment */ /* Statistics for a database in the environment */
typedef struct MDBX_stat { typedef struct MDBX_stat {
uint32_t ms_psize; /* Size of a database page. uint32_t ms_psize; /* Size of a database page.

View File

@ -527,6 +527,7 @@ struct MDBX_txn {
* dirtylist into mt_parent after freeing hidden mt_parent pages. */ * dirtylist into mt_parent after freeing hidden mt_parent pages. */
unsigned mt_dirtyroom; unsigned mt_dirtyroom;
mdbx_canary mt_canary; mdbx_canary mt_canary;
mdbx_tid_t mt_owner; /* thread ID that owns this transaction */
}; };
/* Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty. /* Enough space for 2^32 nodes with minimum of 2 keys per node. I.e., plenty.

View File

@ -690,8 +690,11 @@ static const char *__mdbx_strerr(int errnum) {
return "MDBX_EKEYMISMATCH: The given key value is mismatched to the " return "MDBX_EKEYMISMATCH: The given key value is mismatched to the "
"current cursor position"; "current cursor position";
case MDBX_TOO_LARGE: case MDBX_TOO_LARGE:
return "Database is too large for current system, i.e.could NOT be mapped " return "MDBX_TOO_LARGE: Database is too large for current system, "
"into RAM."; "e.g. could NOT be mapped into RAM";
case MDBX_THREAD_MISMATCH:
return "MDBX_THREAD_MISMATCH: A thread has attempted to use a not "
"owned object, e.g. a transaction that started by another thread";
default: default:
return NULL; return NULL;
} }
@ -968,13 +971,13 @@ static void mdbx_audit(MDBX_txn *txn) {
int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, int mdbx_cmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
const MDBX_val *b) { const MDBX_val *b) {
mdbx_ensure(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE);
return txn->mt_dbxs[dbi].md_cmp(a, b); return txn->mt_dbxs[dbi].md_cmp(a, b);
} }
int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a, int mdbx_dcmp(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *a,
const MDBX_val *b) { const MDBX_val *b) {
mdbx_ensure(NULL, txn->mt_signature == MDBX_MT_SIGNATURE); mdbx_assert(NULL, txn->mt_signature == MDBX_MT_SIGNATURE);
return txn->mt_dbxs[dbi].md_dcmp(a, b); return txn->mt_dbxs[dbi].md_dcmp(a, b);
} }
@ -2394,6 +2397,9 @@ int mdbx_txn_renew(MDBX_txn *txn) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY | MDBX_TXN_FINISHED))) if (unlikely(!F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY | MDBX_TXN_FINISHED)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -2434,6 +2440,9 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(parent->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EINVAL; return MDBX_EINVAL;
if (unlikely(parent->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
/* Nested transactions: Max 1 child, write txns only, no writemap */ /* Nested transactions: Max 1 child, write txns only, no writemap */
flags |= parent->mt_flags; flags |= parent->mt_flags;
if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) { if (unlikely(flags & (MDBX_RDONLY | MDBX_WRITEMAP | MDBX_TXN_BLOCKED))) {
@ -2510,6 +2519,7 @@ int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, unsigned flags,
if (txn != env->me_txn0) if (txn != env->me_txn0)
free(txn); free(txn);
} else { } else {
txn->mt_owner = mdbx_thread_self();
txn->mt_signature = MDBX_MT_SIGNATURE; txn->mt_signature = MDBX_MT_SIGNATURE;
*ret = txn; *ret = txn;
mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO "", mdbx_debug("begin txn %" PRIaTXN "%c %p on env %p, root page %" PRIaPGNO "",
@ -2593,7 +2603,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
mdbx_coherent_barrier(); mdbx_coherent_barrier();
txn->mt_numdbs = 0; /* prevent further DBI activity */ txn->mt_numdbs = 0; /* prevent further DBI activity */
txn->mt_flags |= MDBX_TXN_FINISHED; txn->mt_flags |= MDBX_TXN_FINISHED;
txn->mt_owner = 0;
} else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) { } else if (!F_ISSET(txn->mt_flags, MDBX_TXN_FINISHED)) {
pgno_t *pghead = env->me_pghead; pgno_t *pghead = env->me_pghead;
@ -2621,6 +2631,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
env->me_pglast = 0; env->me_pglast = 0;
env->me_txn = NULL; env->me_txn = NULL;
txn->mt_owner = 0;
txn->mt_signature = 0; txn->mt_signature = 0;
mode = 0; /* txn == env->me_txn0, do not free() it */ mode = 0; /* txn == env->me_txn0, do not free() it */
@ -2640,6 +2651,7 @@ static int mdbx_txn_end(MDBX_txn *txn, unsigned mode) {
if (mode & MDBX_END_FREE) { if (mode & MDBX_END_FREE) {
mdbx_ensure(env, txn != env->me_txn0); mdbx_ensure(env, txn != env->me_txn0);
txn->mt_owner = 0;
txn->mt_signature = 0; txn->mt_signature = 0;
free(txn); free(txn);
} }
@ -2654,6 +2666,9 @@ int mdbx_txn_reset(MDBX_txn *txn) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
/* This call is only valid for read-only txns */ /* This call is only valid for read-only txns */
if (unlikely(!(txn->mt_flags & MDBX_TXN_RDONLY))) if (unlikely(!(txn->mt_flags & MDBX_TXN_RDONLY)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -2669,6 +2684,9 @@ int mdbx_txn_abort(MDBX_txn *txn) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY)) if (F_ISSET(txn->mt_flags, MDBX_TXN_RDONLY))
/* LY: don't close DBI-handles in MDBX mode */ /* LY: don't close DBI-handles in MDBX mode */
return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_UPDATE | MDBX_END_SLOT | return mdbx_txn_end(txn, MDBX_END_ABORT | MDBX_END_UPDATE | MDBX_END_SLOT |
@ -3133,6 +3151,9 @@ int mdbx_txn_commit(MDBX_txn *txn) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
MDBX_env *env = txn->mt_env; MDBX_env *env = txn->mt_env;
if (unlikely(env->me_pid != mdbx_getpid())) { if (unlikely(env->me_pid != mdbx_getpid())) {
env->me_flags |= MDBX_FATAL_ERROR; env->me_flags |= MDBX_FATAL_ERROR;
@ -5256,6 +5277,9 @@ int mdbx_get(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -7162,6 +7186,9 @@ int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -7197,6 +7224,9 @@ int mdbx_cursor_renew(MDBX_txn *txn, MDBX_cursor *mc) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE && if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE &&
mc->mc_signature != MDBX_MC_READY4CLOSE)) mc->mc_signature != MDBX_MC_READY4CLOSE))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -7231,6 +7261,9 @@ int mdbx_cursor_count(MDBX_cursor *mc, size_t *countp) {
if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE)) if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(mc->mc_txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED)) if (unlikely(mc->mc_txn->mt_flags & MDBX_TXN_BLOCKED))
return MDBX_BAD_TXN; return MDBX_BAD_TXN;
@ -8054,6 +8087,9 @@ int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -8543,6 +8579,9 @@ int mdbx_put(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9236,6 +9275,9 @@ int mdbx_dbi_open_ex(MDBX_txn *txn, const char *table_name, unsigned user_flags,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
return MDBX_BAD_TXN; return MDBX_BAD_TXN;
@ -9368,6 +9410,9 @@ int __cold mdbx_dbi_stat(MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *arg,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9422,6 +9467,9 @@ int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_VALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9528,6 +9576,9 @@ int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, int del) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9602,6 +9653,9 @@ int mdbx_set_compare(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9616,6 +9670,9 @@ int mdbx_set_dupsort(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cmp_func *cmp) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -9887,6 +9944,9 @@ int mdbx_txn_straggler(MDBX_txn *txn, int *percent)
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!txn->mt_ro_reader)) if (unlikely(!txn->mt_ro_reader))
return -1; return -1;
@ -10041,9 +10101,13 @@ int __cold mdbx_env_pgwalk(MDBX_txn *txn, MDBX_pgvisitor_func *visitor,
void *user) { void *user) {
if (unlikely(!txn)) if (unlikely(!txn))
return MDBX_BAD_TXN; return MDBX_BAD_TXN;
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
mdbx_walk_ctx_t ctx; mdbx_walk_ctx_t ctx;
ctx.mw_txn = txn; ctx.mw_txn = txn;
ctx.mw_user = user; ctx.mw_user = user;
@ -10069,6 +10133,9 @@ int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED)) if (unlikely(txn->mt_flags & MDBX_TXN_BLOCKED))
return MDBX_BAD_TXN; return MDBX_BAD_TXN;
@ -10097,9 +10164,13 @@ int mdbx_canary_put(MDBX_txn *txn, const mdbx_canary *canary) {
int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary) { int mdbx_canary_get(MDBX_txn *txn, mdbx_canary *canary) {
if (unlikely(txn == NULL || canary == NULL)) if (unlikely(txn == NULL || canary == NULL))
return MDBX_EINVAL; return MDBX_EINVAL;
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
*canary = txn->mt_canary; *canary = txn->mt_canary;
return MDBX_SUCCESS; return MDBX_SUCCESS;
} }
@ -10197,6 +10268,9 @@ int mdbx_replace(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *new_data,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(old_data->iov_base == NULL && old_data->iov_len)) if (unlikely(old_data->iov_base == NULL && old_data->iov_len))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -10332,6 +10406,9 @@ int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -10396,6 +10473,9 @@ int mdbx_is_dirty(const MDBX_txn *txn, const void *ptr) {
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(txn->mt_flags & MDBX_TXN_RDONLY)) if (unlikely(txn->mt_flags & MDBX_TXN_RDONLY))
return MDBX_RESULT_FALSE; return MDBX_RESULT_FALSE;
@ -10457,6 +10537,9 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result,
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE)) if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN; return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID))) if (unlikely(!TXN_DBI_EXIST(txn, dbi, DB_USRVALID)))
return MDBX_EINVAL; return MDBX_EINVAL;

View File

@ -615,14 +615,6 @@ void mdbx_thread_rthc_set(mdbx_thread_key_t key, const void *value) {
#endif #endif
} }
mdbx_tid_t mdbx_thread_self(void) {
#if defined(_WIN32) || defined(_WIN64)
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
int mdbx_thread_create(mdbx_thread_t *thread, int mdbx_thread_create(mdbx_thread_t *thread,
THREAD_RESULT(THREAD_CALL *start_routine)(void *), THREAD_RESULT(THREAD_CALL *start_routine)(void *),
void *arg) { void *arg) {

View File

@ -439,7 +439,6 @@ int mdbx_thread_create(mdbx_thread_t *thread,
THREAD_RESULT(THREAD_CALL *start_routine)(void *), THREAD_RESULT(THREAD_CALL *start_routine)(void *),
void *arg); void *arg);
int mdbx_thread_join(mdbx_thread_t thread); int mdbx_thread_join(mdbx_thread_t thread);
mdbx_tid_t mdbx_thread_self(void);
int mdbx_thread_key_create(mdbx_thread_key_t *key); int mdbx_thread_key_create(mdbx_thread_key_t *key);
void mdbx_thread_key_delete(mdbx_thread_key_t key); void mdbx_thread_key_delete(mdbx_thread_key_t key);
void *mdbx_thread_rthc_get(mdbx_thread_key_t key); void *mdbx_thread_rthc_get(mdbx_thread_key_t key);
@ -465,6 +464,14 @@ static __inline mdbx_pid_t mdbx_getpid(void) {
#endif #endif
} }
static __inline mdbx_tid_t mdbx_thread_self(void) {
#if defined(_WIN32) || defined(_WIN64)
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}
void mdbx_osal_jitter(bool tiny); void mdbx_osal_jitter(bool tiny);
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/