mdbx: refine meta_checktxnid() and meta_waittxnid().

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-07-08 22:09:57 +03:00
parent 6f6c581c6e
commit d572052178

View File

@ -3919,7 +3919,7 @@ static int __must_check_result mdbx_page_split(MDBX_cursor *mc,
MDBX_val *const newdata, MDBX_val *const newdata,
pgno_t newpgno, unsigned nflags); pgno_t newpgno, unsigned nflags);
static bool meta_checktxnid(const MDBX_env *env, const MDBX_meta *meta, static bool meta_checktxnid(const MDBX_env *env, const volatile MDBX_meta *meta,
bool report); bool report);
static int __must_check_result mdbx_validate_meta_copy(MDBX_env *env, static int __must_check_result mdbx_validate_meta_copy(MDBX_env *env,
const MDBX_meta *meta, const MDBX_meta *meta,
@ -7860,7 +7860,7 @@ __cold int mdbx_thread_unregister(const MDBX_env *env) {
} }
/* check against todo4recovery://erased_by_github/libmdbx/issues/269 */ /* check against todo4recovery://erased_by_github/libmdbx/issues/269 */
static bool meta_checktxnid(const MDBX_env *env, const MDBX_meta *meta, static bool meta_checktxnid(const MDBX_env *env, const volatile MDBX_meta *meta,
bool report) { bool report) {
const txnid_t head_txnid = meta_txnid(env, meta); const txnid_t head_txnid = meta_txnid(env, meta);
const txnid_t freedb_mod_txnid = meta->mm_dbs[FREE_DBI].md_mod_txnid; const txnid_t freedb_mod_txnid = meta->mm_dbs[FREE_DBI].md_mod_txnid;
@ -7875,9 +7875,9 @@ static bool meta_checktxnid(const MDBX_env *env, const MDBX_meta *meta,
const MDBX_page *maindb_root = (env->me_map && maindb_root_pgno != P_INVALID) const MDBX_page *maindb_root = (env->me_map && maindb_root_pgno != P_INVALID)
? pgno2page(env, maindb_root_pgno) ? pgno2page(env, maindb_root_pgno)
: nullptr; : nullptr;
const uint64_t magic_and_version = const uint64_t magic_and_version =
unaligned_peek_u64(4, &meta->mm_magic_and_version); unaligned_peek_u64_volatile(4, &meta->mm_magic_and_version);
bool ok = true; bool ok = true;
if (unlikely(!head_txnid || head_txnid < freedb_mod_txnid || if (unlikely(!head_txnid || head_txnid < freedb_mod_txnid ||
(!freedb_mod_txnid && freedb_root && (!freedb_mod_txnid && freedb_root &&
@ -7934,31 +7934,37 @@ static bool meta_checktxnid(const MDBX_env *env, const MDBX_meta *meta,
return ok; return ok;
} }
__cold static bool is_timeout(uint64_t *timestamp) {
if (likely(!*timestamp)) {
*timestamp = mdbx_osal_monotime();
return false;
}
return mdbx_osal_monotime() - *timestamp > 65536 / 10;
}
/* check with timeout as the workaround /* check with timeout as the workaround
* for todo4recovery://erased_by_github/libmdbx/issues/269 */ * for todo4recovery://erased_by_github/libmdbx/issues/269 */
static int meta_waittxnid(const MDBX_env *env, const MDBX_meta *meta, static int meta_waittxnid(const MDBX_env *env, const volatile MDBX_meta *meta,
uint64_t *timestamp) { uint64_t *timestamp) {
if (likely(meta_checktxnid(env, meta, !*timestamp))) if (likely(meta_checktxnid(env, meta, !*timestamp)))
return MDBX_SUCCESS; return MDBX_SUCCESS;
if (!*timestamp) if (likely(!is_timeout(timestamp))) {
*timestamp = mdbx_osal_monotime(); #if defined(_WIN32) || defined(_WIN64)
else if (unlikely(mdbx_osal_monotime() - *timestamp > 65536 / 10)) { SwitchToThread();
mdbx_error("bailout waiting for valid snapshot %s", #elif defined(__linux__) || defined(__gnu_linux__) || defined(_UNIX03_SOURCE)
"(workaround for incoherent flaw of unified page/buffer cache)"); sched_yield();
return MDBX_CORRUPTED; #elif (defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 1)) || defined(_OPEN_THREADS)
pthread_yield();
#else
usleep(42);
#endif
return MDBX_RESULT_TRUE;
} }
#if defined(_WIN32) || defined(_WIN64) mdbx_error("bailout waiting for valid snapshot (%s)",
SwitchToThread(); "workaround for incoherent flaw of unified page/buffer cache");
#elif defined(__linux__) || defined(__gnu_linux__) || defined(_UNIX03_SOURCE) return MDBX_CORRUPTED;
sched_yield();
#elif (defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 1)) || defined(_OPEN_THREADS)
pthread_yield();
#else
usleep(42);
#endif
return MDBX_RESULT_TRUE;
} }
/* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */ /* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */
@ -8171,7 +8177,7 @@ static int mdbx_txn_renew0(MDBX_txn *txn, const unsigned flags) {
uint64_t timestamp = 0; uint64_t timestamp = 0;
while ( while (
"workaround for todo4recovery://erased_by_github/libmdbx/issues/269") { "workaround for todo4recovery://erased_by_github/libmdbx/issues/269") {
rc = meta_waittxnid(env, (const MDBX_meta *)meta, &timestamp); rc = meta_waittxnid(env, meta, &timestamp);
if (likely(rc == MDBX_SUCCESS)) if (likely(rc == MDBX_SUCCESS))
break; break;
if (unlikely(rc != MDBX_RESULT_TRUE)) if (unlikely(rc != MDBX_RESULT_TRUE))