mirror of
https://github.com/isar/libmdbx.git
synced 2025-03-10 19:18:14 +08:00
mdbx: переделка env_owned_wrtxn()
и мест её вызова (backport).
Цель в том чтобы избавить от коллизии блокировки возникающей внутри dxb_sanitize_tail() при использовании Valgrind/ASAN, а также упросить код.
This commit is contained in:
parent
d313008d82
commit
5e714ed946
@ -342,7 +342,7 @@ __cold int mdbx_env_set_flags(MDBX_env *env, MDBX_env_flags_t flags, bool onoff)
|
|||||||
if (unlikely(env->flags & MDBX_RDONLY))
|
if (unlikely(env->flags & MDBX_RDONLY))
|
||||||
return LOG_IFERR(MDBX_EACCESS);
|
return LOG_IFERR(MDBX_EACCESS);
|
||||||
|
|
||||||
const bool lock_needed = (env->flags & ENV_ACTIVE) && !env_txn0_owned(env);
|
const bool lock_needed = (env->flags & ENV_ACTIVE) && !env_owned_wrtxn(env);
|
||||||
bool should_unlock = false;
|
bool should_unlock = false;
|
||||||
if (lock_needed) {
|
if (lock_needed) {
|
||||||
rc = lck_txn_lock(env, false);
|
rc = lck_txn_lock(env, false);
|
||||||
|
@ -958,8 +958,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
|
||||||
const bool txn0_owned = env->basal_txn && env_txn0_owned(env);
|
MDBX_txn *const txn_owned = env_owned_wrtxn(env);
|
||||||
const bool inside_txn = txn0_owned && env->txn;
|
|
||||||
bool should_unlock = false;
|
bool should_unlock = false;
|
||||||
|
|
||||||
#if MDBX_DEBUG && 0 /* минимальные шаги для проверки/отладки уже не нужны */
|
#if MDBX_DEBUG && 0 /* минимальные шаги для проверки/отладки уже не нужны */
|
||||||
@ -975,7 +974,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
if (unlikely(env->flags & MDBX_RDONLY))
|
if (unlikely(env->flags & MDBX_RDONLY))
|
||||||
return LOG_IFERR(MDBX_EACCESS);
|
return LOG_IFERR(MDBX_EACCESS);
|
||||||
|
|
||||||
if (!txn0_owned) {
|
if (!txn_owned) {
|
||||||
int err = lck_txn_lock(env, false);
|
int err = lck_txn_lock(env, false);
|
||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
@ -989,8 +988,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
/* get untouched params from current TXN or DB */
|
/* get untouched params from current TXN or DB */
|
||||||
if (pagesize <= 0 || pagesize >= INT_MAX)
|
if (pagesize <= 0 || pagesize >= INT_MAX)
|
||||||
pagesize = env->ps;
|
pagesize = env->ps;
|
||||||
const geo_t *const geo =
|
const geo_t *const geo = env->txn ? &env->txn->geo : &meta_recent(env, &env->basal_txn->tw.troika).ptr_c->geometry;
|
||||||
inside_txn ? &env->txn->geo : &meta_recent(env, &env->basal_txn->tw.troika).ptr_c->geometry;
|
|
||||||
if (size_lower < 0)
|
if (size_lower < 0)
|
||||||
size_lower = pgno2bytes(env, geo->lower);
|
size_lower = pgno2bytes(env, geo->lower);
|
||||||
if (size_now < 0)
|
if (size_now < 0)
|
||||||
@ -1015,7 +1013,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
size_now = usedbytes;
|
size_now = usedbytes;
|
||||||
} else {
|
} else {
|
||||||
/* env NOT yet mapped */
|
/* env NOT yet mapped */
|
||||||
if (unlikely(inside_txn))
|
if (unlikely(env->txn))
|
||||||
return LOG_IFERR(MDBX_PANIC);
|
return LOG_IFERR(MDBX_PANIC);
|
||||||
|
|
||||||
/* is requested some auto-value for pagesize ? */
|
/* is requested some auto-value for pagesize ? */
|
||||||
@ -1204,8 +1202,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
ENSURE(env, pagesize == (intptr_t)env->ps);
|
ENSURE(env, pagesize == (intptr_t)env->ps);
|
||||||
meta_t meta;
|
meta_t meta;
|
||||||
memset(&meta, 0, sizeof(meta));
|
memset(&meta, 0, sizeof(meta));
|
||||||
if (!inside_txn) {
|
if (!env->txn) {
|
||||||
eASSERT(env, should_unlock);
|
|
||||||
const meta_ptr_t head = meta_recent(env, &env->basal_txn->tw.troika);
|
const meta_ptr_t head = meta_recent(env, &env->basal_txn->tw.troika);
|
||||||
|
|
||||||
uint64_t timestamp = 0;
|
uint64_t timestamp = 0;
|
||||||
@ -1295,7 +1292,7 @@ __cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t si
|
|||||||
if (unlikely(rc != MDBX_SUCCESS))
|
if (unlikely(rc != MDBX_SUCCESS))
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
if (inside_txn) {
|
if (env->txn) {
|
||||||
env->txn->geo = new_geo;
|
env->txn->geo = new_geo;
|
||||||
env->txn->flags |= MDBX_TXN_DIRTY;
|
env->txn->flags |= MDBX_TXN_DIRTY;
|
||||||
} else {
|
} else {
|
||||||
@ -1420,17 +1417,17 @@ __cold int mdbx_env_stat_ex(const MDBX_env *env, const MDBX_txn *txn, MDBX_stat
|
|||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
|
|
||||||
if (env->txn && env_txn0_owned(env))
|
MDBX_txn *txn_owned = env_owned_wrtxn(env);
|
||||||
|
if (txn_owned)
|
||||||
/* inside write-txn */
|
/* inside write-txn */
|
||||||
return LOG_IFERR(stat_acc(env->txn, dest, bytes));
|
return LOG_IFERR(stat_acc(txn_owned, dest, bytes));
|
||||||
|
|
||||||
MDBX_txn *tmp_txn;
|
err = mdbx_txn_begin((MDBX_env *)env, nullptr, MDBX_TXN_RDONLY, &txn_owned);
|
||||||
err = mdbx_txn_begin((MDBX_env *)env, nullptr, MDBX_TXN_RDONLY, &tmp_txn);
|
|
||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
|
|
||||||
const int rc = stat_acc(tmp_txn, dest, bytes);
|
const int rc = stat_acc(txn_owned, dest, bytes);
|
||||||
err = mdbx_txn_abort(tmp_txn);
|
err = mdbx_txn_abort(txn_owned);
|
||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
return LOG_IFERR(rc);
|
return LOG_IFERR(rc);
|
||||||
|
@ -180,7 +180,7 @@ __cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, uint64
|
|||||||
if (unlikely(err != MDBX_SUCCESS))
|
if (unlikely(err != MDBX_SUCCESS))
|
||||||
return LOG_IFERR(err);
|
return LOG_IFERR(err);
|
||||||
|
|
||||||
const bool lock_needed = ((env->flags & ENV_ACTIVE) && env->basal_txn && !env_txn0_owned(env));
|
const bool lock_needed = ((env->flags & ENV_ACTIVE) && env->basal_txn && !env_owned_wrtxn(env));
|
||||||
bool should_unlock = false;
|
bool should_unlock = false;
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case MDBX_opt_sync_bytes:
|
case MDBX_opt_sync_bytes:
|
||||||
|
@ -368,7 +368,7 @@ void dxb_sanitize_tail(MDBX_env *env, MDBX_txn *txn) {
|
|||||||
if (env->pid != osal_getpid()) {
|
if (env->pid != osal_getpid()) {
|
||||||
/* resurrect after fork */
|
/* resurrect after fork */
|
||||||
return;
|
return;
|
||||||
} else if (env->txn && env_txn0_owned(env)) {
|
} else if (env_owned_wrtxn(env)) {
|
||||||
/* inside write-txn */
|
/* inside write-txn */
|
||||||
last = meta_recent(env, &env->basal_txn->tw.troika).ptr_v->geometry.first_unallocated;
|
last = meta_recent(env, &env->basal_txn->tw.troika).ptr_v->geometry.first_unallocated;
|
||||||
} else if (env->flags & MDBX_RDONLY) {
|
} else if (env->flags & MDBX_RDONLY) {
|
||||||
|
21
src/env.c
21
src/env.c
@ -3,9 +3,14 @@
|
|||||||
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
bool env_txn0_owned(const MDBX_env *env) {
|
MDBX_txn *env_owned_wrtxn(const MDBX_env *env) {
|
||||||
return (env->flags & MDBX_NOSTICKYTHREADS) ? (env->basal_txn->owner != 0)
|
if (likely(env->basal_txn)) {
|
||||||
: (env->basal_txn->owner == osal_thread_self());
|
const bool is_owned = (env->flags & MDBX_NOSTICKYTHREADS) ? (env->basal_txn->owner != 0)
|
||||||
|
: (env->basal_txn->owner == osal_thread_self());
|
||||||
|
if (is_owned)
|
||||||
|
return env->txn ? env->txn : env->basal_txn;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int env_page_auxbuffer(MDBX_env *env) {
|
int env_page_auxbuffer(MDBX_env *env) {
|
||||||
@ -60,7 +65,7 @@ __cold int env_sync(MDBX_env *env, bool force, bool nonblock) {
|
|||||||
if (unlikely(env->flags & MDBX_RDONLY))
|
if (unlikely(env->flags & MDBX_RDONLY))
|
||||||
return MDBX_EACCESS;
|
return MDBX_EACCESS;
|
||||||
|
|
||||||
const bool txn0_owned = env_txn0_owned(env);
|
MDBX_txn *const txn_owned = env_owned_wrtxn(env);
|
||||||
bool should_unlock = false;
|
bool should_unlock = false;
|
||||||
int rc = MDBX_RESULT_TRUE /* means "nothing to sync" */;
|
int rc = MDBX_RESULT_TRUE /* means "nothing to sync" */;
|
||||||
|
|
||||||
@ -71,7 +76,7 @@ retry:;
|
|||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
const troika_t troika = (txn0_owned | should_unlock) ? env->basal_txn->tw.troika : meta_tap(env);
|
const troika_t troika = (txn_owned || should_unlock) ? env->basal_txn->tw.troika : meta_tap(env);
|
||||||
const meta_ptr_t head = meta_recent(env, &troika);
|
const meta_ptr_t head = meta_recent(env, &troika);
|
||||||
const uint64_t unsynced_pages = atomic_load64(&env->lck->unsynced_pages, mo_Relaxed);
|
const uint64_t unsynced_pages = atomic_load64(&env->lck->unsynced_pages, mo_Relaxed);
|
||||||
if (unsynced_pages == 0) {
|
if (unsynced_pages == 0) {
|
||||||
@ -104,7 +109,7 @@ retry:;
|
|||||||
osal_monotime() - eoos_timestamp >= autosync_period))
|
osal_monotime() - eoos_timestamp >= autosync_period))
|
||||||
flags &= MDBX_WRITEMAP /* clear flags for full steady sync */;
|
flags &= MDBX_WRITEMAP /* clear flags for full steady sync */;
|
||||||
|
|
||||||
if (!txn0_owned) {
|
if (!txn_owned) {
|
||||||
if (!should_unlock) {
|
if (!should_unlock) {
|
||||||
#if MDBX_ENABLE_PGOP_STAT
|
#if MDBX_ENABLE_PGOP_STAT
|
||||||
unsigned wops = 0;
|
unsigned wops = 0;
|
||||||
@ -163,8 +168,8 @@ retry:;
|
|||||||
flags |= txn_shrink_allowed;
|
flags |= txn_shrink_allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
eASSERT(env, txn0_owned || should_unlock);
|
eASSERT(env, txn_owned || should_unlock);
|
||||||
eASSERT(env, !txn0_owned || (flags & txn_shrink_allowed) == 0);
|
eASSERT(env, !txn_owned || (flags & txn_shrink_allowed) == 0);
|
||||||
|
|
||||||
if (!head.is_steady && unlikely(env->stuck_meta >= 0) && troika.recent != (uint8_t)env->stuck_meta) {
|
if (!head.is_steady && unlikely(env->stuck_meta >= 0) && troika.recent != (uint8_t)env->stuck_meta) {
|
||||||
NOTICE("skip %s since wagering meta-page (%u) is mispatch the recent "
|
NOTICE("skip %s since wagering meta-page (%u) is mispatch the recent "
|
||||||
|
@ -76,7 +76,7 @@ MDBX_INTERNAL int env_open(MDBX_env *env, mdbx_mode_t mode);
|
|||||||
MDBX_INTERNAL int env_info(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *out, size_t bytes, troika_t *troika);
|
MDBX_INTERNAL int env_info(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *out, size_t bytes, troika_t *troika);
|
||||||
MDBX_INTERNAL int env_sync(MDBX_env *env, bool force, bool nonblock);
|
MDBX_INTERNAL int env_sync(MDBX_env *env, bool force, bool nonblock);
|
||||||
MDBX_INTERNAL int env_close(MDBX_env *env, bool resurrect_after_fork);
|
MDBX_INTERNAL int env_close(MDBX_env *env, bool resurrect_after_fork);
|
||||||
MDBX_INTERNAL bool env_txn0_owned(const MDBX_env *env);
|
MDBX_INTERNAL MDBX_txn *env_owned_wrtxn(const MDBX_env *env);
|
||||||
MDBX_INTERNAL int __must_check_result env_page_auxbuffer(MDBX_env *env);
|
MDBX_INTERNAL int __must_check_result env_page_auxbuffer(MDBX_env *env);
|
||||||
MDBX_INTERNAL unsigned env_setup_pagesize(MDBX_env *env, const size_t pagesize);
|
MDBX_INTERNAL unsigned env_setup_pagesize(MDBX_env *env, const size_t pagesize);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user