From 242afea71db4a7c2c8fb027da62107d057a52993 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Sun, 23 Apr 2023 10:00:36 +0700 Subject: [PATCH] mdbx_v0.12.5 (#103) --- mdbx/mdbx.c | 471 ++++++++++++++++++++++--------------------- mdbx/mdbx.h | 12 +- mdbxdist/mdbx.c | 471 ++++++++++++++++++++++--------------------- mdbxdist/mdbx.h | 12 +- mdbxdist/mdbx_chk.c | 17 +- mdbxdist/mdbx_copy.c | 17 +- mdbxdist/mdbx_drop.c | 17 +- mdbxdist/mdbx_dump.c | 17 +- mdbxdist/mdbx_load.c | 17 +- mdbxdist/mdbx_stat.c | 28 ++- 10 files changed, 579 insertions(+), 500 deletions(-) diff --git a/mdbx/mdbx.c b/mdbx/mdbx.c index e4c7004..61de9b7 100644 --- a/mdbx/mdbx.c +++ b/mdbx/mdbx.c @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -808,14 +808,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ @@ -7325,9 +7330,8 @@ static int __must_check_result page_split(MDBX_cursor *mc, MDBX_val *const newdata, pgno_t newpgno, const unsigned naf); -static int coherency_timeout(uint64_t *timestamp, pgno_t pgno); -static bool coherency_check_meta(const MDBX_env *env, - const volatile MDBX_meta *meta, bool report); +static int coherency_timeout(uint64_t *timestamp, intptr_t pgno, + const MDBX_env *env); static int __must_check_result validate_meta_copy(MDBX_env *env, const MDBX_meta *meta, MDBX_meta *dest); @@ -8707,7 +8711,7 @@ static void iov_callback4dirtypages(iov_ctx_t *ctx, size_t offset, void *data, WARNING("catch delayed/non-arrived page %" PRIaPGNO " %s", wp->mp_pgno, "(workaround for incoherent flaw of unified page/buffer cache)"); do - if (coherency_timeout(&ctx->coherency_timestamp, wp->mp_pgno) != + if (coherency_timeout(&ctx->coherency_timestamp, wp->mp_pgno, env) != MDBX_RESULT_TRUE) { ctx->err = MDBX_PROBLEM; break; @@ -12271,14 +12275,6 @@ __cold int mdbx_env_sync_ex(MDBX_env *env, bool force, bool nonblock) { return env_sync(env, force, nonblock); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_sync(MDBX_env *env) { return __inline_mdbx_env_sync(env); } - -__cold int mdbx_env_sync_poll(MDBX_env *env) { - return __inline_mdbx_env_sync_poll(env); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Back up parent txn's cursors, then grab the originals for tracking */ static int cursor_shadow(MDBX_txn *parent, MDBX_txn *nested) { tASSERT(parent, parent->mt_cursors[FREE_DBI] == nullptr); @@ -12344,8 +12340,8 @@ static void cursors_eot(MDBX_txn *txn, const bool merge) { if (bk) { MDBX_xcursor *mx = mc->mc_xcursor; tASSERT(txn, txn->mt_parent != NULL); - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6001, "Using uninitialized memory '*mc->mc_backup'."); + /* Zap: Using uninitialized memory '*mc->mc_backup'. */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001); ENSURE(txn->mt_env, bk->mc_signature == MDBX_MC_LIVE); tASSERT(txn, mx == bk->mc_xcursor); if (stage == MDBX_MC_WAIT4EOT /* Cursor was closed by user */) @@ -12627,20 +12623,26 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, (!freedb_mod_txnid && freedb_root && likely(magic_and_version == MDBX_DATA_MAGIC)))) { if (report) - WARNING("catch invalid %sdb.mod_txnid %" PRIaTXN - " for meta_txnid %" PRIaTXN " %s", - "free", freedb_mod_txnid, txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING( + "catch invalid %sdb.mod_txnid %" PRIaTXN " for meta_txnid %" PRIaTXN + " %s", + "free", freedb_mod_txnid, txnid, + (env->me_stuck_meta < 0) + ? "(workaround for incoherent flaw of unified page/buffer cache)" + : "(wagering meta)"); ok = false; } if (unlikely(txnid < maindb_mod_txnid || (!maindb_mod_txnid && maindb_root && likely(magic_and_version == MDBX_DATA_MAGIC)))) { if (report) - WARNING("catch invalid %sdb.mod_txnid %" PRIaTXN - " for meta_txnid %" PRIaTXN " %s", - "main", maindb_mod_txnid, txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING( + "catch invalid %sdb.mod_txnid %" PRIaTXN " for meta_txnid %" PRIaTXN + " %s", + "main", maindb_mod_txnid, txnid, + (env->me_stuck_meta < 0) + ? "(workaround for incoherent flaw of unified page/buffer cache)" + : "(wagering meta)"); ok = false; } if (likely(freedb_root && freedb_mod_txnid)) { @@ -12650,11 +12652,12 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, const txnid_t root_txnid = freedb_root->mp_txnid; if (unlikely(root_txnid != freedb_mod_txnid)) { if (report) - WARNING( - "catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN - " for %sdb.mod_txnid %" PRIaTXN " %s", - freedb_root_pgno, root_txnid, "free", freedb_mod_txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING("catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN + " for %sdb.mod_txnid %" PRIaTXN " %s", + freedb_root_pgno, root_txnid, "free", freedb_mod_txnid, + (env->me_stuck_meta < 0) ? "(workaround for incoherent flaw of " + "unified page/buffer cache)" + : "(wagering meta)"); ok = false; } } @@ -12665,11 +12668,12 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, const txnid_t root_txnid = maindb_root->mp_txnid; if (unlikely(root_txnid != maindb_mod_txnid)) { if (report) - WARNING( - "catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN - " for %sdb.mod_txnid %" PRIaTXN " %s", - maindb_root_pgno, root_txnid, "main", maindb_mod_txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING("catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN + " for %sdb.mod_txnid %" PRIaTXN " %s", + maindb_root_pgno, root_txnid, "main", maindb_mod_txnid, + (env->me_stuck_meta < 0) ? "(workaround for incoherent flaw of " + "unified page/buffer cache)" + : "(wagering meta)"); ok = false; } } @@ -12681,15 +12685,16 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, return ok; } -__cold static int coherency_timeout(uint64_t *timestamp, pgno_t pgno) { +__cold static int coherency_timeout(uint64_t *timestamp, intptr_t pgno, + const MDBX_env *env) { if (likely(timestamp && *timestamp == 0)) *timestamp = osal_monotime(); else if (unlikely(!timestamp || osal_monotime() - *timestamp > osal_16dot16_to_monotime(65536 / 10))) { - if (pgno) - ERROR("bailout waiting for %" PRIaPGNO " page arrival %s", pgno, + if (pgno >= 0 && pgno != env->me_stuck_meta) + ERROR("bailout waiting for %" PRIuSIZE " page arrival %s", pgno, "(workaround for incoherent flaw of unified page/buffer cache)"); - else + else if (env->me_stuck_meta < 0) ERROR("bailout waiting for valid snapshot (%s)", "workaround for incoherent flaw of unified page/buffer cache"); return MDBX_PROBLEM; @@ -12710,23 +12715,25 @@ __cold static int coherency_timeout(uint64_t *timestamp, pgno_t pgno) { /* check with timeout as the workaround * for https://libmdbx.dqdkfa.ru/dead-github/issues/269 */ -__hot static int coherency_check_readed(const MDBX_env *env, - const txnid_t txnid, - const volatile MDBX_db *dbs, - const volatile MDBX_meta *meta, - uint64_t *timestamp) { - const bool report = !(timestamp && *timestamp); - if (unlikely(!coherency_check(env, txnid, dbs, meta, report))) - return coherency_timeout(timestamp, 0); +__hot static int coherency_check_head(MDBX_txn *txn, const meta_ptr_t head, + uint64_t *timestamp) { + /* Copy the DB info and flags */ + txn->mt_geo = head.ptr_v->mm_geo; + memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); + txn->mt_canary = head.ptr_v->mm_canary; + + if (unlikely(!coherency_check(txn->mt_env, head.txnid, txn->mt_dbs, + head.ptr_v, *timestamp == 0))) + return coherency_timeout(timestamp, -1, txn->mt_env); return MDBX_SUCCESS; } static int coherency_check_written(const MDBX_env *env, const txnid_t txnid, const volatile MDBX_meta *meta, - uint64_t *timestamp) { + const intptr_t pgno, uint64_t *timestamp) { const bool report = !(timestamp && *timestamp); const txnid_t head_txnid = meta_txnid(meta); - if (unlikely(head_txnid < MIN_TXNID || (head_txnid < txnid))) { + if (unlikely(head_txnid < MIN_TXNID || head_txnid < txnid)) { if (report) { env->me_lck->mti_pgop_stat.incoherence.weak = (env->me_lck->mti_pgop_stat.incoherence.weak >= INT32_MAX) @@ -12737,16 +12744,18 @@ static int coherency_check_written(const MDBX_env *env, const txnid_t txnid, bytes2pgno(env, ptr_dist(meta, env->me_map)), "(workaround for incoherent flaw of unified page/buffer cache)"); } - return coherency_timeout(timestamp, 0); + return coherency_timeout(timestamp, pgno, env); } - return coherency_check_readed(env, head_txnid, meta->mm_dbs, meta, timestamp); + if (unlikely(!coherency_check(env, head_txnid, meta->mm_dbs, meta, report))) + return coherency_timeout(timestamp, pgno, env); + return MDBX_SUCCESS; } -static bool coherency_check_meta(const MDBX_env *env, +static bool check_meta_coherency(const MDBX_env *env, const volatile MDBX_meta *meta, bool report) { uint64_t timestamp = 0; - return coherency_check_written(env, 0, meta, report ? ×tamp : nullptr) == - MDBX_SUCCESS; + return coherency_check_written(env, 0, meta, -1, + report ? ×tamp : nullptr) == MDBX_SUCCESS; } /* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */ @@ -12858,10 +12867,6 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { /* Snap the state from current meta-head */ txn->mt_txnid = head.txnid; - txn->mt_geo = head.ptr_v->mm_geo; - memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - txn->mt_canary = head.ptr_v->mm_canary; - if (likely(env->me_stuck_meta < 0) && unlikely(meta_should_retry(env, &troika) || head.txnid < atomic_load64(&env->me_lck->mti_oldest_reader, @@ -12879,8 +12884,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { continue; } - rc = coherency_check_readed(env, head.txnid, txn->mt_dbs, head.ptr_v, - ×tamp); + rc = coherency_check_head(txn, head, ×tamp); jitter4testing(false); if (likely(rc == MDBX_SUCCESS)) break; @@ -12950,14 +12954,12 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { const meta_ptr_t head = meta_recent(env, &txn->tw.troika); uint64_t timestamp = 0; while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - rc = coherency_check_readed(env, head.txnid, head.ptr_v->mm_dbs, - head.ptr_v, ×tamp); + rc = coherency_check_head(txn, head, ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) goto bailout; } - txn->mt_canary = head.ptr_c->mm_canary; eASSERT(env, meta_txnid(head.ptr_v) == head.txnid); txn->mt_txnid = safe64_txnid_next(head.txnid); if (unlikely(txn->mt_txnid > MAX_TXNID)) { @@ -12982,10 +12984,6 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { env->me_txn = txn; txn->mt_numdbs = env->me_numdbs; memcpy(txn->mt_dbiseqs, env->me_dbiseqs, txn->mt_numdbs * sizeof(unsigned)); - /* Copy the DB info and flags */ - memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - /* Moved to here to avoid a data race in read TXNs */ - txn->mt_geo = head.ptr_c->mm_geo; if ((txn->mt_flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC) { rc = dpl_alloc(txn); @@ -13198,13 +13196,6 @@ int mdbx_txn_renew(MDBX_txn *txn) { return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, - MDBX_txn **ret) { - return __inline_mdbx_txn_begin(env, parent, flags, ret); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - int mdbx_txn_set_userctx(MDBX_txn *txn, void *ctx) { int rc = check_txn(txn, MDBX_TXN_FINISHED); if (unlikely(rc != MDBX_SUCCESS)) @@ -13288,6 +13279,9 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, (MDBX_GOOFY_MSVC_STATIC_ANALYZER && base > size) ? size : base); txn->mt_dbs = ptr_disp(txn, base); txn->mt_cursors = ptr_disp(txn->mt_dbs, sizeof(MDBX_db) * env->me_maxdbs); +#if MDBX_DEBUG + txn->mt_cursors[FREE_DBI] = nullptr; /* avoid SIGSEGV in an assertion later */ +#endif /* MDBX_DEBUG */ txn->mt_dbistate = ptr_disp(txn, size - env->me_maxdbs); txn->mt_dbxs = env->me_dbxs; /* static */ txn->mt_flags = flags; @@ -15151,10 +15145,6 @@ static __always_inline bool check_dbi(MDBX_txn *txn, MDBX_dbi dbi, return dbi_import(txn, dbi); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_txn_commit(MDBX_txn *txn) { return __inline_mdbx_txn_commit(txn); } -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Merge child txn into parent */ static __inline void txn_merge(MDBX_txn *const parent, MDBX_txn *const txn, const size_t parent_retired_len) { @@ -16536,7 +16526,7 @@ __cold static MDBX_page *meta_model(const MDBX_env *env, MDBX_page *model, model_meta->mm_dbs[MAIN_DBI].md_root = P_INVALID; meta_set_txnid(env, model_meta, MIN_TXNID + num); unaligned_poke_u64(4, model_meta->mm_sign, meta_sign(model_meta)); - eASSERT(env, coherency_check_meta(env, model_meta, true)); + eASSERT(env, check_meta_coherency(env, model_meta, true)); return ptr_disp(model, env->me_psize); } @@ -16707,7 +16697,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, goto fail; } meta_set_txnid(env, pending, txnid); - eASSERT(env, coherency_check_meta(env, pending, true)); + eASSERT(env, check_meta_coherency(env, pending, true)); } } } @@ -16753,7 +16743,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, rc = (flags & MDBX_SAFE_NOSYNC) ? MDBX_RESULT_TRUE /* carry non-steady */ : MDBX_RESULT_FALSE /* carry steady */; } - eASSERT(env, coherency_check_meta(env, pending, true)); + eASSERT(env, check_meta_coherency(env, pending, true)); /* Steady or Weak */ if (rc == MDBX_RESULT_FALSE /* carry steady */) { @@ -16858,7 +16848,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, /* LY: 'commit' the meta */ meta_update_end(env, target, unaligned_peek_u64(4, pending->mm_txnid_b)); jitter4testing(true); - eASSERT(env, coherency_check_meta(env, target, true)); + eASSERT(env, check_meta_coherency(env, target, true)); } else { /* dangerous case (target == head), only mm_sign could * me updated, check assertions once again */ @@ -16931,8 +16921,9 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, uint64_t timestamp = 0; while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - rc = - coherency_check_written(env, pending->unsafe_txnid, target, ×tamp); + rc = coherency_check_written(env, pending->unsafe_txnid, target, + bytes2pgno(env, ptr_dist(target, env->me_map)), + ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) @@ -16961,7 +16952,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, pending->mm_geo.upper, impilict_shrink); if (rc != MDBX_SUCCESS && rc != MDBX_EPERM) goto fail; - eASSERT(env, coherency_check_meta(env, target, true)); + eASSERT(env, check_meta_coherency(env, target, true)); } MDBX_lockinfo *const lck = env->me_lck_mmap.lck; @@ -17200,10 +17191,10 @@ __cold static intptr_t get_reasonable_db_maxsize(intptr_t *cached_result) { return *cached_result; } -__cold LIBMDBX_API int -mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, - intptr_t size_upper, intptr_t growth_step, - intptr_t shrink_threshold, intptr_t pagesize) { +__cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, + intptr_t size_now, intptr_t size_upper, + intptr_t growth_step, + intptr_t shrink_threshold, intptr_t pagesize) { int rc = check_env(env, false); if (unlikely(rc != MDBX_SUCCESS)) return rc; @@ -17455,7 +17446,6 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, ENSURE(env, pagesize == (intptr_t)env->me_psize); MDBX_meta meta; memset(&meta, 0, sizeof(meta)); - const MDBX_geo *current_geo; if (!inside_txn) { eASSERT(env, need_unlock); const meta_ptr_t head = meta_recent(env, &env->me_txn0->tw.troika); @@ -17463,14 +17453,13 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, uint64_t timestamp = 0; while ("workaround for " "https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - meta = *head.ptr_c; - rc = coherency_check_readed(env, head.txnid, meta.mm_dbs, &meta, - ×tamp); + rc = coherency_check_head(env->me_txn0, head, ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) goto bailout; } + meta = *head.ptr_c; const txnid_t txnid = safe64_txnid_next(head.txnid); if (unlikely(txnid > MAX_TXNID)) { rc = MDBX_TXN_FULL; @@ -17478,11 +17467,10 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, goto bailout; } meta_set_txnid(env, &meta, txnid); - current_geo = &meta.mm_geo; - } else { - current_geo = &env->me_txn->mt_geo; } + const MDBX_geo *const current_geo = + &(env->me_txn ? env->me_txn : env->me_txn0)->mt_geo; /* update env-geo to avoid influences */ env->me_dbgeo.now = pgno2bytes(env, current_geo->now); env->me_dbgeo.lower = pgno2bytes(env, current_geo->lower); @@ -17585,28 +17573,6 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) { - return __inline_mdbx_env_set_mapsize(env, size); -} - -__cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { - return __inline_mdbx_env_set_maxdbs(env, dbs); -} - -__cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) { - return __inline_mdbx_env_get_maxdbs(env, dbs); -} - -__cold int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) { - return __inline_mdbx_env_set_maxreaders(env, readers); -} - -__cold int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers) { - return __inline_mdbx_env_get_maxreaders(env, readers); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold static int alloc_page_buf(MDBX_env *env) { return env->me_pbuf ? MDBX_SUCCESS : osal_memalign_alloc(env->me_os_psize, @@ -18410,9 +18376,9 @@ __cold static int __must_check_result override_meta(MDBX_env *env, MDBX_meta *const model = page_meta(page); meta_set_txnid(env, model, txnid); if (txnid) - eASSERT(env, coherency_check_meta(env, model, true)); + eASSERT(env, check_meta_coherency(env, model, true)); if (shape) { - if (txnid && unlikely(!coherency_check_meta(env, shape, false))) { + if (txnid && unlikely(!check_meta_coherency(env, shape, false))) { ERROR("bailout overriding meta-%zu since model failed " "freedb/maindb %s-check for txnid #%" PRIaTXN, target, "pre", constmeta_txnid(shape)); @@ -18436,7 +18402,7 @@ __cold static int __must_check_result override_meta(MDBX_env *env, model->mm_dbs[MAIN_DBI].md_root != P_INVALID)) memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, sizeof(model->mm_magic_and_version)); - if (unlikely(!coherency_check_meta(env, model, false))) { + if (unlikely(!check_meta_coherency(env, model, false))) { ERROR("bailout overriding meta-%zu since model failed " "freedb/maindb %s-check for txnid #%" PRIaTXN, target, "post", txnid); @@ -18486,7 +18452,10 @@ __cold static int __must_check_result override_meta(MDBX_env *env, osal_flush_incoherent_mmap(env->me_map, pgno2bytes(env, NUM_METAS), env->me_os_psize); } - eASSERT(env, !env->me_txn && !env->me_txn0); + eASSERT(env, (!env->me_txn && !env->me_txn0) || + (env->me_stuck_meta == (int)target && + (env->me_flags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) == + MDBX_EXCLUSIVE)); return rc; } @@ -19013,7 +18982,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname, if (!(flags & (MDBX_RDONLY | MDBX_SAFE_NOSYNC | MDBX_NOMETASYNC | MDBX_EXCLUSIVE))) { if (MDBX_AVOID_MSYNC && (flags & MDBX_WRITEMAP)) { - /* Запрошен режим MDBX_SAFE_NOSYNC | MDBX_WRITEMAP при активной опции + /* Запрошен режим MDBX_SYNC_DURABLE | MDBX_WRITEMAP при активной опции * MDBX_AVOID_MSYNC. * * 1) В этой комбинации наиболее выгодно использовать WriteFileGather(), @@ -19485,12 +19454,6 @@ __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_close(MDBX_env *env) { - return __inline_mdbx_env_close(env); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Search for key within a page, using binary search. * Returns the smallest entry larger or equal to the key. * Updates the cursor index with the index of the found entry. @@ -20044,19 +20007,11 @@ static __noinline int node_read_bigdata(MDBX_cursor *mc, const MDBX_node *node, if (!MDBX_DISABLE_VALIDATION) { const MDBX_env *env = mc->mc_txn->mt_env; const size_t dsize = data->iov_len; - if (unlikely(node_size_len(node_ks(node), dsize) <= env->me_leaf_nodemax) && - mc->mc_dbi != FREE_DBI) - poor_page(mp, "too small data (%zu bytes) for bigdata-node", dsize); const unsigned npages = number_of_ovpages(env, dsize); - if (unlikely(lp.page->mp_pages != npages)) { - if (lp.page->mp_pages < npages) - return bad_page(lp.page, - "too less n-pages %u for bigdata-node (%zu bytes)", - lp.page->mp_pages, dsize); - else if (mc->mc_dbi != FREE_DBI) - poor_page(lp.page, "extra n-pages %u for bigdata-node (%zu bytes)", - lp.page->mp_pages, dsize); - } + if (unlikely(lp.page->mp_pages < npages)) + return bad_page(lp.page, + "too less n-pages %u for bigdata-node (%zu bytes)", + lp.page->mp_pages, dsize); } return MDBX_SUCCESS; } @@ -25859,8 +25814,8 @@ __cold int mdbx_env_copy(MDBX_env *env, const char *dest_path, return rc; } -LIBMDBX_API int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest_path, - MDBX_copy_flags_t flags) { +__cold int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest_path, + MDBX_copy_flags_t flags) { #endif /* Windows */ int rc = check_env(env, true); @@ -26066,12 +26021,6 @@ __cold int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *arg) { return MDBX_SUCCESS; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_stat(const MDBX_env *env, MDBX_stat *stat, size_t bytes) { - return __inline_mdbx_env_stat(env, stat, bytes); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - static void stat_get(const MDBX_db *db, MDBX_stat *st, size_t bytes) { st->ms_depth = db->md_depth; st->ms_branch_pages = db->md_branch_pages; @@ -26243,13 +26192,6 @@ __cold int mdbx_dbi_dupsort_depthmask(MDBX_txn *txn, MDBX_dbi dbi, return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, - size_t bytes) { - return __inline_mdbx_env_info(env, info, bytes); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold static int fetch_envinfo_ex(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *arg, const size_t bytes) { @@ -26473,7 +26415,7 @@ static __inline MDBX_cmp_func *get_default_datacmp(unsigned flags) { static int dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp) { - /* LY: so, accepting only three cases for the table's flags: + /* Accepting only three cases: * 1) user_flags and both comparators are zero * = assume that a by-default mode/flags is requested for reading; * 2) user_flags exactly the same @@ -26495,6 +26437,10 @@ static int dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, /* make sure flags changes get committed */ txn->mt_dbs[dbi].md_flags = user_flags & DB_PERSISTENT_FLAGS; txn->mt_flags |= MDBX_TXN_DIRTY; + /* обнуляем компараторы для установки в соответствии с флагами, + * либо заданных пользователем */ + txn->mt_dbxs[dbi].md_cmp = nullptr; + txn->mt_dbxs[dbi].md_dcmp = nullptr; } else { return /* FIXME: return extended info */ MDBX_INCOMPATIBLE; } @@ -26913,12 +26859,6 @@ int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, return MDBX_SUCCESS; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { - return __inline_mdbx_dbi_flags(txn, dbi, flags); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - static int drop_tree(MDBX_cursor *mc, const bool may_have_subDBs) { int rc = page_search(mc, NULL, MDBX_PS_FIRST); if (likely(rc == MDBX_SUCCESS)) { @@ -27428,16 +27368,6 @@ __cold static txnid_t kick_longlived_readers(MDBX_env *env, return oldest; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { - return __inline_mdbx_env_set_syncbytes(env, threshold); -} - -__cold int mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) { - return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr) { int rc = check_env(env, false); if (unlikely(rc != MDBX_SUCCESS)) @@ -28511,16 +28441,6 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, /*----------------------------------------------------------------------------*/ -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold MDBX_NOTHROW_CONST_FUNCTION intptr_t mdbx_limits_pgsize_min(void) { - return __inline_mdbx_limits_pgsize_min(); -} - -__cold MDBX_NOTHROW_CONST_FUNCTION intptr_t mdbx_limits_pgsize_max(void) { - return __inline_mdbx_limits_pgsize_max(); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold intptr_t mdbx_limits_dbsize_min(intptr_t pagesize) { if (pagesize < 1) pagesize = (intptr_t)mdbx_default_pagesize(); @@ -28624,16 +28544,6 @@ uint32_t mdbx_key_from_ptrfloat(const float *const ieee754_32bit) { return float2key(ieee754_32bit); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -MDBX_NOTHROW_CONST_FUNCTION uint64_t mdbx_key_from_int64(const int64_t i64) { - return __inline_mdbx_key_from_int64(i64); -} - -MDBX_NOTHROW_CONST_FUNCTION uint32_t mdbx_key_from_int32(const int32_t i32) { - return __inline_mdbx_key_from_int32(i32); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - #define IEEE754_DOUBLE_MANTISSA_SIZE 52 #define IEEE754_DOUBLE_EXPONENTA_BIAS 0x3FF #define IEEE754_DOUBLE_EXPONENTA_MAX 0x7FF @@ -29442,6 +29352,109 @@ __cold void global_ctor(void) { #endif /* #if 0 */ } +/*------------------------------------------------------------------------------ + * Legacy API */ + +#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API + +LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, + MDBX_txn_flags_t flags, MDBX_txn **ret) { + return __inline_mdbx_txn_begin(env, parent, flags, ret); +} + +LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn) { + return __inline_mdbx_txn_commit(txn); +} + +LIBMDBX_API __cold int mdbx_env_stat(const MDBX_env *env, MDBX_stat *stat, + size_t bytes) { + return __inline_mdbx_env_stat(env, stat, bytes); +} + +LIBMDBX_API __cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, + size_t bytes) { + return __inline_mdbx_env_info(env, info, bytes); +} + +LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { + return __inline_mdbx_dbi_flags(txn, dbi, flags); +} + +LIBMDBX_API __cold int mdbx_env_sync(MDBX_env *env) { + return __inline_mdbx_env_sync(env); +} + +LIBMDBX_API __cold int mdbx_env_sync_poll(MDBX_env *env) { + return __inline_mdbx_env_sync_poll(env); +} + +LIBMDBX_API __cold int mdbx_env_close(MDBX_env *env) { + return __inline_mdbx_env_close(env); +} + +LIBMDBX_API __cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) { + return __inline_mdbx_env_set_mapsize(env, size); +} + +LIBMDBX_API __cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { + return __inline_mdbx_env_set_maxdbs(env, dbs); +} + +LIBMDBX_API __cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) { + return __inline_mdbx_env_get_maxdbs(env, dbs); +} + +LIBMDBX_API __cold int mdbx_env_set_maxreaders(MDBX_env *env, + unsigned readers) { + return __inline_mdbx_env_set_maxreaders(env, readers); +} + +LIBMDBX_API __cold int mdbx_env_get_maxreaders(const MDBX_env *env, + unsigned *readers) { + return __inline_mdbx_env_get_maxreaders(env, readers); +} + +LIBMDBX_API __cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { + return __inline_mdbx_env_set_syncbytes(env, threshold); +} + +LIBMDBX_API __cold int mdbx_env_get_syncbytes(const MDBX_env *env, + size_t *threshold) { + return __inline_mdbx_env_get_syncbytes(env, threshold); +} + +LIBMDBX_API __cold int mdbx_env_set_syncperiod(MDBX_env *env, + unsigned seconds_16dot16) { + return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16); +} + +LIBMDBX_API __cold int mdbx_env_get_syncperiod(const MDBX_env *env, + unsigned *seconds_16dot16) { + return __inline_mdbx_env_get_syncperiod(env, seconds_16dot16); +} + +LIBMDBX_API __cold MDBX_NOTHROW_CONST_FUNCTION intptr_t +mdbx_limits_pgsize_min(void) { + return __inline_mdbx_limits_pgsize_min(); +} + +LIBMDBX_API __cold MDBX_NOTHROW_CONST_FUNCTION intptr_t +mdbx_limits_pgsize_max(void) { + return __inline_mdbx_limits_pgsize_max(); +} + +LIBMDBX_API MDBX_NOTHROW_CONST_FUNCTION uint64_t +mdbx_key_from_int64(const int64_t i64) { + return __inline_mdbx_key_from_int64(i64); +} + +LIBMDBX_API MDBX_NOTHROW_CONST_FUNCTION uint32_t +mdbx_key_from_int32(const int32_t i32) { + return __inline_mdbx_key_from_int32(i32); +} + +#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ + /******************************************************************************/ __dll_export @@ -29679,7 +29692,10 @@ __dll_export }; #ifdef __SANITIZE_ADDRESS__ -LIBMDBX_API __attribute__((__weak__)) const char *__asan_default_options(void) { +#if !defined(_MSC_VER) || __has_attribute(weak) +LIBMDBX_API __attribute__((__weak__)) +#endif +const char *__asan_default_options(void) { return "symbolize=1:allow_addr2line=1:" #if MDBX_DEBUG "debug=1:" @@ -29753,7 +29769,8 @@ static int ntstatus2errcode(NTSTATUS status) { OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.Internal = status; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6387, "'_Param_(1)' could be '0'"); + /* Zap: '_Param_(1)' could be '0' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6387); return GetOverlappedResult(NULL, &ov, &dummy, FALSE) ? MDBX_SUCCESS : (int)GetLastError(); } @@ -29788,8 +29805,8 @@ extern NTSTATUS NTAPI NtMapViewOfSection( extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN OPTIONAL PVOID BaseAddress); -MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(28251, - "Inconsistent annotation for 'NtClose'...") +/* Zap: Inconsistent annotation for 'NtClose'... */ +MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(28251) extern NTSTATUS NTAPI NtClose(HANDLE Handle); extern NTSTATUS NTAPI NtAllocateVirtualMemory( @@ -30020,17 +30037,16 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, va_list ap) { va_list ones; va_copy(ones, ap); - int needed = vsnprintf(nullptr, 0, fmt, ap); + const int needed = vsnprintf(nullptr, 0, fmt, ones); + va_end(ones); if (unlikely(needed < 0 || needed >= INT_MAX)) { *strp = nullptr; - va_end(ones); return needed; } *strp = osal_malloc(needed + (size_t)1); if (unlikely(*strp == nullptr)) { - va_end(ones); #if defined(_WIN32) || defined(_WIN64) SetLastError(MDBX_ENOMEM); #else @@ -30039,9 +30055,7 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, return -1; } - int actual = vsnprintf(*strp, needed + (size_t)1, fmt, ones); - va_end(ones); - + const int actual = vsnprintf(*strp, needed + (size_t)1, fmt, ap); assert(actual == needed); if (unlikely(actual < 0)) { osal_free(*strp); @@ -30055,7 +30069,7 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, MDBX_INTERNAL_FUNC int osal_asprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int rc = osal_vasprintf(strp, fmt, ap); + const int rc = osal_vasprintf(strp, fmt, ap); va_end(ap); return rc; } @@ -30509,8 +30523,8 @@ MDBX_INTERNAL_FUNC void osal_ioring_walk( if (bytes & ior_WriteFile_flag) { data = Ptr64ToPtr(item->sgv[0].Buffer); bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { if (data + ior->pagesize != item->sgv[i].Buffer) { callback(ctx, offset, data, bytes); @@ -30557,8 +30571,8 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (bytes & ior_WriteFile_flag) { assert(ior->overlapped_fd && fd == ior->overlapped_fd); bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { bytes += ior->pagesize; ++i; @@ -30697,8 +30711,8 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { size_t i = 1, bytes = item->single.iov_len - ior_WriteFile_flag; if (bytes & ior_WriteFile_flag) { bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { bytes += ior->pagesize; ++i; @@ -30793,8 +30807,8 @@ MDBX_INTERNAL_FUNC void osal_ioring_reset(osal_ioring_t *ior) { ior_put_event(ior, item->ov.hEvent); size_t i = 1; if ((item->single.iov_len & ior_WriteFile_flag) == 0) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) ++i; } @@ -30813,8 +30827,8 @@ static void ior_cleanup(osal_ioring_t *ior, const size_t since) { osal_ioring_reset(ior); #if defined(_WIN32) || defined(_WIN64) for (size_t i = since; i < ior->event_stack; ++i) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6001, "Using uninitialized memory '**ior.event_pool'"); + /* Zap: Using uninitialized memory '**ior.event_pool' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001); CloseHandle(ior->event_pool[i]); } ior->event_stack = 0; @@ -32454,7 +32468,8 @@ retry_mapview:; #endif /* POSIX / Windows */ - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6287, "Redundant code"); + /* Zap: Redundant code */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6287); assert(rc != MDBX_SUCCESS || (map->base != nullptr && map->base != MAP_FAILED && map->current == size && map->limit == limit && @@ -33254,10 +33269,10 @@ __dll_export const struct MDBX_version_info mdbx_version = { 0, 12, - 3, - 30, - {"2023-02-14T12:09:44+03:00", "056bb01c9eb5f3d038255f79108076b072918bd0", "29d12f1fc3ab10a41a6edab054ee884b9c57e6ee", - "v0.12.3-30-g29d12f1f"}, + 5, + 0, + {"2023-04-18T11:03:31+03:00", "cf967b230d768c074762cc51bf89c6ad3ea726a9", "9b8291457bfc7322e258f7efd81a5206a3d99e9d", + "v0.12.5-0-g9b829145"}, sourcery}; __dll_export @@ -33465,9 +33480,9 @@ int mdbx_txn_lock(MDBX_env *env, bool dontwait) { } if (env->me_flags & MDBX_EXCLUSIVE) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 26115, "Failing to release lock 'env->me_windowsbug_lock' in function " - "'mdbx_txn_lock'"); + /* Zap: Failing to release lock 'env->me_windowsbug_lock' + * in function 'mdbx_txn_lock' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return MDBX_SUCCESS; } @@ -33488,9 +33503,9 @@ int mdbx_txn_lock(MDBX_env *env, bool dontwait) { } } if (rc == MDBX_SUCCESS) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 26115, "Failing to release lock 'env->me_windowsbug_lock' in function " - "'mdbx_txn_lock'"); + /* Zap: Failing to release lock 'env->me_windowsbug_lock' + * in function 'mdbx_txn_lock' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return rc; } diff --git a/mdbx/mdbx.h b/mdbx/mdbx.h index ce46b6f..cc42298 100644 --- a/mdbx/mdbx.h +++ b/mdbx/mdbx.h @@ -2060,7 +2060,9 @@ LIBMDBX_API const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, * \returns a non-zero error value on failure and 0 on success. */ LIBMDBX_API int mdbx_env_create(MDBX_env **penv); -/** \brief MDBX environment options. */ +/** \brief MDBX environment extra runtime options. + * \ingroup c_settings + * \see mdbx_env_set_option() \see mdbx_env_get_option() */ enum MDBX_option_t { /** \brief Controls the maximum number of named databases for the environment. * @@ -2268,7 +2270,7 @@ enum MDBX_option_t { typedef enum MDBX_option_t MDBX_option_t; #endif -/** \brief Sets the value of a runtime options for an environment. +/** \brief Sets the value of a extra runtime options for an environment. * \ingroup c_settings * * \param [in] env An environment handle returned by \ref mdbx_env_create(). @@ -2281,7 +2283,7 @@ typedef enum MDBX_option_t MDBX_option_t; LIBMDBX_API int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, uint64_t value); -/** \brief Gets the value of runtime options from an environment. +/** \brief Gets the value of extra runtime options from an environment. * \ingroup c_settings * * \param [in] env An environment handle returned by \ref mdbx_env_create(). @@ -3055,6 +3057,8 @@ LIBMDBX_API int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *fd); * it is reasonable to know some details in order to make optimal decisions * when choosing parameters. * + * \see mdbx_env_info_ex() + * * Both \ref mdbx_env_set_geometry() and legacy \ref mdbx_env_set_mapsize() are * inapplicable to read-only opened environment. * @@ -3164,7 +3168,7 @@ LIBMDBX_API int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *fd); * \note Actual values may be different than your have specified because of * rounding to specified database page size, the system page size and/or the * size of the system virtual memory management unit. You can get actual values - * by \ref mdbx_env_sync_ex() or see by using the tool `mdbx_chk` with the `-v` + * by \ref mdbx_env_info_ex() or see by using the tool `mdbx_chk` with the `-v` * option. * * Legacy \ref mdbx_env_set_mapsize() correspond to calling diff --git a/mdbxdist/mdbx.c b/mdbxdist/mdbx.c index e4c7004..61de9b7 100644 --- a/mdbxdist/mdbx.c +++ b/mdbxdist/mdbx.c @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -808,14 +808,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ @@ -7325,9 +7330,8 @@ static int __must_check_result page_split(MDBX_cursor *mc, MDBX_val *const newdata, pgno_t newpgno, const unsigned naf); -static int coherency_timeout(uint64_t *timestamp, pgno_t pgno); -static bool coherency_check_meta(const MDBX_env *env, - const volatile MDBX_meta *meta, bool report); +static int coherency_timeout(uint64_t *timestamp, intptr_t pgno, + const MDBX_env *env); static int __must_check_result validate_meta_copy(MDBX_env *env, const MDBX_meta *meta, MDBX_meta *dest); @@ -8707,7 +8711,7 @@ static void iov_callback4dirtypages(iov_ctx_t *ctx, size_t offset, void *data, WARNING("catch delayed/non-arrived page %" PRIaPGNO " %s", wp->mp_pgno, "(workaround for incoherent flaw of unified page/buffer cache)"); do - if (coherency_timeout(&ctx->coherency_timestamp, wp->mp_pgno) != + if (coherency_timeout(&ctx->coherency_timestamp, wp->mp_pgno, env) != MDBX_RESULT_TRUE) { ctx->err = MDBX_PROBLEM; break; @@ -12271,14 +12275,6 @@ __cold int mdbx_env_sync_ex(MDBX_env *env, bool force, bool nonblock) { return env_sync(env, force, nonblock); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_sync(MDBX_env *env) { return __inline_mdbx_env_sync(env); } - -__cold int mdbx_env_sync_poll(MDBX_env *env) { - return __inline_mdbx_env_sync_poll(env); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Back up parent txn's cursors, then grab the originals for tracking */ static int cursor_shadow(MDBX_txn *parent, MDBX_txn *nested) { tASSERT(parent, parent->mt_cursors[FREE_DBI] == nullptr); @@ -12344,8 +12340,8 @@ static void cursors_eot(MDBX_txn *txn, const bool merge) { if (bk) { MDBX_xcursor *mx = mc->mc_xcursor; tASSERT(txn, txn->mt_parent != NULL); - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6001, "Using uninitialized memory '*mc->mc_backup'."); + /* Zap: Using uninitialized memory '*mc->mc_backup'. */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001); ENSURE(txn->mt_env, bk->mc_signature == MDBX_MC_LIVE); tASSERT(txn, mx == bk->mc_xcursor); if (stage == MDBX_MC_WAIT4EOT /* Cursor was closed by user */) @@ -12627,20 +12623,26 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, (!freedb_mod_txnid && freedb_root && likely(magic_and_version == MDBX_DATA_MAGIC)))) { if (report) - WARNING("catch invalid %sdb.mod_txnid %" PRIaTXN - " for meta_txnid %" PRIaTXN " %s", - "free", freedb_mod_txnid, txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING( + "catch invalid %sdb.mod_txnid %" PRIaTXN " for meta_txnid %" PRIaTXN + " %s", + "free", freedb_mod_txnid, txnid, + (env->me_stuck_meta < 0) + ? "(workaround for incoherent flaw of unified page/buffer cache)" + : "(wagering meta)"); ok = false; } if (unlikely(txnid < maindb_mod_txnid || (!maindb_mod_txnid && maindb_root && likely(magic_and_version == MDBX_DATA_MAGIC)))) { if (report) - WARNING("catch invalid %sdb.mod_txnid %" PRIaTXN - " for meta_txnid %" PRIaTXN " %s", - "main", maindb_mod_txnid, txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING( + "catch invalid %sdb.mod_txnid %" PRIaTXN " for meta_txnid %" PRIaTXN + " %s", + "main", maindb_mod_txnid, txnid, + (env->me_stuck_meta < 0) + ? "(workaround for incoherent flaw of unified page/buffer cache)" + : "(wagering meta)"); ok = false; } if (likely(freedb_root && freedb_mod_txnid)) { @@ -12650,11 +12652,12 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, const txnid_t root_txnid = freedb_root->mp_txnid; if (unlikely(root_txnid != freedb_mod_txnid)) { if (report) - WARNING( - "catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN - " for %sdb.mod_txnid %" PRIaTXN " %s", - freedb_root_pgno, root_txnid, "free", freedb_mod_txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING("catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN + " for %sdb.mod_txnid %" PRIaTXN " %s", + freedb_root_pgno, root_txnid, "free", freedb_mod_txnid, + (env->me_stuck_meta < 0) ? "(workaround for incoherent flaw of " + "unified page/buffer cache)" + : "(wagering meta)"); ok = false; } } @@ -12665,11 +12668,12 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, const txnid_t root_txnid = maindb_root->mp_txnid; if (unlikely(root_txnid != maindb_mod_txnid)) { if (report) - WARNING( - "catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN - " for %sdb.mod_txnid %" PRIaTXN " %s", - maindb_root_pgno, root_txnid, "main", maindb_mod_txnid, - "(workaround for incoherent flaw of unified page/buffer cache)"); + WARNING("catch invalid root_page %" PRIaPGNO " mod_txnid %" PRIaTXN + " for %sdb.mod_txnid %" PRIaTXN " %s", + maindb_root_pgno, root_txnid, "main", maindb_mod_txnid, + (env->me_stuck_meta < 0) ? "(workaround for incoherent flaw of " + "unified page/buffer cache)" + : "(wagering meta)"); ok = false; } } @@ -12681,15 +12685,16 @@ static bool coherency_check(const MDBX_env *env, const txnid_t txnid, return ok; } -__cold static int coherency_timeout(uint64_t *timestamp, pgno_t pgno) { +__cold static int coherency_timeout(uint64_t *timestamp, intptr_t pgno, + const MDBX_env *env) { if (likely(timestamp && *timestamp == 0)) *timestamp = osal_monotime(); else if (unlikely(!timestamp || osal_monotime() - *timestamp > osal_16dot16_to_monotime(65536 / 10))) { - if (pgno) - ERROR("bailout waiting for %" PRIaPGNO " page arrival %s", pgno, + if (pgno >= 0 && pgno != env->me_stuck_meta) + ERROR("bailout waiting for %" PRIuSIZE " page arrival %s", pgno, "(workaround for incoherent flaw of unified page/buffer cache)"); - else + else if (env->me_stuck_meta < 0) ERROR("bailout waiting for valid snapshot (%s)", "workaround for incoherent flaw of unified page/buffer cache"); return MDBX_PROBLEM; @@ -12710,23 +12715,25 @@ __cold static int coherency_timeout(uint64_t *timestamp, pgno_t pgno) { /* check with timeout as the workaround * for https://libmdbx.dqdkfa.ru/dead-github/issues/269 */ -__hot static int coherency_check_readed(const MDBX_env *env, - const txnid_t txnid, - const volatile MDBX_db *dbs, - const volatile MDBX_meta *meta, - uint64_t *timestamp) { - const bool report = !(timestamp && *timestamp); - if (unlikely(!coherency_check(env, txnid, dbs, meta, report))) - return coherency_timeout(timestamp, 0); +__hot static int coherency_check_head(MDBX_txn *txn, const meta_ptr_t head, + uint64_t *timestamp) { + /* Copy the DB info and flags */ + txn->mt_geo = head.ptr_v->mm_geo; + memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); + txn->mt_canary = head.ptr_v->mm_canary; + + if (unlikely(!coherency_check(txn->mt_env, head.txnid, txn->mt_dbs, + head.ptr_v, *timestamp == 0))) + return coherency_timeout(timestamp, -1, txn->mt_env); return MDBX_SUCCESS; } static int coherency_check_written(const MDBX_env *env, const txnid_t txnid, const volatile MDBX_meta *meta, - uint64_t *timestamp) { + const intptr_t pgno, uint64_t *timestamp) { const bool report = !(timestamp && *timestamp); const txnid_t head_txnid = meta_txnid(meta); - if (unlikely(head_txnid < MIN_TXNID || (head_txnid < txnid))) { + if (unlikely(head_txnid < MIN_TXNID || head_txnid < txnid)) { if (report) { env->me_lck->mti_pgop_stat.incoherence.weak = (env->me_lck->mti_pgop_stat.incoherence.weak >= INT32_MAX) @@ -12737,16 +12744,18 @@ static int coherency_check_written(const MDBX_env *env, const txnid_t txnid, bytes2pgno(env, ptr_dist(meta, env->me_map)), "(workaround for incoherent flaw of unified page/buffer cache)"); } - return coherency_timeout(timestamp, 0); + return coherency_timeout(timestamp, pgno, env); } - return coherency_check_readed(env, head_txnid, meta->mm_dbs, meta, timestamp); + if (unlikely(!coherency_check(env, head_txnid, meta->mm_dbs, meta, report))) + return coherency_timeout(timestamp, pgno, env); + return MDBX_SUCCESS; } -static bool coherency_check_meta(const MDBX_env *env, +static bool check_meta_coherency(const MDBX_env *env, const volatile MDBX_meta *meta, bool report) { uint64_t timestamp = 0; - return coherency_check_written(env, 0, meta, report ? ×tamp : nullptr) == - MDBX_SUCCESS; + return coherency_check_written(env, 0, meta, -1, + report ? ×tamp : nullptr) == MDBX_SUCCESS; } /* Common code for mdbx_txn_begin() and mdbx_txn_renew(). */ @@ -12858,10 +12867,6 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { /* Snap the state from current meta-head */ txn->mt_txnid = head.txnid; - txn->mt_geo = head.ptr_v->mm_geo; - memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - txn->mt_canary = head.ptr_v->mm_canary; - if (likely(env->me_stuck_meta < 0) && unlikely(meta_should_retry(env, &troika) || head.txnid < atomic_load64(&env->me_lck->mti_oldest_reader, @@ -12879,8 +12884,7 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { continue; } - rc = coherency_check_readed(env, head.txnid, txn->mt_dbs, head.ptr_v, - ×tamp); + rc = coherency_check_head(txn, head, ×tamp); jitter4testing(false); if (likely(rc == MDBX_SUCCESS)) break; @@ -12950,14 +12954,12 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { const meta_ptr_t head = meta_recent(env, &txn->tw.troika); uint64_t timestamp = 0; while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - rc = coherency_check_readed(env, head.txnid, head.ptr_v->mm_dbs, - head.ptr_v, ×tamp); + rc = coherency_check_head(txn, head, ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) goto bailout; } - txn->mt_canary = head.ptr_c->mm_canary; eASSERT(env, meta_txnid(head.ptr_v) == head.txnid); txn->mt_txnid = safe64_txnid_next(head.txnid); if (unlikely(txn->mt_txnid > MAX_TXNID)) { @@ -12982,10 +12984,6 @@ static int txn_renew(MDBX_txn *txn, const unsigned flags) { env->me_txn = txn; txn->mt_numdbs = env->me_numdbs; memcpy(txn->mt_dbiseqs, env->me_dbiseqs, txn->mt_numdbs * sizeof(unsigned)); - /* Copy the DB info and flags */ - memcpy(txn->mt_dbs, head.ptr_c->mm_dbs, CORE_DBS * sizeof(MDBX_db)); - /* Moved to here to avoid a data race in read TXNs */ - txn->mt_geo = head.ptr_c->mm_geo; if ((txn->mt_flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC) { rc = dpl_alloc(txn); @@ -13198,13 +13196,6 @@ int mdbx_txn_renew(MDBX_txn *txn) { return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, - MDBX_txn **ret) { - return __inline_mdbx_txn_begin(env, parent, flags, ret); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - int mdbx_txn_set_userctx(MDBX_txn *txn, void *ctx) { int rc = check_txn(txn, MDBX_TXN_FINISHED); if (unlikely(rc != MDBX_SUCCESS)) @@ -13288,6 +13279,9 @@ int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, (MDBX_GOOFY_MSVC_STATIC_ANALYZER && base > size) ? size : base); txn->mt_dbs = ptr_disp(txn, base); txn->mt_cursors = ptr_disp(txn->mt_dbs, sizeof(MDBX_db) * env->me_maxdbs); +#if MDBX_DEBUG + txn->mt_cursors[FREE_DBI] = nullptr; /* avoid SIGSEGV in an assertion later */ +#endif /* MDBX_DEBUG */ txn->mt_dbistate = ptr_disp(txn, size - env->me_maxdbs); txn->mt_dbxs = env->me_dbxs; /* static */ txn->mt_flags = flags; @@ -15151,10 +15145,6 @@ static __always_inline bool check_dbi(MDBX_txn *txn, MDBX_dbi dbi, return dbi_import(txn, dbi); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_txn_commit(MDBX_txn *txn) { return __inline_mdbx_txn_commit(txn); } -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Merge child txn into parent */ static __inline void txn_merge(MDBX_txn *const parent, MDBX_txn *const txn, const size_t parent_retired_len) { @@ -16536,7 +16526,7 @@ __cold static MDBX_page *meta_model(const MDBX_env *env, MDBX_page *model, model_meta->mm_dbs[MAIN_DBI].md_root = P_INVALID; meta_set_txnid(env, model_meta, MIN_TXNID + num); unaligned_poke_u64(4, model_meta->mm_sign, meta_sign(model_meta)); - eASSERT(env, coherency_check_meta(env, model_meta, true)); + eASSERT(env, check_meta_coherency(env, model_meta, true)); return ptr_disp(model, env->me_psize); } @@ -16707,7 +16697,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, goto fail; } meta_set_txnid(env, pending, txnid); - eASSERT(env, coherency_check_meta(env, pending, true)); + eASSERT(env, check_meta_coherency(env, pending, true)); } } } @@ -16753,7 +16743,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, rc = (flags & MDBX_SAFE_NOSYNC) ? MDBX_RESULT_TRUE /* carry non-steady */ : MDBX_RESULT_FALSE /* carry steady */; } - eASSERT(env, coherency_check_meta(env, pending, true)); + eASSERT(env, check_meta_coherency(env, pending, true)); /* Steady or Weak */ if (rc == MDBX_RESULT_FALSE /* carry steady */) { @@ -16858,7 +16848,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, /* LY: 'commit' the meta */ meta_update_end(env, target, unaligned_peek_u64(4, pending->mm_txnid_b)); jitter4testing(true); - eASSERT(env, coherency_check_meta(env, target, true)); + eASSERT(env, check_meta_coherency(env, target, true)); } else { /* dangerous case (target == head), only mm_sign could * me updated, check assertions once again */ @@ -16931,8 +16921,9 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, uint64_t timestamp = 0; while ("workaround for https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - rc = - coherency_check_written(env, pending->unsafe_txnid, target, ×tamp); + rc = coherency_check_written(env, pending->unsafe_txnid, target, + bytes2pgno(env, ptr_dist(target, env->me_map)), + ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) @@ -16961,7 +16952,7 @@ static int sync_locked(MDBX_env *env, unsigned flags, MDBX_meta *const pending, pending->mm_geo.upper, impilict_shrink); if (rc != MDBX_SUCCESS && rc != MDBX_EPERM) goto fail; - eASSERT(env, coherency_check_meta(env, target, true)); + eASSERT(env, check_meta_coherency(env, target, true)); } MDBX_lockinfo *const lck = env->me_lck_mmap.lck; @@ -17200,10 +17191,10 @@ __cold static intptr_t get_reasonable_db_maxsize(intptr_t *cached_result) { return *cached_result; } -__cold LIBMDBX_API int -mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, - intptr_t size_upper, intptr_t growth_step, - intptr_t shrink_threshold, intptr_t pagesize) { +__cold int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, + intptr_t size_now, intptr_t size_upper, + intptr_t growth_step, + intptr_t shrink_threshold, intptr_t pagesize) { int rc = check_env(env, false); if (unlikely(rc != MDBX_SUCCESS)) return rc; @@ -17455,7 +17446,6 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, ENSURE(env, pagesize == (intptr_t)env->me_psize); MDBX_meta meta; memset(&meta, 0, sizeof(meta)); - const MDBX_geo *current_geo; if (!inside_txn) { eASSERT(env, need_unlock); const meta_ptr_t head = meta_recent(env, &env->me_txn0->tw.troika); @@ -17463,14 +17453,13 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, uint64_t timestamp = 0; while ("workaround for " "https://libmdbx.dqdkfa.ru/dead-github/issues/269") { - meta = *head.ptr_c; - rc = coherency_check_readed(env, head.txnid, meta.mm_dbs, &meta, - ×tamp); + rc = coherency_check_head(env->me_txn0, head, ×tamp); if (likely(rc == MDBX_SUCCESS)) break; if (unlikely(rc != MDBX_RESULT_TRUE)) goto bailout; } + meta = *head.ptr_c; const txnid_t txnid = safe64_txnid_next(head.txnid); if (unlikely(txnid > MAX_TXNID)) { rc = MDBX_TXN_FULL; @@ -17478,11 +17467,10 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, goto bailout; } meta_set_txnid(env, &meta, txnid); - current_geo = &meta.mm_geo; - } else { - current_geo = &env->me_txn->mt_geo; } + const MDBX_geo *const current_geo = + &(env->me_txn ? env->me_txn : env->me_txn0)->mt_geo; /* update env-geo to avoid influences */ env->me_dbgeo.now = pgno2bytes(env, current_geo->now); env->me_dbgeo.lower = pgno2bytes(env, current_geo->lower); @@ -17585,28 +17573,6 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) { - return __inline_mdbx_env_set_mapsize(env, size); -} - -__cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { - return __inline_mdbx_env_set_maxdbs(env, dbs); -} - -__cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) { - return __inline_mdbx_env_get_maxdbs(env, dbs); -} - -__cold int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) { - return __inline_mdbx_env_set_maxreaders(env, readers); -} - -__cold int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers) { - return __inline_mdbx_env_get_maxreaders(env, readers); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold static int alloc_page_buf(MDBX_env *env) { return env->me_pbuf ? MDBX_SUCCESS : osal_memalign_alloc(env->me_os_psize, @@ -18410,9 +18376,9 @@ __cold static int __must_check_result override_meta(MDBX_env *env, MDBX_meta *const model = page_meta(page); meta_set_txnid(env, model, txnid); if (txnid) - eASSERT(env, coherency_check_meta(env, model, true)); + eASSERT(env, check_meta_coherency(env, model, true)); if (shape) { - if (txnid && unlikely(!coherency_check_meta(env, shape, false))) { + if (txnid && unlikely(!check_meta_coherency(env, shape, false))) { ERROR("bailout overriding meta-%zu since model failed " "freedb/maindb %s-check for txnid #%" PRIaTXN, target, "pre", constmeta_txnid(shape)); @@ -18436,7 +18402,7 @@ __cold static int __must_check_result override_meta(MDBX_env *env, model->mm_dbs[MAIN_DBI].md_root != P_INVALID)) memcpy(&model->mm_magic_and_version, &shape->mm_magic_and_version, sizeof(model->mm_magic_and_version)); - if (unlikely(!coherency_check_meta(env, model, false))) { + if (unlikely(!check_meta_coherency(env, model, false))) { ERROR("bailout overriding meta-%zu since model failed " "freedb/maindb %s-check for txnid #%" PRIaTXN, target, "post", txnid); @@ -18486,7 +18452,10 @@ __cold static int __must_check_result override_meta(MDBX_env *env, osal_flush_incoherent_mmap(env->me_map, pgno2bytes(env, NUM_METAS), env->me_os_psize); } - eASSERT(env, !env->me_txn && !env->me_txn0); + eASSERT(env, (!env->me_txn && !env->me_txn0) || + (env->me_stuck_meta == (int)target && + (env->me_flags & (MDBX_EXCLUSIVE | MDBX_RDONLY)) == + MDBX_EXCLUSIVE)); return rc; } @@ -19013,7 +18982,7 @@ __cold int mdbx_env_openW(MDBX_env *env, const wchar_t *pathname, if (!(flags & (MDBX_RDONLY | MDBX_SAFE_NOSYNC | MDBX_NOMETASYNC | MDBX_EXCLUSIVE))) { if (MDBX_AVOID_MSYNC && (flags & MDBX_WRITEMAP)) { - /* Запрошен режим MDBX_SAFE_NOSYNC | MDBX_WRITEMAP при активной опции + /* Запрошен режим MDBX_SYNC_DURABLE | MDBX_WRITEMAP при активной опции * MDBX_AVOID_MSYNC. * * 1) В этой комбинации наиболее выгодно использовать WriteFileGather(), @@ -19485,12 +19454,6 @@ __cold int mdbx_env_close_ex(MDBX_env *env, bool dont_sync) { return rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_close(MDBX_env *env) { - return __inline_mdbx_env_close(env); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - /* Search for key within a page, using binary search. * Returns the smallest entry larger or equal to the key. * Updates the cursor index with the index of the found entry. @@ -20044,19 +20007,11 @@ static __noinline int node_read_bigdata(MDBX_cursor *mc, const MDBX_node *node, if (!MDBX_DISABLE_VALIDATION) { const MDBX_env *env = mc->mc_txn->mt_env; const size_t dsize = data->iov_len; - if (unlikely(node_size_len(node_ks(node), dsize) <= env->me_leaf_nodemax) && - mc->mc_dbi != FREE_DBI) - poor_page(mp, "too small data (%zu bytes) for bigdata-node", dsize); const unsigned npages = number_of_ovpages(env, dsize); - if (unlikely(lp.page->mp_pages != npages)) { - if (lp.page->mp_pages < npages) - return bad_page(lp.page, - "too less n-pages %u for bigdata-node (%zu bytes)", - lp.page->mp_pages, dsize); - else if (mc->mc_dbi != FREE_DBI) - poor_page(lp.page, "extra n-pages %u for bigdata-node (%zu bytes)", - lp.page->mp_pages, dsize); - } + if (unlikely(lp.page->mp_pages < npages)) + return bad_page(lp.page, + "too less n-pages %u for bigdata-node (%zu bytes)", + lp.page->mp_pages, dsize); } return MDBX_SUCCESS; } @@ -25859,8 +25814,8 @@ __cold int mdbx_env_copy(MDBX_env *env, const char *dest_path, return rc; } -LIBMDBX_API int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest_path, - MDBX_copy_flags_t flags) { +__cold int mdbx_env_copyW(MDBX_env *env, const wchar_t *dest_path, + MDBX_copy_flags_t flags) { #endif /* Windows */ int rc = check_env(env, true); @@ -26066,12 +26021,6 @@ __cold int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *arg) { return MDBX_SUCCESS; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_stat(const MDBX_env *env, MDBX_stat *stat, size_t bytes) { - return __inline_mdbx_env_stat(env, stat, bytes); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - static void stat_get(const MDBX_db *db, MDBX_stat *st, size_t bytes) { st->ms_depth = db->md_depth; st->ms_branch_pages = db->md_branch_pages; @@ -26243,13 +26192,6 @@ __cold int mdbx_dbi_dupsort_depthmask(MDBX_txn *txn, MDBX_dbi dbi, return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, - size_t bytes) { - return __inline_mdbx_env_info(env, info, bytes); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold static int fetch_envinfo_ex(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *arg, const size_t bytes) { @@ -26473,7 +26415,7 @@ static __inline MDBX_cmp_func *get_default_datacmp(unsigned flags) { static int dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, MDBX_cmp_func *keycmp, MDBX_cmp_func *datacmp) { - /* LY: so, accepting only three cases for the table's flags: + /* Accepting only three cases: * 1) user_flags and both comparators are zero * = assume that a by-default mode/flags is requested for reading; * 2) user_flags exactly the same @@ -26495,6 +26437,10 @@ static int dbi_bind(MDBX_txn *txn, const MDBX_dbi dbi, unsigned user_flags, /* make sure flags changes get committed */ txn->mt_dbs[dbi].md_flags = user_flags & DB_PERSISTENT_FLAGS; txn->mt_flags |= MDBX_TXN_DIRTY; + /* обнуляем компараторы для установки в соответствии с флагами, + * либо заданных пользователем */ + txn->mt_dbxs[dbi].md_cmp = nullptr; + txn->mt_dbxs[dbi].md_dcmp = nullptr; } else { return /* FIXME: return extended info */ MDBX_INCOMPATIBLE; } @@ -26913,12 +26859,6 @@ int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, return MDBX_SUCCESS; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { - return __inline_mdbx_dbi_flags(txn, dbi, flags); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - static int drop_tree(MDBX_cursor *mc, const bool may_have_subDBs) { int rc = page_search(mc, NULL, MDBX_PS_FIRST); if (likely(rc == MDBX_SUCCESS)) { @@ -27428,16 +27368,6 @@ __cold static txnid_t kick_longlived_readers(MDBX_env *env, return oldest; } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { - return __inline_mdbx_env_set_syncbytes(env, threshold); -} - -__cold int mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) { - return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr) { int rc = check_env(env, false); if (unlikely(rc != MDBX_SUCCESS)) @@ -28511,16 +28441,6 @@ int mdbx_dbi_sequence(MDBX_txn *txn, MDBX_dbi dbi, uint64_t *result, /*----------------------------------------------------------------------------*/ -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -__cold MDBX_NOTHROW_CONST_FUNCTION intptr_t mdbx_limits_pgsize_min(void) { - return __inline_mdbx_limits_pgsize_min(); -} - -__cold MDBX_NOTHROW_CONST_FUNCTION intptr_t mdbx_limits_pgsize_max(void) { - return __inline_mdbx_limits_pgsize_max(); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - __cold intptr_t mdbx_limits_dbsize_min(intptr_t pagesize) { if (pagesize < 1) pagesize = (intptr_t)mdbx_default_pagesize(); @@ -28624,16 +28544,6 @@ uint32_t mdbx_key_from_ptrfloat(const float *const ieee754_32bit) { return float2key(ieee754_32bit); } -#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API -MDBX_NOTHROW_CONST_FUNCTION uint64_t mdbx_key_from_int64(const int64_t i64) { - return __inline_mdbx_key_from_int64(i64); -} - -MDBX_NOTHROW_CONST_FUNCTION uint32_t mdbx_key_from_int32(const int32_t i32) { - return __inline_mdbx_key_from_int32(i32); -} -#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ - #define IEEE754_DOUBLE_MANTISSA_SIZE 52 #define IEEE754_DOUBLE_EXPONENTA_BIAS 0x3FF #define IEEE754_DOUBLE_EXPONENTA_MAX 0x7FF @@ -29442,6 +29352,109 @@ __cold void global_ctor(void) { #endif /* #if 0 */ } +/*------------------------------------------------------------------------------ + * Legacy API */ + +#ifndef LIBMDBX_NO_EXPORTS_LEGACY_API + +LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, + MDBX_txn_flags_t flags, MDBX_txn **ret) { + return __inline_mdbx_txn_begin(env, parent, flags, ret); +} + +LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn) { + return __inline_mdbx_txn_commit(txn); +} + +LIBMDBX_API __cold int mdbx_env_stat(const MDBX_env *env, MDBX_stat *stat, + size_t bytes) { + return __inline_mdbx_env_stat(env, stat, bytes); +} + +LIBMDBX_API __cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, + size_t bytes) { + return __inline_mdbx_env_info(env, info, bytes); +} + +LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { + return __inline_mdbx_dbi_flags(txn, dbi, flags); +} + +LIBMDBX_API __cold int mdbx_env_sync(MDBX_env *env) { + return __inline_mdbx_env_sync(env); +} + +LIBMDBX_API __cold int mdbx_env_sync_poll(MDBX_env *env) { + return __inline_mdbx_env_sync_poll(env); +} + +LIBMDBX_API __cold int mdbx_env_close(MDBX_env *env) { + return __inline_mdbx_env_close(env); +} + +LIBMDBX_API __cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) { + return __inline_mdbx_env_set_mapsize(env, size); +} + +LIBMDBX_API __cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { + return __inline_mdbx_env_set_maxdbs(env, dbs); +} + +LIBMDBX_API __cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) { + return __inline_mdbx_env_get_maxdbs(env, dbs); +} + +LIBMDBX_API __cold int mdbx_env_set_maxreaders(MDBX_env *env, + unsigned readers) { + return __inline_mdbx_env_set_maxreaders(env, readers); +} + +LIBMDBX_API __cold int mdbx_env_get_maxreaders(const MDBX_env *env, + unsigned *readers) { + return __inline_mdbx_env_get_maxreaders(env, readers); +} + +LIBMDBX_API __cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { + return __inline_mdbx_env_set_syncbytes(env, threshold); +} + +LIBMDBX_API __cold int mdbx_env_get_syncbytes(const MDBX_env *env, + size_t *threshold) { + return __inline_mdbx_env_get_syncbytes(env, threshold); +} + +LIBMDBX_API __cold int mdbx_env_set_syncperiod(MDBX_env *env, + unsigned seconds_16dot16) { + return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16); +} + +LIBMDBX_API __cold int mdbx_env_get_syncperiod(const MDBX_env *env, + unsigned *seconds_16dot16) { + return __inline_mdbx_env_get_syncperiod(env, seconds_16dot16); +} + +LIBMDBX_API __cold MDBX_NOTHROW_CONST_FUNCTION intptr_t +mdbx_limits_pgsize_min(void) { + return __inline_mdbx_limits_pgsize_min(); +} + +LIBMDBX_API __cold MDBX_NOTHROW_CONST_FUNCTION intptr_t +mdbx_limits_pgsize_max(void) { + return __inline_mdbx_limits_pgsize_max(); +} + +LIBMDBX_API MDBX_NOTHROW_CONST_FUNCTION uint64_t +mdbx_key_from_int64(const int64_t i64) { + return __inline_mdbx_key_from_int64(i64); +} + +LIBMDBX_API MDBX_NOTHROW_CONST_FUNCTION uint32_t +mdbx_key_from_int32(const int32_t i32) { + return __inline_mdbx_key_from_int32(i32); +} + +#endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ + /******************************************************************************/ __dll_export @@ -29679,7 +29692,10 @@ __dll_export }; #ifdef __SANITIZE_ADDRESS__ -LIBMDBX_API __attribute__((__weak__)) const char *__asan_default_options(void) { +#if !defined(_MSC_VER) || __has_attribute(weak) +LIBMDBX_API __attribute__((__weak__)) +#endif +const char *__asan_default_options(void) { return "symbolize=1:allow_addr2line=1:" #if MDBX_DEBUG "debug=1:" @@ -29753,7 +29769,8 @@ static int ntstatus2errcode(NTSTATUS status) { OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.Internal = status; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6387, "'_Param_(1)' could be '0'"); + /* Zap: '_Param_(1)' could be '0' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6387); return GetOverlappedResult(NULL, &ov, &dummy, FALSE) ? MDBX_SUCCESS : (int)GetLastError(); } @@ -29788,8 +29805,8 @@ extern NTSTATUS NTAPI NtMapViewOfSection( extern NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN OPTIONAL PVOID BaseAddress); -MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(28251, - "Inconsistent annotation for 'NtClose'...") +/* Zap: Inconsistent annotation for 'NtClose'... */ +MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(28251) extern NTSTATUS NTAPI NtClose(HANDLE Handle); extern NTSTATUS NTAPI NtAllocateVirtualMemory( @@ -30020,17 +30037,16 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, va_list ap) { va_list ones; va_copy(ones, ap); - int needed = vsnprintf(nullptr, 0, fmt, ap); + const int needed = vsnprintf(nullptr, 0, fmt, ones); + va_end(ones); if (unlikely(needed < 0 || needed >= INT_MAX)) { *strp = nullptr; - va_end(ones); return needed; } *strp = osal_malloc(needed + (size_t)1); if (unlikely(*strp == nullptr)) { - va_end(ones); #if defined(_WIN32) || defined(_WIN64) SetLastError(MDBX_ENOMEM); #else @@ -30039,9 +30055,7 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, return -1; } - int actual = vsnprintf(*strp, needed + (size_t)1, fmt, ones); - va_end(ones); - + const int actual = vsnprintf(*strp, needed + (size_t)1, fmt, ap); assert(actual == needed); if (unlikely(actual < 0)) { osal_free(*strp); @@ -30055,7 +30069,7 @@ MDBX_INTERNAL_FUNC int osal_vasprintf(char **strp, const char *fmt, MDBX_INTERNAL_FUNC int osal_asprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - int rc = osal_vasprintf(strp, fmt, ap); + const int rc = osal_vasprintf(strp, fmt, ap); va_end(ap); return rc; } @@ -30509,8 +30523,8 @@ MDBX_INTERNAL_FUNC void osal_ioring_walk( if (bytes & ior_WriteFile_flag) { data = Ptr64ToPtr(item->sgv[0].Buffer); bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { if (data + ior->pagesize != item->sgv[i].Buffer) { callback(ctx, offset, data, bytes); @@ -30557,8 +30571,8 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { if (bytes & ior_WriteFile_flag) { assert(ior->overlapped_fd && fd == ior->overlapped_fd); bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { bytes += ior->pagesize; ++i; @@ -30697,8 +30711,8 @@ osal_ioring_write(osal_ioring_t *ior, mdbx_filehandle_t fd) { size_t i = 1, bytes = item->single.iov_len - ior_WriteFile_flag; if (bytes & ior_WriteFile_flag) { bytes = ior->pagesize; - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) { bytes += ior->pagesize; ++i; @@ -30793,8 +30807,8 @@ MDBX_INTERNAL_FUNC void osal_ioring_reset(osal_ioring_t *ior) { ior_put_event(ior, item->ov.hEvent); size_t i = 1; if ((item->single.iov_len & ior_WriteFile_flag) == 0) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6385, "Reading invalid data from 'item->sgv'"); + /* Zap: Reading invalid data from 'item->sgv' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6385); while (item->sgv[i].Buffer) ++i; } @@ -30813,8 +30827,8 @@ static void ior_cleanup(osal_ioring_t *ior, const size_t since) { osal_ioring_reset(ior); #if defined(_WIN32) || defined(_WIN64) for (size_t i = since; i < ior->event_stack; ++i) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 6001, "Using uninitialized memory '**ior.event_pool'"); + /* Zap: Using uninitialized memory '**ior.event_pool' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6001); CloseHandle(ior->event_pool[i]); } ior->event_stack = 0; @@ -32454,7 +32468,8 @@ retry_mapview:; #endif /* POSIX / Windows */ - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6287, "Redundant code"); + /* Zap: Redundant code */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(6287); assert(rc != MDBX_SUCCESS || (map->base != nullptr && map->base != MAP_FAILED && map->current == size && map->limit == limit && @@ -33254,10 +33269,10 @@ __dll_export const struct MDBX_version_info mdbx_version = { 0, 12, - 3, - 30, - {"2023-02-14T12:09:44+03:00", "056bb01c9eb5f3d038255f79108076b072918bd0", "29d12f1fc3ab10a41a6edab054ee884b9c57e6ee", - "v0.12.3-30-g29d12f1f"}, + 5, + 0, + {"2023-04-18T11:03:31+03:00", "cf967b230d768c074762cc51bf89c6ad3ea726a9", "9b8291457bfc7322e258f7efd81a5206a3d99e9d", + "v0.12.5-0-g9b829145"}, sourcery}; __dll_export @@ -33465,9 +33480,9 @@ int mdbx_txn_lock(MDBX_env *env, bool dontwait) { } if (env->me_flags & MDBX_EXCLUSIVE) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 26115, "Failing to release lock 'env->me_windowsbug_lock' in function " - "'mdbx_txn_lock'"); + /* Zap: Failing to release lock 'env->me_windowsbug_lock' + * in function 'mdbx_txn_lock' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return MDBX_SUCCESS; } @@ -33488,9 +33503,9 @@ int mdbx_txn_lock(MDBX_env *env, bool dontwait) { } } if (rc == MDBX_SUCCESS) { - MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER( - 26115, "Failing to release lock 'env->me_windowsbug_lock' in function " - "'mdbx_txn_lock'"); + /* Zap: Failing to release lock 'env->me_windowsbug_lock' + * in function 'mdbx_txn_lock' */ + MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(26115); return rc; } diff --git a/mdbxdist/mdbx.h b/mdbxdist/mdbx.h index ce46b6f..cc42298 100644 --- a/mdbxdist/mdbx.h +++ b/mdbxdist/mdbx.h @@ -2060,7 +2060,9 @@ LIBMDBX_API const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, * \returns a non-zero error value on failure and 0 on success. */ LIBMDBX_API int mdbx_env_create(MDBX_env **penv); -/** \brief MDBX environment options. */ +/** \brief MDBX environment extra runtime options. + * \ingroup c_settings + * \see mdbx_env_set_option() \see mdbx_env_get_option() */ enum MDBX_option_t { /** \brief Controls the maximum number of named databases for the environment. * @@ -2268,7 +2270,7 @@ enum MDBX_option_t { typedef enum MDBX_option_t MDBX_option_t; #endif -/** \brief Sets the value of a runtime options for an environment. +/** \brief Sets the value of a extra runtime options for an environment. * \ingroup c_settings * * \param [in] env An environment handle returned by \ref mdbx_env_create(). @@ -2281,7 +2283,7 @@ typedef enum MDBX_option_t MDBX_option_t; LIBMDBX_API int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, uint64_t value); -/** \brief Gets the value of runtime options from an environment. +/** \brief Gets the value of extra runtime options from an environment. * \ingroup c_settings * * \param [in] env An environment handle returned by \ref mdbx_env_create(). @@ -3055,6 +3057,8 @@ LIBMDBX_API int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *fd); * it is reasonable to know some details in order to make optimal decisions * when choosing parameters. * + * \see mdbx_env_info_ex() + * * Both \ref mdbx_env_set_geometry() and legacy \ref mdbx_env_set_mapsize() are * inapplicable to read-only opened environment. * @@ -3164,7 +3168,7 @@ LIBMDBX_API int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *fd); * \note Actual values may be different than your have specified because of * rounding to specified database page size, the system page size and/or the * size of the system virtual memory management unit. You can get actual values - * by \ref mdbx_env_sync_ex() or see by using the tool `mdbx_chk` with the `-v` + * by \ref mdbx_env_info_ex() or see by using the tool `mdbx_chk` with the `-v` * option. * * Legacy \ref mdbx_env_set_mapsize() correspond to calling diff --git a/mdbxdist/mdbx_chk.c b/mdbxdist/mdbx_chk.c index cd5032f..7c1db1a 100644 --- a/mdbxdist/mdbx_chk.c +++ b/mdbxdist/mdbx_chk.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -830,14 +830,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ diff --git a/mdbxdist/mdbx_copy.c b/mdbxdist/mdbx_copy.c index 2ed1c99..bcc6780 100644 --- a/mdbxdist/mdbx_copy.c +++ b/mdbxdist/mdbx_copy.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -830,14 +830,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ diff --git a/mdbxdist/mdbx_drop.c b/mdbxdist/mdbx_drop.c index cd81cd6..c617560 100644 --- a/mdbxdist/mdbx_drop.c +++ b/mdbxdist/mdbx_drop.c @@ -36,7 +36,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -832,14 +832,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ diff --git a/mdbxdist/mdbx_dump.c b/mdbxdist/mdbx_dump.c index 8a178ce..58d7c35 100644 --- a/mdbxdist/mdbx_dump.c +++ b/mdbxdist/mdbx_dump.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -830,14 +830,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ diff --git a/mdbxdist/mdbx_load.c b/mdbxdist/mdbx_load.c index b3e02da..6b9b139 100644 --- a/mdbxdist/mdbx_load.c +++ b/mdbxdist/mdbx_load.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -830,14 +830,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ diff --git a/mdbxdist/mdbx_stat.c b/mdbxdist/mdbx_stat.c index e06f694..ab08ad2 100644 --- a/mdbxdist/mdbx_stat.c +++ b/mdbxdist/mdbx_stat.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY 5777e7cda5ce7601d3d4f997c2d985538a3a61e6b6e02682cca2137e05e756cb_v0_12_3_30_g29d12f1f +#define MDBX_BUILD_SOURCERY 3bd4ed05bd2736470da2556602a105008d8b53012d792b77aefd32d0baeb533b_v0_12_5_0_g9b829145 #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -830,14 +830,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ -#if MDBX_GOOFY_MSVC_STATIC_ANALYZER +#if MDBX_GOOFY_MSVC_STATIC_ANALYZER || (defined(_MSC_VER) && _MSC_VER > 1919) #define MDBX_ANALYSIS_ASSUME(expr) __analysis_assume(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) \ - _Pragma(MDBX_STRINGIFY(prefast(suppress : warn_id))) +#ifdef _PREFAST_ +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(prefast(suppress : warn_id)) #else -#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) -#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id, note) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) \ + __pragma(warning(suppress : warn_id)) #endif +#else +#define MDBX_ANALYSIS_ASSUME(expr) assert(expr) +#define MDBX_SUPPRESS_GOOFY_MSVC_ANALYZER(warn_id) +#endif /* MDBX_GOOFY_MSVC_STATIC_ANALYZER */ /*----------------------------------------------------------------------------*/ @@ -4372,6 +4377,17 @@ int main(int argc, char *argv[]) { printf(" WOP: %8" PRIu64 "\t// number of explicit write operations (not a pages) to a disk\n", mei.mi_pgop_stat.wops); + printf(" PreFault: %8" PRIu64 + "\t// number of prefault write operations (not a pages)\n", + mei.mi_pgop_stat.prefault); + printf(" mInCore: %8" PRIu64 "\t// number of mincore() calls\n", + mei.mi_pgop_stat.mincore); + printf(" mSync: %8" PRIu64 + "\t// number of explicit msync-to-disk operations (not a pages)\n", + mei.mi_pgop_stat.msync); + printf(" fSync: %8" PRIu64 + "\t// number of explicit fsync-to-disk operations (not a pages)\n", + mei.mi_pgop_stat.fsync); } if (envinfo) {