diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..79f8a99 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,2 @@ +edition = "2021" +tab_spaces = 4 diff --git a/Cargo.toml b/Cargo.toml index f57a80a..d405c8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ authors = [ "Victor Porof ", "Artem Vorotnikov ", ] -edition = "2018" +edition = "2021" license = "Apache-2.0" description = "Idiomatic and safe MDBX wrapper." documentation = "https://docs.rs/mdbx" @@ -24,22 +24,21 @@ name = "mdbx" members = ["mdbx-sys"] [dependencies] -bitflags = "1" -byteorder = "1" -derive_more = "0.99" -indexmap = "1" -libc = "0.2" +byteorder = "1.4.3" +derive_more = "0.99.16" +indexmap = "1.7.0" +libc = "0.2.107" lifetimed-bytes = { git = "https://github.com/vorot93/lifetimed-bytes" } -parking_lot = "0.11" -thiserror = "1" - +parking_lot = "0.11.2" +thiserror = "1.0.30" ffi = { package = "mdbx-sys", path = "./mdbx-sys" } +os_str_bytes = "5.0.0" [dev-dependencies] -criterion = "0.3" -rand = "0.8" -rand_xorshift = "0.3" -tempfile = "3" +criterion = "0.3.5" +rand = "0.8.4" +rand_xorshift = "0.3.0" +tempfile = "3.2.0" [[bench]] name = "cursor" diff --git a/mdbx-sys/Cargo.toml b/mdbx-sys/Cargo.toml index c1f2887..45516b9 100644 --- a/mdbx-sys/Cargo.toml +++ b/mdbx-sys/Cargo.toml @@ -3,7 +3,7 @@ name = "mdbx-sys" # NB: When modifying, also modify html_root_url in lib.rs # NB: The version must match the version of mdbx version = "0.9.3" -edition = "2018" +edition = "2021" authors = [ "Dan Burkert ", "Victor Porof ", @@ -23,8 +23,8 @@ categories = ["database", "external-ffi-bindings"] name = "mdbx_sys" [dependencies] -libc = "0.2" +libc = "0.2.107" [build-dependencies] -cc = "1.0" -bindgen = { version = "0.59", default-features = false, features = ["runtime"] } +cc = "1.0.72" +bindgen = { version = "0.59.1", default-features = false, features = ["runtime"] } diff --git a/mdbx-sys/build.rs b/mdbx-sys/build.rs index c79f908..2e85036 100644 --- a/mdbx-sys/build.rs +++ b/mdbx-sys/build.rs @@ -59,6 +59,8 @@ fn main() { .allowlist_var("^(MDBX|mdbx)_.*") .allowlist_type("^(MDBX|mdbx)_.*") .allowlist_function("^(MDBX|mdbx)_.*") + .rustified_enum("^(MDBX_option_t|MDBX_cursor_op)") + .bitfield_enum("^(MDBX_constants|MDBX_log_level_t|MDBX_debug_flags_t|MDBX_env_flags_t|MDBX_txn_flags_t|MDBX_db_flags_t|MDBX_put_flags_t|MDBX_copy_flags_t|MDBX_env_delete_mode_t|MDBX_dbi_state_t|MDBX_page_type_t|MDBX_error_t)") .size_t_is_usize(true) .ctypes_prefix("::libc") .parse_callbacks(Box::new(Callbacks)) diff --git a/mdbx-sys/libmdbx/CMakeLists.txt b/mdbx-sys/libmdbx/CMakeLists.txt index 49429eb..8a32f08 100644 --- a/mdbx-sys/libmdbx/CMakeLists.txt +++ b/mdbx-sys/libmdbx/CMakeLists.txt @@ -334,9 +334,16 @@ list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_11 HAS_CXX11) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_14 HAS_CXX14) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_17 HAS_CXX17) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_20 HAS_CXX20) +list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_std_23 HAS_CXX23) if(NOT DEFINED MDBX_CXX_STANDARD) + if(DEFINED ENV{CMAKE_CXX_STANDARD}) + set(CMAKE_CXX_STANDARD $ENV{CMAKE_CXX_STANDARD}) + endif() if(DEFINED CMAKE_CXX_STANDARD) set(MDBX_CXX_STANDARD ${CMAKE_CXX_STANDARD}) + elseif(NOT HAS_CXX23 LESS 0 + AND NOT (CMAKE_COMPILER_IS_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12)) + set(MDBX_CXX_STANDARD 23) elseif(NOT HAS_CXX20 LESS 0 AND NOT (CMAKE_COMPILER_IS_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)) set(MDBX_CXX_STANDARD 20) diff --git a/mdbx-sys/libmdbx/ChangeLog.md b/mdbx-sys/libmdbx/ChangeLog.md index 749f71b..ad54a52 100644 --- a/mdbx-sys/libmdbx/ChangeLog.md +++ b/mdbx-sys/libmdbx/ChangeLog.md @@ -14,10 +14,24 @@ ChangeLog - [Support for RAW devices](https://github.com/erthink/libmdbx/issues/124). - [Support MessagePack for Keys & Values](https://github.com/erthink/libmdbx/issues/115). - [Engage new terminology](https://github.com/erthink/libmdbx/issues/137). - - Finalize C++ API (few typos and bugs are still maybe for now). + - Finalize C++ API (there is still a small chance for a few typos and bugs). - Packages for [Astra Linux](https://astralinux.ru/), [ALT Linux](https://www.altlinux.org/), [ROSA Linux](https://www.rosalinux.ru/), etc. +## v0.11.2 (underway) + +Acknowledgements: + + - [장세연 (Чан Се Ен)](https://github.com/sasgas) for contributing to C++ API. + +Minors: + + - Fixed `constexpr`-related macros for legacy compilers. + - Allowed to define 'CMAKE_CXX_STANDARD` using an environment variable. + - Simplified collection statistics of page operation . + - [Fixed](https://github.com/erthink/libmdbx/pull/239) compilation with devtoolset-9 on CentOS/RHEL 7. + + ## v0.11.1 at 2021-10-23 ### Backward compatibility break: diff --git a/mdbx-sys/libmdbx/GNUmakefile b/mdbx-sys/libmdbx/GNUmakefile index c188aba..0d960e2 100644 --- a/mdbx-sys/libmdbx/GNUmakefile +++ b/mdbx-sys/libmdbx/GNUmakefile @@ -35,7 +35,7 @@ CFLAGS ?= -std=gnu11 -O2 -g -Wall -Werror -Wextra -Wpedantic -ffunction-section # -Wno-tautological-compare CXX ?= g++ # Choosing C++ standard with deferred simple variable expansion trick -CXXSTD ?= $(eval CXXSTD := $$(shell PROBE=$$$$([ -f mdbx.c++ ] && echo mdbx.c++ || echo src/mdbx.c++); for std in gnu++20 c++20 gnu++2a c++2a gnu++17 c++17 gnu++14 c++14 gnu+11 c++11; do $(CXX) -std=$$$${std} -c $$$${PROBE} -o /dev/null 2>/dev/null >/dev/null && echo "-std=$$$${std}" && exit; done))$(CXXSTD) +CXXSTD ?= $(eval CXXSTD := $$(shell PROBE=$$$$([ -f mdbx.c++ ] && echo mdbx.c++ || echo src/mdbx.c++); for std in gnu++23 c++23 gnu++2b c++2b gnu++20 c++20 gnu++2a c++2a gnu++17 c++17 gnu++1z c++1z gnu++14 c++14 gnu++1y c++1y gnu+11 c++11 gnu++0x c++0x; do $(CXX) -std=$$$${std} -c $$$${PROBE} -o /dev/null 2>std-$$$${std}.err >/dev/null && echo "-std=$$$${std}" && exit; done))$(CXXSTD) CXXFLAGS = $(CXXSTD) $(filter-out -std=gnu11,$(CFLAGS)) # TIP: Try append '--no-as-needed,-lrt' for ability to built with modern glibc, but then use with the old. diff --git a/mdbx-sys/libmdbx/VERSION.txt b/mdbx-sys/libmdbx/VERSION.txt index 22bce9d..548f534 100644 --- a/mdbx-sys/libmdbx/VERSION.txt +++ b/mdbx-sys/libmdbx/VERSION.txt @@ -1 +1 @@ -0.11.1.0 +0.11.1.21 diff --git a/mdbx-sys/libmdbx/mdbx.c b/mdbx-sys/libmdbx/mdbx.c index 8feec57..5051ead 100644 --- a/mdbx-sys/libmdbx/mdbx.c +++ b/mdbx-sys/libmdbx/mdbx.c @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -62,6 +62,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -999,9 +1012,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1253,7 +1267,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2022,8 +2035,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2067,70 +2078,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2246,8 +2193,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3015,6 +2960,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3184,15 +3138,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3327,10 +3272,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif @@ -4248,6 +4194,70 @@ size_t __hot mdbx_e2k_strnlen_bug_workaround(const char *s, size_t maxlen) { /*------------------------------------------------------------------------------ * safe read/write volatile 64-bit fields on 32-bit architectures. */ +MDBX_MAYBE_UNUSED static __always_inline uint64_t +atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, + enum MDBX_memory_order order) { + STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); +#if MDBX_64BIT_ATOMIC +#ifdef MDBX_HAVE_C11ATOMICS + assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); + atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); +#else /* MDBX_HAVE_C11ATOMICS */ + if (order != mo_Relaxed) + mdbx_compiler_barrier(); + p->weak = value; + mdbx_memory_fence(order, true); +#endif /* MDBX_HAVE_C11ATOMICS */ +#else /* !MDBX_64BIT_ATOMIC */ + mdbx_compiler_barrier(); + atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); + mdbx_jitter4testing(true); + atomic_store32(&p->high, (uint32_t)(value >> 32), order); + mdbx_jitter4testing(true); +#endif /* !MDBX_64BIT_ATOMIC */ + return value; +} + +MDBX_MAYBE_UNUSED static +#if MDBX_64BIT_ATOMIC + __always_inline +#endif /* MDBX_64BIT_ATOMIC */ + uint64_t + atomic_load64(const MDBX_atomic_uint64_t *p, + enum MDBX_memory_order order) { + STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); +#if MDBX_64BIT_ATOMIC +#ifdef MDBX_HAVE_C11ATOMICS + assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); + return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); +#else /* MDBX_HAVE_C11ATOMICS */ + mdbx_memory_fence(order, false); + const uint64_t value = p->weak; + if (order != mo_Relaxed) + mdbx_compiler_barrier(); + return value; +#endif /* MDBX_HAVE_C11ATOMICS */ +#else /* !MDBX_64BIT_ATOMIC */ + mdbx_compiler_barrier(); + uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; + mdbx_jitter4testing(true); + value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed + : mo_AcquireRelease); + mdbx_jitter4testing(true); + for (;;) { + mdbx_compiler_barrier(); + uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; + mdbx_jitter4testing(true); + again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed + : mo_AcquireRelease); + mdbx_jitter4testing(true); + if (likely(value == again)) + return value; + value = again; + } +#endif /* !MDBX_64BIT_ATOMIC */ +} + static __always_inline void atomic_yield(void) { #if defined(_WIN32) || defined(_WIN64) YieldProcessor(); @@ -4934,9 +4944,6 @@ static int uniq_peek(const mdbx_mmap_t *pending, mdbx_mmap_t *scan) { rc = MDBX_SUCCESS; } else { bait = 0 /* hush MSVC warning */; -#if MDBX_ENABLE_PGOP_STAT - safe64_inc(&scan_lck->mti_pgop_stat.wops, 1); -#endif /* MDBX_ENABLE_PGOP_STAT */ rc = mdbx_msync(scan, 0, sizeof(MDBX_lockinfo), MDBX_SYNC_DATA); if (rc == MDBX_SUCCESS) rc = mdbx_pread(pending->fd, &bait, sizeof(scan_lck->mti_bait_uniqueness), @@ -4993,9 +5000,6 @@ __cold static int uniq_check(const mdbx_mmap_t *pending, MDBX_env **found) { if (err == MDBX_RESULT_TRUE) err = uniq_poke(pending, &scan->me_lck_mmap, &salt); if (err == MDBX_RESULT_TRUE) { -#if MDBX_ENABLE_PGOP_STAT - safe64_inc(&scan->me_lck_mmap.lck->mti_pgop_stat.wops, 1); -#endif /* MDBX_ENABLE_PGOP_STAT */ (void)mdbx_msync(&scan->me_lck_mmap, 0, sizeof(MDBX_lockinfo), MDBX_SYNC_NONE); err = uniq_poke(pending, &scan->me_lck_mmap, &salt); @@ -8346,7 +8350,7 @@ static int mdbx_iov_write(MDBX_txn *const txn, struct mdbx_iov_ctx *ctx) { bytes2pgno(env, ctx->iov[i].iov_len)); #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&txn->mt_env->me_lck->mti_pgop_stat.wops, ctx->iov_items); + txn->mt_env->me_lck->mti_pgop_stat.wops.weak += ctx->iov_items; #endif /* MDBX_ENABLE_PGOP_STAT */ ctx->iov_items = 0; ctx->iov_bytes = 0; @@ -8411,7 +8415,7 @@ static int spill_page(MDBX_txn *txn, struct mdbx_iov_ctx *ctx, MDBX_page *dp, err = mdbx_pnl_append_range(true, &txn->tw.spill_pages, pgno << 1, npages); #if MDBX_ENABLE_PGOP_STAT if (likely(err == MDBX_SUCCESS)) - safe64_inc(&txn->mt_env->me_lck->mti_pgop_stat.spill, npages); + txn->mt_env->me_lck->mti_pgop_stat.spill.weak += npages; #endif /* MDBX_ENABLE_PGOP_STAT */ } return err; @@ -8592,7 +8596,7 @@ static int mdbx_txn_spill(MDBX_txn *const txn, MDBX_cursor *const m0, if (!MDBX_FAKE_SPILL_WRITEMAP && ctx.flush_end > ctx.flush_begin) { MDBX_env *const env = txn->mt_env; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ rc = mdbx_msync(&env->me_dxb_mmap, pgno_align2os_bytes(env, ctx.flush_begin), @@ -9419,7 +9423,7 @@ __cold static int mdbx_mapresize(MDBX_env *env, const pgno_t used_pgno, if ((env->me_flags & MDBX_WRITEMAP) && env->me_lck->mti_unsynced_pages.weak) { #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ rc = mdbx_msync(&env->me_dxb_mmap, 0, pgno_align2os_bytes(env, used_pgno), MDBX_SYNC_NONE); @@ -9570,7 +9574,7 @@ static int mdbx_meta_unsteady(MDBX_env *env, const txnid_t last_steady, __cold static int mdbx_wipe_steady(MDBX_env *env, const txnid_t last_steady) { #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ const mdbx_filehandle_t fd = (env->me_dsync_fd != INVALID_HANDLE_VALUE) ? env->me_dsync_fd @@ -10190,7 +10194,7 @@ mdbx_page_unspill(MDBX_txn *const txn, const MDBX_page *const mp) { if (unlikely(ret.err != MDBX_SUCCESS)) return ret; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&txn->mt_env->me_lck->mti_pgop_stat.unspill, npages); + txn->mt_env->me_lck->mti_pgop_stat.unspill.weak += npages; #endif /* MDBX_ENABLE_PGOP_STAT */ ret.page->mp_flags |= (scan == txn) ? 0 : P_SPILLED; ret.err = MDBX_SUCCESS; @@ -10263,7 +10267,7 @@ __hot static int mdbx_page_touch(MDBX_cursor *mc) { } #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&txn->mt_env->me_lck->mti_pgop_stat.cow, 1); + txn->mt_env->me_lck->mti_pgop_stat.cow.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ mdbx_page_copy(np, mp, txn->mt_env->me_psize); np->mp_pgno = pgno; @@ -10306,7 +10310,7 @@ __hot static int mdbx_page_touch(MDBX_cursor *mc) { goto fail; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&txn->mt_env->me_lck->mti_pgop_stat.clone, 1); + txn->mt_env->me_lck->mti_pgop_stat.clone.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ } @@ -10384,7 +10388,7 @@ __cold static int mdbx_env_sync_internal(MDBX_env *env, bool force, const size_t usedbytes = pgno_align2os_bytes(env, head->mm_geo.next); #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ mdbx_txn_unlock(env); @@ -10434,7 +10438,17 @@ __cold static int mdbx_env_sync_internal(MDBX_env *env, bool force, if (atomic_load32(&env->me_lck->mti_meta_sync_txnid, mo_Relaxed) != (uint32_t)head_txnid) { #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + if (need_unlock) + env->me_lck->mti_pgop_stat.wops.weak += 1; +#if MDBX_64BIT_ATOMIC + else { + MDBX_atomic_uint64_t *wops = &env->me_lck->mti_pgop_stat.wops; + while (unlikely(!atomic_cas64(wops, wops->weak, wops->weak + 1))) + atomic_yield(); + } +#else + /* loose the env->me_lck->mti_pgop_stat.wops.weak increment */ +#endif /* MDBX_64BIT_ATOMIC */ #endif /* MDBX_ENABLE_PGOP_STAT */ rc = (flags & MDBX_WRITEMAP) ? mdbx_msync(&env->me_dxb_mmap, 0, @@ -13913,9 +13927,7 @@ __cold static MDBX_page *mdbx_meta_model(const MDBX_env *env, MDBX_page *model, pages2pv(pv2pages(model_meta->mm_geo.shrink_pv))); model_meta->mm_psize = env->me_psize; - model_meta->mm_flags = (uint16_t)env->me_flags & DB_PERSISTENT_FLAGS; - model_meta->mm_flags = - MDBX_INTEGERKEY; /* this is mm_dbs[FREE_DBI].md_flags */ + model_meta->mm_dbs[FREE_DBI].md_flags = MDBX_INTEGERKEY; model_meta->mm_dbs[FREE_DBI].md_root = P_INVALID; model_meta->mm_dbs[MAIN_DBI].md_root = P_INVALID; mdbx_meta_set_txnid(env, model_meta, MIN_TXNID + num); @@ -14098,7 +14110,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, mode_bits |= MDBX_SYNC_IODQ; } #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ if (flags & MDBX_WRITEMAP) rc = @@ -14184,7 +14196,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, target == head || mdbx_meta_txnid_stable(env, target) < unaligned_peek_u64(4, pending->mm_txnid_a)); #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ if (flags & MDBX_WRITEMAP) { mdbx_jitter4testing(true); @@ -14195,7 +14207,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, unaligned_poke_u64(4, target->mm_datasync_sign, MDBX_DATASIGN_WEAK); #ifndef NDEBUG /* debug: provoke failure to catch a violators, but don't touch mm_psize - * and mm_flags to allow readers catch actual pagesize. */ + * to allow readers catch actual pagesize. */ uint8_t *provoke_begin = (uint8_t *)&target->mm_dbs[FREE_DBI].md_root; uint8_t *provoke_end = (uint8_t *)&target->mm_datasync_sign; memset(provoke_begin, 0xCC, provoke_end - provoke_begin); @@ -14243,7 +14255,7 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, ? env->me_dsync_fd : env->me_lazy_fd; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ rc = mdbx_pwrite(fd, pending, sizeof(MDBX_meta), (uint8_t *)target - env->me_map); @@ -15296,15 +15308,15 @@ __cold static int mdbx_setup_dxb(MDBX_env *env, const int lck_rc, if ((env->me_flags & MDBX_RDONLY) == 0 && env->me_stuck_meta < 0) { for (int n = 0; n < 3; ++n) { - MDBX_meta *const meta = METAPAGE(env, n); - if (unlikely(unaligned_peek_u64(4, &meta->mm_magic_and_version) != + MDBX_meta *const pmeta = METAPAGE(env, n); + if (unlikely(unaligned_peek_u64(4, &pmeta->mm_magic_and_version) != MDBX_DATA_MAGIC)) { - const txnid_t txnid = mdbx_meta_txnid_fluid(env, meta); + const txnid_t txnid = mdbx_meta_txnid_fluid(env, pmeta); mdbx_notice("%s %s" "meta[%u], txnid %" PRIaTXN, "updating db-format signature for", - META_IS_STEADY(meta) ? "stead-" : "weak-", n, txnid); - err = mdbx_override_meta(env, n, txnid, meta); + META_IS_STEADY(pmeta) ? "stead-" : "weak-", n, txnid); + err = mdbx_override_meta(env, n, txnid, pmeta); if (unlikely(err != MDBX_SUCCESS)) { mdbx_error("%s meta[%u], txnid %" PRIaTXN ", error %d", "updating db-format signature for", n, txnid, err); @@ -15642,7 +15654,7 @@ __cold static int __must_check_result mdbx_override_meta( return MDBX_PROBLEM; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.wops, 1); + env->me_lck->mti_pgop_stat.wops.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ if (env->me_flags & MDBX_WRITEMAP) { rc = mdbx_msync(&env->me_dxb_mmap, 0, @@ -18344,8 +18356,7 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, return err; #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&mc->mc_txn->mt_env->me_lck->mti_pgop_stat.clone, - ovpages); + mc->mc_txn->mt_env->me_lck->mti_pgop_stat.clone.weak += ovpages; #endif /* MDBX_ENABLE_PGOP_STAT */ mdbx_cassert(mc, mdbx_dirtylist_check(mc->mc_txn)); } @@ -18864,7 +18875,7 @@ static struct page_result mdbx_page_new(MDBX_cursor *mc, const unsigned flags, mdbx_cassert(mc, *mc->mc_dbistate & DBI_DIRTY); mdbx_cassert(mc, mc->mc_txn->mt_flags & MDBX_TXN_DIRTY); #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&mc->mc_txn->mt_env->me_lck->mti_pgop_stat.newly, npages); + mc->mc_txn->mt_env->me_lck->mti_pgop_stat.newly.weak += npages; #endif /* MDBX_ENABLE_PGOP_STAT */ if (likely((flags & P_OVERFLOW) == 0)) { @@ -20216,7 +20227,7 @@ static int mdbx_page_merge(MDBX_cursor *csrc, MDBX_cursor *cdst) { mdbx_cassert(cdst, cdst->mc_snum == cdst->mc_top + 1); #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&cdst->mc_txn->mt_env->me_lck->mti_pgop_stat.merge, 1); + cdst->mc_txn->mt_env->me_lck->mti_pgop_stat.merge.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ if (IS_LEAF(cdst->mc_pg[cdst->mc_top])) { @@ -21712,7 +21723,7 @@ static int mdbx_page_split(MDBX_cursor *mc, const MDBX_val *const newkey, newdata->iov_base = node_data(node); } #if MDBX_ENABLE_PGOP_STAT - safe64_inc(&env->me_lck->mti_pgop_stat.split, 1); + env->me_lck->mti_pgop_stat.split.weak += 1; #endif /* MDBX_ENABLE_PGOP_STAT */ } @@ -22739,31 +22750,11 @@ __cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, } #endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ -__cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, - MDBX_envinfo *arg, size_t bytes) { - if (unlikely((env == NULL && txn == NULL) || arg == NULL)) - return MDBX_EINVAL; - - if (txn) { - int err = check_txn(txn, MDBX_TXN_BLOCKED); - if (unlikely(err != MDBX_SUCCESS)) - return err; - } - if (env) { - int err = check_env(env, false); - if (unlikely(err != MDBX_SUCCESS)) - return err; - if (txn && unlikely(txn->mt_env != env)) - return MDBX_EINVAL; - } else { - env = txn->mt_env; - } +__cold static int fetch_envinfo_ex(const MDBX_env *env, const MDBX_txn *txn, + MDBX_envinfo *arg, const size_t bytes) { const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid); const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat); - if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid && - bytes != size_before_pgop_stat) - return MDBX_EINVAL; /* is the environment open? (https://github.com/erthink/libmdbx/issues/171) */ if (unlikely(!env->me_map)) { @@ -22793,64 +22784,48 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, const MDBX_meta *const meta0 = METAPAGE(env, 0); const MDBX_meta *const meta1 = METAPAGE(env, 1); const MDBX_meta *const meta2 = METAPAGE(env, 2); - pgno_t unsynced_pages; - while (1) { - if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) - return MDBX_PANIC; + if (unlikely(env->me_flags & MDBX_FATAL_ERROR)) + return MDBX_PANIC; - const MDBX_meta *const recent_meta = mdbx_meta_head(env); - arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, recent_meta); - arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0); - arg->mi_meta0_sign = unaligned_peek_u64(4, meta0->mm_datasync_sign); - arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1); - arg->mi_meta1_sign = unaligned_peek_u64(4, meta1->mm_datasync_sign); - arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); - arg->mi_meta2_sign = unaligned_peek_u64(4, meta2->mm_datasync_sign); - if (likely(bytes > size_before_bootid)) { - memcpy(&arg->mi_bootid.meta0, &meta0->mm_bootid, 16); - memcpy(&arg->mi_bootid.meta1, &meta1->mm_bootid, 16); - memcpy(&arg->mi_bootid.meta2, &meta2->mm_bootid, 16); - } - - const MDBX_meta *txn_meta = recent_meta; - arg->mi_last_pgno = txn_meta->mm_geo.next - 1; - arg->mi_geo.current = pgno2bytes(env, txn_meta->mm_geo.now); - if (txn) { - arg->mi_last_pgno = txn->mt_next_pgno - 1; - arg->mi_geo.current = pgno2bytes(env, txn->mt_end_pgno); - - const txnid_t wanna_meta_txnid = (txn->mt_flags & MDBX_TXN_RDONLY) - ? txn->mt_txnid - : txn->mt_txnid - xMDBX_TXNID_STEP; - txn_meta = (arg->mi_meta0_txnid == wanna_meta_txnid) ? meta0 : txn_meta; - txn_meta = (arg->mi_meta1_txnid == wanna_meta_txnid) ? meta1 : txn_meta; - txn_meta = (arg->mi_meta2_txnid == wanna_meta_txnid) ? meta2 : txn_meta; - } - arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower); - arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper); - arg->mi_geo.shrink = pgno2bytes(env, pv2pages(txn_meta->mm_geo.shrink_pv)); - arg->mi_geo.grow = pgno2bytes(env, pv2pages(txn_meta->mm_geo.grow_pv)); - unsynced_pages = - atomic_load32(&env->me_lck->mti_unsynced_pages, mo_Relaxed) + - (atomic_load32(&env->me_lck->mti_meta_sync_txnid, mo_Relaxed) != - (uint32_t)arg->mi_last_pgno); - - arg->mi_mapsize = env->me_dxb_mmap.limit; - mdbx_compiler_barrier(); - if (likely(arg->mi_meta0_txnid == mdbx_meta_txnid_fluid(env, meta0) && - arg->mi_meta0_sign == - unaligned_peek_u64(4, meta0->mm_datasync_sign) && - arg->mi_meta1_txnid == mdbx_meta_txnid_fluid(env, meta1) && - arg->mi_meta1_sign == - unaligned_peek_u64(4, meta1->mm_datasync_sign) && - arg->mi_meta2_txnid == mdbx_meta_txnid_fluid(env, meta2) && - arg->mi_meta2_sign == - unaligned_peek_u64(4, meta2->mm_datasync_sign) && - recent_meta == mdbx_meta_head(env) && - arg->mi_recent_txnid == mdbx_meta_txnid_fluid(env, recent_meta))) - break; + const MDBX_meta *const recent_meta = mdbx_meta_head(env); + arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, recent_meta); + arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0); + arg->mi_meta0_sign = unaligned_peek_u64(4, meta0->mm_datasync_sign); + arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1); + arg->mi_meta1_sign = unaligned_peek_u64(4, meta1->mm_datasync_sign); + arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); + arg->mi_meta2_sign = unaligned_peek_u64(4, meta2->mm_datasync_sign); + if (likely(bytes > size_before_bootid)) { + memcpy(&arg->mi_bootid.meta0, &meta0->mm_bootid, 16); + memcpy(&arg->mi_bootid.meta1, &meta1->mm_bootid, 16); + memcpy(&arg->mi_bootid.meta2, &meta2->mm_bootid, 16); } + const MDBX_meta *txn_meta = recent_meta; + arg->mi_last_pgno = txn_meta->mm_geo.next - 1; + arg->mi_geo.current = pgno2bytes(env, txn_meta->mm_geo.now); + if (txn) { + arg->mi_last_pgno = txn->mt_next_pgno - 1; + arg->mi_geo.current = pgno2bytes(env, txn->mt_end_pgno); + + const txnid_t wanna_meta_txnid = (txn->mt_flags & MDBX_TXN_RDONLY) + ? txn->mt_txnid + : txn->mt_txnid - xMDBX_TXNID_STEP; + txn_meta = (arg->mi_meta0_txnid == wanna_meta_txnid) ? meta0 : txn_meta; + txn_meta = (arg->mi_meta1_txnid == wanna_meta_txnid) ? meta1 : txn_meta; + txn_meta = (arg->mi_meta2_txnid == wanna_meta_txnid) ? meta2 : txn_meta; + } + arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower); + arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper); + arg->mi_geo.shrink = pgno2bytes(env, pv2pages(txn_meta->mm_geo.shrink_pv)); + arg->mi_geo.grow = pgno2bytes(env, pv2pages(txn_meta->mm_geo.grow_pv)); + const pgno_t unsynced_pages = + atomic_load32(&env->me_lck->mti_unsynced_pages, mo_Relaxed) + + (atomic_load32(&env->me_lck->mti_meta_sync_txnid, mo_Relaxed) != + (uint32_t)arg->mi_last_pgno); + + arg->mi_mapsize = env->me_dxb_mmap.limit; + const MDBX_lockinfo *const lck = env->me_lck; arg->mi_maxreaders = env->me_maxreaders; arg->mi_numreaders = env->me_lck_mmap.lck @@ -22916,9 +22891,51 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, } } + mdbx_compiler_barrier(); return MDBX_SUCCESS; } +__cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, + MDBX_envinfo *arg, size_t bytes) { + if (unlikely((env == NULL && txn == NULL) || arg == NULL)) + return MDBX_EINVAL; + + if (txn) { + int err = check_txn(txn, MDBX_TXN_BLOCKED); + if (unlikely(err != MDBX_SUCCESS)) + return err; + } + if (env) { + int err = check_env(env, false); + if (unlikely(err != MDBX_SUCCESS)) + return err; + if (txn && unlikely(txn->mt_env != env)) + return MDBX_EINVAL; + } else { + env = txn->mt_env; + } + + const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid); + const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat); + if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid && + bytes != size_before_pgop_stat) + return MDBX_EINVAL; + + MDBX_envinfo snap; + int rc = fetch_envinfo_ex(env, txn, &snap, sizeof(snap)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + + while (1) { + rc = fetch_envinfo_ex(env, txn, arg, sizeof(bytes)); + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + if (likely(memcmp(&snap, arg, bytes) == 0)) + return MDBX_SUCCESS; + memcpy(&snap, arg, bytes); + } +} + static __inline MDBX_cmp_func *get_default_keycmp(unsigned flags) { return (flags & MDBX_REVERSEKEY) ? cmp_reverse @@ -28480,9 +28497,9 @@ __dll_export 0, 11, 1, - 0, - {"2021-10-23T20:15:50+03:00", "d2935a94c0f91ab07ba6a941dd01f58965a0a8f7", "113162b6511e1de791599ac87914930a1f6b02ee", - "v0.11.1-0-g113162b6"}, + 21, + {"2021-11-16T16:18:26+08:00", "360f93c9fdf7ece2631c9e40e9d41e4be8cadb50", "f35b55ff7b2396cf864b8e890dea28449933e667", + "v0.11.1-21-gf35b55f"}, sourcery}; __dll_export diff --git a/mdbx-sys/libmdbx/mdbx.c++ b/mdbx-sys/libmdbx/mdbx.c++ index 26eb662..e41ea86 100644 --- a/mdbx-sys/libmdbx/mdbx.c++ +++ b/mdbx-sys/libmdbx/mdbx.c++ @@ -12,7 +12,7 @@ * . */ #define xMDBX_ALLOY 1 -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -62,6 +62,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -999,9 +1012,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1253,7 +1267,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2022,8 +2035,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2067,70 +2078,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2246,8 +2193,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3015,6 +2960,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3184,15 +3138,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3327,10 +3272,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif @@ -4415,7 +4361,8 @@ bool from_base64::is_erroneous() const noexcept { template class LIBMDBX_API_TYPE buffer; -#if defined(__cpp_lib_memory_resource) && __cpp_lib_memory_resource >= 201603L +#if defined(__cpp_lib_memory_resource) && \ + __cpp_lib_memory_resource >= 201603L && _GLIBCXX_USE_CXX11_ABI template class LIBMDBX_API_TYPE buffer; #endif /* __cpp_lib_memory_resource >= 201603L */ diff --git a/mdbx-sys/libmdbx/mdbx.h b/mdbx-sys/libmdbx/mdbx.h index 2a9f56f..e3bf898 100644 --- a/mdbx-sys/libmdbx/mdbx.h +++ b/mdbx-sys/libmdbx/mdbx.h @@ -393,7 +393,8 @@ typedef mode_t mdbx_mode_t; #define MDBX_CXX01_CONSTEXPR __inline #define MDBX_CXX01_CONSTEXPR_VAR const #elif !defined(DOXYGEN) && \ - (!defined(__cpp_constexpr) || __cpp_constexpr < 200704L || \ + ((__cplusplus < 201103L && defined(__cpp_constexpr) && \ + __cpp_constexpr < 200704L) || \ (defined(__LCC__) && __LCC__ < 124) || \ (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407) && \ !defined(__clang__) && !defined(__LCC__)) || \ @@ -410,7 +411,7 @@ typedef mode_t mdbx_mode_t; #define MDBX_CXX11_CONSTEXPR __inline #define MDBX_CXX11_CONSTEXPR_VAR const #elif !defined(DOXYGEN) && \ - (!defined(__cpp_constexpr) || __cpp_constexpr < 201304 || \ + (!defined(__cpp_constexpr) || __cpp_constexpr < 201304L || \ (defined(__LCC__) && __LCC__ < 124) || \ (defined(__GNUC__) && __GNUC__ < 6 && !defined(__clang__) && \ !defined(__LCC__)) || \ diff --git a/mdbx-sys/libmdbx/mdbx.h++ b/mdbx-sys/libmdbx/mdbx.h++ index 8390dcf..d47906e 100644 --- a/mdbx-sys/libmdbx/mdbx.h++ +++ b/mdbx-sys/libmdbx/mdbx.h++ @@ -286,7 +286,8 @@ class cursor; class cursor_managed; #if defined(DOXYGEN) || \ - defined(__cpp_lib_memory_resource) && __cpp_lib_memory_resource >= 201603L + (defined(__cpp_lib_memory_resource) && \ + __cpp_lib_memory_resource >= 201603L && _GLIBCXX_USE_CXX11_ABI) /// \brief Default polymorphic allocator for modern code. using polymorphic_allocator = ::std::pmr::string::allocator_type; #endif /* __cpp_lib_memory_resource >= 201603L */ diff --git a/mdbx-sys/libmdbx/mdbx_chk.c b/mdbx-sys/libmdbx/mdbx_chk.c index c9d1c5e..27249a3 100644 --- a/mdbx-sys/libmdbx/mdbx_chk.c +++ b/mdbx-sys/libmdbx/mdbx_chk.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -84,6 +84,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1021,9 +1034,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1275,7 +1289,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2044,8 +2057,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2089,70 +2100,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2268,8 +2215,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3037,6 +2982,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3206,15 +3160,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3349,10 +3294,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/mdbx-sys/libmdbx/mdbx_copy.c b/mdbx-sys/libmdbx/mdbx_copy.c index 0fd63d3..95a0849 100644 --- a/mdbx-sys/libmdbx/mdbx_copy.c +++ b/mdbx-sys/libmdbx/mdbx_copy.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -84,6 +84,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1021,9 +1034,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1275,7 +1289,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2044,8 +2057,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2089,70 +2100,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2268,8 +2215,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3037,6 +2982,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3206,15 +3160,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3349,10 +3294,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/mdbx-sys/libmdbx/mdbx_drop.c b/mdbx-sys/libmdbx/mdbx_drop.c index a9bbf2f..e18674e 100644 --- a/mdbx-sys/libmdbx/mdbx_drop.c +++ b/mdbx-sys/libmdbx/mdbx_drop.c @@ -36,7 +36,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -86,6 +86,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1023,9 +1036,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1277,7 +1291,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2046,8 +2059,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2091,70 +2102,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2270,8 +2217,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3039,6 +2984,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3208,15 +3162,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3351,10 +3296,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/mdbx-sys/libmdbx/mdbx_dump.c b/mdbx-sys/libmdbx/mdbx_dump.c index 7183561..3f5b24d 100644 --- a/mdbx-sys/libmdbx/mdbx_dump.c +++ b/mdbx-sys/libmdbx/mdbx_dump.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -84,6 +84,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1021,9 +1034,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1275,7 +1289,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2044,8 +2057,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2089,70 +2100,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2268,8 +2215,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3037,6 +2982,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3206,15 +3160,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3349,10 +3294,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/mdbx-sys/libmdbx/mdbx_load.c b/mdbx-sys/libmdbx/mdbx_load.c index c97df32..447cb28 100644 --- a/mdbx-sys/libmdbx/mdbx_load.c +++ b/mdbx-sys/libmdbx/mdbx_load.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -84,6 +84,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1021,9 +1034,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1275,7 +1289,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2044,8 +2057,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2089,70 +2100,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2268,8 +2215,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3037,6 +2982,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3206,15 +3160,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3349,10 +3294,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/mdbx-sys/libmdbx/mdbx_stat.c b/mdbx-sys/libmdbx/mdbx_stat.c index 5d9437d..76c478a 100644 --- a/mdbx-sys/libmdbx/mdbx_stat.c +++ b/mdbx-sys/libmdbx/mdbx_stat.c @@ -34,7 +34,7 @@ * top-level directory of the distribution or, alternatively, at * . */ -#define MDBX_BUILD_SOURCERY e5282b30d89e877fff2a5d79d89fc4ade5841a57bccc0bd61d79cbb4e8cf271f_v0_11_1_0_g113162b6 +#define MDBX_BUILD_SOURCERY e6a110a2cd2ab9f2e426d0d0cb7b8d28e8b7d968ca86837adf90de186a6cf646_v0_11_1_21_gf35b55f #ifdef MDBX_CONFIG_H #include MDBX_CONFIG_H #endif @@ -84,6 +84,19 @@ * Studio 2015 Update 3). But you could remove this #error and try to continue * at your own risk. In such case please don't rise up an issues related ONLY to * old compilers. + * + * NOTE: + * Unfortunately, there are several different builds of "Visual Studio" that + * are called "Visual Studio 2015 Update 3". + * + * The 190024234 is used here because it is minimal version of Visual Studio + * that was used for build and testing libmdbx in recent years. Soon this + * value will be increased to 19.0.24241.7, since build and testing using + * "Visual Studio 2015" will be performed only at https://ci.appveyor.com. + * + * Please ask Microsoft (but not us) for information about version differences + * and how to and where you can obtain the latest "Visual Studio 2015" build + * with all fixes. */ #error \ "At least \"Microsoft C/C++ Compiler\" version 19.00.24234 (Visual Studio 2015 Update 3) is required." @@ -1021,9 +1034,10 @@ typedef union MDBX_srwlock { } MDBX_srwlock; #endif /* Windows */ -#ifdef __cplusplus -extern void mdbx_osal_jitter(bool tiny); -#else +#ifndef __cplusplus + +MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny); /*----------------------------------------------------------------------------*/ /* Atomics */ @@ -1275,7 +1289,6 @@ MDBX_MAYBE_UNUSED static __inline uintptr_t mdbx_thread_self(void) { return (uintptr_t)thunk; } -MDBX_MAYBE_UNUSED MDBX_INTERNAL_FUNC void mdbx_osal_jitter(bool tiny); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_monotime(void); MDBX_INTERNAL_FUNC uint64_t mdbx_osal_16dot16_to_monotime(uint32_t seconds_16dot16); @@ -2044,8 +2057,6 @@ static __always_inline memory_order mo_c11_load(enum MDBX_memory_order fence) { #ifndef __cplusplus -static __inline void mdbx_jitter4testing(bool tiny); - MDBX_MAYBE_UNUSED static __always_inline void mdbx_memory_fence(enum MDBX_memory_order order, bool write) { #ifdef MDBX_HAVE_C11ATOMICS @@ -2089,70 +2100,6 @@ atomic_load32(const MDBX_atomic_uint32_t *p, enum MDBX_memory_order order) { #endif /* MDBX_HAVE_C11ATOMICS */ } -MDBX_MAYBE_UNUSED static __always_inline uint64_t -atomic_store64(MDBX_atomic_uint64_t *p, const uint64_t value, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p))); - atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - p->weak = value; - mdbx_memory_fence(order, true); -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - atomic_store32(&p->low, (uint32_t)value, mo_Relaxed); - mdbx_jitter4testing(true); - atomic_store32(&p->high, (uint32_t)(value >> 32), order); - mdbx_jitter4testing(true); -#endif /* !MDBX_64BIT_ATOMIC */ - return value; -} - -MDBX_MAYBE_UNUSED static -#if MDBX_64BIT_ATOMIC - __always_inline -#endif /* MDBX_64BIT_ATOMIC */ - uint64_t - atomic_load64(const MDBX_atomic_uint64_t *p, - enum MDBX_memory_order order) { - STATIC_ASSERT(sizeof(MDBX_atomic_uint64_t) == 8); -#if MDBX_64BIT_ATOMIC -#ifdef MDBX_HAVE_C11ATOMICS - assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p))); - return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order)); -#else /* MDBX_HAVE_C11ATOMICS */ - mdbx_memory_fence(order, false); - const uint64_t value = p->weak; - if (order != mo_Relaxed) - mdbx_compiler_barrier(); - return value; -#endif /* MDBX_HAVE_C11ATOMICS */ -#else /* !MDBX_64BIT_ATOMIC */ - mdbx_compiler_barrier(); - uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - for (;;) { - mdbx_compiler_barrier(); - uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32; - mdbx_jitter4testing(true); - again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed - : mo_AcquireRelease); - mdbx_jitter4testing(true); - if (likely(value == again)) - return value; - value = again; - } -#endif /* !MDBX_64BIT_ATOMIC */ -} - #endif /* !__cplusplus */ /*----------------------------------------------------------------------------*/ @@ -2268,8 +2215,6 @@ typedef struct MDBX_meta { MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ /* The size of pages used in this DB */ #define mm_psize mm_dbs[FREE_DBI].md_xsize -/* Any persistent environment flags, see mdbx_env */ -#define mm_flags mm_dbs[FREE_DBI].md_flags MDBX_canary mm_canary; #define MDBX_DATASIGN_NONE 0u @@ -3037,6 +2982,15 @@ extern uint8_t mdbx_runtime_flags; extern uint8_t mdbx_loglevel; extern MDBX_debug_func *mdbx_debug_logger; +MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { +#if MDBX_DEBUG + if (MDBX_DBG_JITTER & mdbx_runtime_flags) + mdbx_osal_jitter(tiny); +#else + (void)tiny; +#endif +} + MDBX_INTERNAL_FUNC void MDBX_PRINTF_ARGS(4, 5) mdbx_debug_log(int level, const char *function, int line, const char *fmt, ...) MDBX_PRINTF_ARGS(4, 5); @@ -3206,15 +3160,6 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_global_init(void); MDBX_INTERNAL_FUNC void mdbx_rthc_global_dtor(void); MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); -MDBX_MAYBE_UNUSED static __inline void mdbx_jitter4testing(bool tiny) { -#if MDBX_DEBUG - if (MDBX_DBG_JITTER & mdbx_runtime_flags) - mdbx_osal_jitter(tiny); -#else - (void)tiny; -#endif -} - #endif /* !__cplusplus */ #define MDBX_IS_ERROR(rc) \ @@ -3349,10 +3294,11 @@ typedef struct MDBX_node { * | 1, a > b * \ */ -#if 1 +#ifndef __e2k__ /* LY: fast enough on most systems */ #define CMP2INT(a, b) (((b) > (a)) ? -1 : (a) > (b)) #else +/* LY: more parallelable on VLIW Elbrus */ #define CMP2INT(a, b) (((a) > (b)) - ((b) > (a))) #endif diff --git a/src/codec.rs b/src/codec.rs index eef4124..2b0c6a1 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -1,4 +1,4 @@ -use crate::{error::mdbx_result, Error, TransactionKind}; +use crate::{mdbx_result, Error, TransactionKind}; use derive_more::*; use lifetimed_bytes::Bytes; use std::{borrow::Cow, slice}; @@ -34,7 +34,8 @@ impl<'tx> TableObject<'tx> for Cow<'tx, [u8]> { txn: *const ffi::MDBX_txn, data_val: &ffi::MDBX_val, ) -> Result { - let is_dirty = (!K::ONLY_CLEAN) && mdbx_result(ffi::mdbx_is_dirty(txn, data_val.iov_base))?; + let is_dirty = + (!K::ONLY_CLEAN) && mdbx_result!(ffi::mdbx_is_dirty(txn, data_val.iov_base))?; let s = slice::from_raw_parts(data_val.iov_base as *const u8, data_val.iov_len); diff --git a/src/cursor.rs b/src/cursor.rs index 3f874dd..8c798a4 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -1,18 +1,12 @@ use crate::{ database::Database, - error::{mdbx_result, Error, Result}, - flags::*, - mdbx_try_optional, + error::{Error, Result}, + mdbx_result, mdbx_try_optional, transaction::{txn_execute, TransactionKind, RW}, EnvironmentKind, TableObject, Transaction, }; -use ffi::{ - MDBX_cursor_op, MDBX_FIRST, MDBX_FIRST_DUP, MDBX_GET_BOTH, MDBX_GET_BOTH_RANGE, - MDBX_GET_CURRENT, MDBX_GET_MULTIPLE, MDBX_LAST, MDBX_LAST_DUP, MDBX_NEXT, MDBX_NEXT_DUP, - MDBX_NEXT_MULTIPLE, MDBX_NEXT_NODUP, MDBX_PREV, MDBX_PREV_DUP, MDBX_PREV_MULTIPLE, - MDBX_PREV_NODUP, MDBX_SET, MDBX_SET_KEY, MDBX_SET_LOWERBOUND, MDBX_SET_RANGE, -}; -use libc::{c_uint, c_void}; +use ffi::{MDBX_cursor_op, MDBX_error_t}; +use libc::c_void; use parking_lot::Mutex; use std::{borrow::Cow, fmt, marker::PhantomData, mem, ptr, result, sync::Arc}; @@ -38,7 +32,7 @@ where let txn = txn.txn_mutex(); unsafe { - mdbx_result(txn_execute(&*txn, |txn| { + mdbx_result!(txn_execute(&*txn, |txn| { ffi::mdbx_cursor_open(txn, db.dbi(), &mut cursor) }))?; } @@ -61,7 +55,7 @@ where _marker: PhantomData, }; - mdbx_result(res)?; + mdbx_result!(res)?; Ok(s) } @@ -93,7 +87,7 @@ where let key_ptr = key_val.iov_base; let data_ptr = data_val.iov_base; txn_execute(&*self.txn, |txn| { - let v = mdbx_result(ffi::mdbx_cursor_get( + let v = mdbx_result!(ffi::mdbx_cursor_get( self.cursor, &mut key_val, &mut data_val, @@ -149,31 +143,31 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_FIRST) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_FIRST) } - /// [DatabaseFlags::DUP_SORT]-only: Position at first data item of current key. + /// [ffi::MDBX_db_flags_t::DUP_SORT]-only: Position at first data item of current key. pub fn first_dup(&mut self) -> Result> where Value: TableObject<'txn>, { - self.get_value(None, None, MDBX_FIRST_DUP) + self.get_value(None, None, ffi::MDBX_cursor_op::MDBX_FIRST_DUP) } - /// [DatabaseFlags::DUP_SORT]-only: Position at key/data pair. + /// [ffi::MDBX_db_flags_t::DUP_SORT]-only: Position at key/data pair. pub fn get_both(&mut self, k: &[u8], v: &[u8]) -> Result> where Value: TableObject<'txn>, { - self.get_value(Some(k), Some(v), MDBX_GET_BOTH) + self.get_value(Some(k), Some(v), ffi::MDBX_cursor_op::MDBX_GET_BOTH) } - /// [DatabaseFlags::DUP_SORT]-only: Position at given key and at first data greater than or equal to specified data. + /// [ffi::MDBX_db_flags_t::DUP_SORT]-only: Position at given key and at first data greater than or equal to specified data. pub fn get_both_range(&mut self, k: &[u8], v: &[u8]) -> Result> where Value: TableObject<'txn>, { - self.get_value(Some(k), Some(v), MDBX_GET_BOTH_RANGE) + self.get_value(Some(k), Some(v), ffi::MDBX_cursor_op::MDBX_GET_BOTH_RANGE) } /// Return key/data at current cursor position. @@ -182,7 +176,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_GET_CURRENT) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_GET_CURRENT) } /// DupFixed-only: Return up to a page of duplicate data items from current cursor position. @@ -191,7 +185,7 @@ where where Value: TableObject<'txn>, { - self.get_value(None, None, MDBX_GET_MULTIPLE) + self.get_value(None, None, ffi::MDBX_cursor_op::MDBX_GET_MULTIPLE) } /// Position at last key/data item. @@ -200,7 +194,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_LAST) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_LAST) } /// DupSort-only: Position at last data item of current key. @@ -208,7 +202,7 @@ where where Value: TableObject<'txn>, { - self.get_value(None, None, MDBX_LAST_DUP) + self.get_value(None, None, ffi::MDBX_cursor_op::MDBX_LAST_DUP) } /// Position at next data item @@ -218,25 +212,25 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_NEXT) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_NEXT) } - /// [DatabaseFlags::DUP_SORT]-only: Position at next data item of current key. + /// [ffi::MDBX_db_flags_t::DUP_SORT]-only: Position at next data item of current key. pub fn next_dup(&mut self) -> Result> where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_NEXT_DUP) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_NEXT_DUP) } - /// [DatabaseFlags::DUP_FIXED]-only: Return up to a page of duplicate data items from next cursor position. Move cursor to prepare for MDBX_NEXT_MULTIPLE. + /// [ffi::MDBX_db_flags_t::DUP_FIXED]-only: Return up to a page of duplicate data items from next cursor position. Move cursor to prepare for ffi::MDBX_cursor_op::MDBX_NEXT_MULTIPLE. pub fn next_multiple(&mut self) -> Result> where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_NEXT_MULTIPLE) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_NEXT_MULTIPLE) } /// Position at first data item of next key. @@ -245,7 +239,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_NEXT_NODUP) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_NEXT_NODUP) } /// Position at previous data item. @@ -254,16 +248,16 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_PREV) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_PREV) } - /// [DatabaseFlags::DUP_SORT]-only: Position at previous data item of current key. + /// [ffi::MDBX_db_flags_t::DUP_SORT]-only: Position at previous data item of current key. pub fn prev_dup(&mut self) -> Result> where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_PREV_DUP) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_PREV_DUP) } /// Position at last data item of previous key. @@ -272,7 +266,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_PREV_NODUP) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_PREV_NODUP) } /// Position at specified key. @@ -280,7 +274,7 @@ where where Value: TableObject<'txn>, { - self.get_value(Some(key), None, MDBX_SET) + self.get_value(Some(key), None, ffi::MDBX_cursor_op::MDBX_SET) } /// Position at specified key, return both key and data. @@ -289,7 +283,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(Some(key), None, MDBX_SET_KEY) + self.get_full(Some(key), None, ffi::MDBX_cursor_op::MDBX_SET_KEY) } /// Position at first key greater than or equal to specified key. @@ -298,16 +292,16 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(Some(key), None, MDBX_SET_RANGE) + self.get_full(Some(key), None, ffi::MDBX_cursor_op::MDBX_SET_RANGE) } - /// [DatabaseFlags::DUP_FIXED]-only: Position at previous page and return up to a page of duplicate data items. + /// [ffi::MDBX_db_flags_t::DUP_FIXED]-only: Position at previous page and return up to a page of duplicate data items. pub fn prev_multiple(&mut self) -> Result> where Key: TableObject<'txn>, Value: TableObject<'txn>, { - self.get_full(None, None, MDBX_PREV_MULTIPLE) + self.get_full(None, None, ffi::MDBX_cursor_op::MDBX_PREV_MULTIPLE) } /// Position at first key-value pair greater than or equal to specified, return both key and data, and the return code depends on a exact match. @@ -321,7 +315,8 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - let (k, v, found) = mdbx_try_optional!(self.get(Some(key), None, MDBX_SET_LOWERBOUND)); + let (k, v, found) = + mdbx_try_optional!(self.get(Some(key), None, ffi::MDBX_cursor_op::MDBX_SET_LOWERBOUND)); Ok(Some((found, k.unwrap(), v))) } @@ -330,7 +325,7 @@ where /// after the cursor, and continue until the end of the database. For new /// cursors, the iterator will begin with the first item in the database. /// - /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the + /// For databases with duplicate data items ([ffi::MDBX_db_flags_t::DUP_SORT]), the /// duplicate data items of each key will be returned before moving on to /// the next key. pub fn iter(&mut self) -> Iter<'txn, '_, K, Key, Value> @@ -339,12 +334,16 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT) + Iter::new( + self, + ffi::MDBX_cursor_op::MDBX_NEXT, + ffi::MDBX_cursor_op::MDBX_NEXT, + ) } /// Iterate over database items starting from the beginning of the database. /// - /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the + /// For databases with duplicate data items ([ffi::MDBX_db_flags_t::DUP_SORT]), the /// duplicate data items of each key will be returned before moving on to /// the next key. pub fn iter_start(&mut self) -> Iter<'txn, '_, K, Key, Value> @@ -353,12 +352,16 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - Iter::new(self, ffi::MDBX_FIRST, ffi::MDBX_NEXT) + Iter::new( + self, + ffi::MDBX_cursor_op::MDBX_FIRST, + ffi::MDBX_cursor_op::MDBX_NEXT, + ) } /// Iterate over database items starting from the given key. /// - /// For databases with duplicate data items ([DatabaseFlags::DUP_SORT]), the + /// For databases with duplicate data items ([ffi::MDBX_db_flags_t::DUP_SORT]), the /// duplicate data items of each key will be returned before moving on to /// the next key. pub fn iter_from(&mut self, key: &[u8]) -> Iter<'txn, '_, K, Key, Value> @@ -370,7 +373,11 @@ where if let Err(error) = res { return Iter::Err(Some(error)); }; - Iter::new(self, ffi::MDBX_GET_CURRENT, ffi::MDBX_NEXT) + Iter::new( + self, + ffi::MDBX_cursor_op::MDBX_GET_CURRENT, + ffi::MDBX_cursor_op::MDBX_NEXT, + ) } /// Iterate over duplicate database items. The iterator will begin with the @@ -381,7 +388,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - IterDup::new(self, ffi::MDBX_NEXT) + IterDup::new(self, ffi::MDBX_cursor_op::MDBX_NEXT) } /// Iterate over duplicate database items starting from the beginning of the @@ -391,7 +398,7 @@ where Key: TableObject<'txn>, Value: TableObject<'txn>, { - IterDup::new(self, ffi::MDBX_FIRST) + IterDup::new(self, ffi::MDBX_cursor_op::MDBX_FIRST) } /// Iterate over duplicate items in the database starting from the given @@ -405,7 +412,7 @@ where if let Err(error) = res { return IterDup::Err(Some(error)); }; - IterDup::new(self, ffi::MDBX_GET_CURRENT) + IterDup::new(self, ffi::MDBX_cursor_op::MDBX_GET_CURRENT) } /// Iterate over the duplicates of the item in the database with the given key. @@ -419,18 +426,26 @@ where Ok(Some(_)) => (), Ok(None) => { let _: Result> = self.last(); - return Iter::new(self, ffi::MDBX_NEXT, ffi::MDBX_NEXT); + return Iter::new( + self, + ffi::MDBX_cursor_op::MDBX_NEXT, + ffi::MDBX_cursor_op::MDBX_NEXT, + ); } Err(error) => return Iter::Err(Some(error)), }; - Iter::new(self, ffi::MDBX_GET_CURRENT, ffi::MDBX_NEXT_DUP) + Iter::new( + self, + ffi::MDBX_cursor_op::MDBX_GET_CURRENT, + ffi::MDBX_cursor_op::MDBX_NEXT_DUP, + ) } } impl<'txn> Cursor<'txn, RW> { /// Puts a key/data pair into the database. The cursor will be positioned at /// the new data item, or on failure usually near it. - pub fn put(&mut self, key: &[u8], data: &[u8], flags: WriteFlags) -> Result<()> { + pub fn put(&mut self, key: &[u8], data: &[u8], flags: ffi::MDBX_put_flags_t) -> Result<()> { let key_val: ffi::MDBX_val = ffi::MDBX_val { iov_len: key.len(), iov_base: key.as_ptr() as *mut c_void, @@ -439,9 +454,10 @@ impl<'txn> Cursor<'txn, RW> { iov_len: data.len(), iov_base: data.as_ptr() as *mut c_void, }; - mdbx_result(unsafe { + mdbx_result!(unsafe { txn_execute(&*self.txn, |_| { - ffi::mdbx_cursor_put(self.cursor, &key_val, &mut data_val, flags.bits()) + let _ = &self; + ffi::mdbx_cursor_put(self.cursor, &key_val, &mut data_val, flags) }) })?; @@ -452,13 +468,11 @@ impl<'txn> Cursor<'txn, RW> { /// /// ### Flags /// - /// [WriteFlags::NO_DUP_DATA] may be used to delete all data items for the - /// current key, if the database was opened with [DatabaseFlags::DUP_SORT]. - pub fn del(&mut self, flags: WriteFlags) -> Result<()> { - mdbx_result(unsafe { - txn_execute(&*self.txn, |_| { - ffi::mdbx_cursor_del(self.cursor, flags.bits()) - }) + /// [ffi::MDBX_put_flags_t::NO_DUP_DATA] may be used to delete all data items for the + /// current key, if the database was opened with [ffi::MDBX_db_flags_t::DUP_SORT]. + pub fn del(&mut self, flags: ffi::MDBX_put_flags_t) -> Result<()> { + mdbx_result!(unsafe { + txn_execute(&*self.txn, |_| { let _ = &self; ffi::mdbx_cursor_del(self.cursor, flags) }) })?; Ok(()) @@ -488,9 +502,9 @@ where K: TransactionKind, { fn drop(&mut self) { - txn_execute(&*self.txn, |_| unsafe { + txn_execute(&*self.txn, |_| { let _ = &self; unsafe { ffi::mdbx_cursor_close(self.cursor) - }) + } }) } } @@ -518,7 +532,11 @@ where type IntoIter = IntoIter<'txn, K, Cow<'txn, [u8]>, Cow<'txn, [u8]>>; fn into_iter(self) -> Self::IntoIter { - IntoIter::new(self, MDBX_NEXT, MDBX_NEXT) + IntoIter::new( + self, + ffi::MDBX_cursor_op::MDBX_NEXT, + ffi::MDBX_cursor_op::MDBX_NEXT, + ) } } @@ -599,8 +617,13 @@ where let op = mem::replace(op, *next_op); unsafe { txn_execute(&*cursor.txn, |txn| { - match ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) { - ffi::MDBX_SUCCESS => { + match MDBX_error_t(ffi::mdbx_cursor_get( + cursor.cursor(), + &mut key, + &mut data, + op, + )) { + MDBX_error_t::MDBX_SUCCESS => { let key = match Key::decode_val::(txn, &key) { Ok(v) => v, Err(e) => return Some(Err(e)), @@ -613,7 +636,7 @@ where } // EINVAL can occur when the cursor was previously seeked to a non-existent value, // e.g. iter_from with a key greater than all values in the database. - ffi::MDBX_NOTFOUND | libc::ENODATA => None, + MDBX_error_t::MDBX_NOTFOUND | MDBX_error_t::MDBX_ENODATA => None, error => Some(Err(Error::from_err_code(error))), } }) @@ -705,8 +728,13 @@ where let op = mem::replace(op, *next_op); unsafe { txn_execute(&*cursor.txn, |txn| { - match ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) { - ffi::MDBX_SUCCESS => { + match MDBX_error_t(ffi::mdbx_cursor_get( + cursor.cursor(), + &mut key, + &mut data, + op, + )) { + MDBX_error_t::MDBX_SUCCESS => { let key = match Key::decode_val::(txn, &key) { Ok(v) => v, Err(e) => return Some(Err(e)), @@ -719,7 +747,7 @@ where } // EINVAL can occur when the cursor was previously seeked to a non-existent value, // e.g. iter_from with a key greater than all values in the database. - ffi::MDBX_NOTFOUND | libc::ENODATA => None, + MDBX_error_t::MDBX_NOTFOUND | MDBX_error_t::MDBX_ENODATA => None, error => Some(Err(Error::from_err_code(error))), } }) @@ -756,7 +784,7 @@ where cursor: &'cur mut Cursor<'txn, K>, /// The first operation to perform when the consumer calls Iter.next(). - op: c_uint, + op: MDBX_cursor_op, _marker: PhantomData, }, @@ -769,7 +797,7 @@ where Value: TableObject<'txn>, { /// Creates a new iterator backed by the given cursor. - fn new(cursor: &'cur mut Cursor<'txn, K>, op: c_uint) -> Self { + fn new(cursor: &'cur mut Cursor<'txn, K>, op: MDBX_cursor_op) -> Self { IterDup::Ok { cursor, op, @@ -808,17 +836,17 @@ where iov_len: 0, iov_base: ptr::null_mut(), }; - let op = mem::replace(op, ffi::MDBX_NEXT_NODUP); + let op = mem::replace(op, ffi::MDBX_cursor_op::MDBX_NEXT_NODUP); txn_execute(&*cursor.txn, |_| { let err_code = unsafe { ffi::mdbx_cursor_get(cursor.cursor(), &mut key, &mut data, op) }; - if err_code == ffi::MDBX_SUCCESS { + if MDBX_error_t(err_code) == MDBX_error_t::MDBX_SUCCESS { Some(IntoIter::new( Cursor::new_at_position(&**cursor).unwrap(), - ffi::MDBX_GET_CURRENT, - ffi::MDBX_NEXT_DUP, + ffi::MDBX_cursor_op::MDBX_GET_CURRENT, + ffi::MDBX_cursor_op::MDBX_NEXT_DUP, )) } else { None @@ -848,9 +876,12 @@ mod test { assert_eq!(None, txn.cursor(&db).unwrap().first::<(), ()>().unwrap()); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + txn.put(&db, b"key1", b"val1", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val3", ffi::MDBX_put_flags_t::empty()) + .unwrap(); let mut cursor = txn.cursor(&db).unwrap(); assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1"))); @@ -872,13 +903,19 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val3", WriteFlags::empty()).unwrap(); + let db = txn.create_db(None, ffi::MDBX_db_flags_t::DUP_SORT).unwrap(); + txn.put(&db, b"key1", b"val1", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val2", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val3", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val1", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val3", ffi::MDBX_put_flags_t::empty()) + .unwrap(); let mut cursor = txn.cursor(&db).unwrap(); assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1"))); @@ -911,14 +948,23 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn - .create_db(None, DatabaseFlags::DUP_SORT | DatabaseFlags::DUP_FIXED) + .create_db( + None, + ffi::MDBX_db_flags_t::DUP_SORT | ffi::MDBX_db_flags_t::DUP_FIXED, + ) + .unwrap(); + txn.put(&db, b"key1", b"val1", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val2", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val3", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val4", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val5", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val6", ffi::MDBX_put_flags_t::empty()) .unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val4", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val5", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val6", WriteFlags::empty()).unwrap(); let mut cursor = txn.cursor(&db).unwrap(); assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1"))); @@ -942,7 +988,8 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); for (key, data) in &items { - txn.put(&db, key, data, WriteFlags::empty()).unwrap(); + txn.put(&db, key, data, ffi::MDBX_put_flags_t::empty()) + .unwrap(); } assert!(!txn.commit().unwrap()); } @@ -1015,7 +1062,7 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); + txn.create_db(None, ffi::MDBX_db_flags_t::DUP_SORT).unwrap(); txn.commit().unwrap(); let txn = env.begin_ro_txn().unwrap(); @@ -1042,7 +1089,7 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); + txn.create_db(None, ffi::MDBX_db_flags_t::DUP_SORT).unwrap(); txn.commit().unwrap(); let items: Vec<(_, _)> = [ @@ -1067,7 +1114,8 @@ mod test { let txn = env.begin_rw_txn().unwrap(); for (key, data) in items.clone() { let db = txn.open_db(None).unwrap(); - txn.put(&db, key, data, WriteFlags::empty()).unwrap(); + txn.put(&db, key, data, ffi::MDBX_put_flags_t::empty()) + .unwrap(); } txn.commit().unwrap(); } @@ -1173,7 +1221,7 @@ mod test { let items = vec![(*b"a", *b"1"), (*b"b", *b"2")]; { let txn = env.begin_rw_txn().unwrap(); - let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); + let db = txn.create_db(None, ffi::MDBX_db_flags_t::DUP_SORT).unwrap(); assert_eq!( txn.cursor(&db) .unwrap() @@ -1190,7 +1238,8 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); for (key, data) in &items { - txn.put(&db, key, data, WriteFlags::empty()).unwrap(); + txn.put(&db, key, data, ffi::MDBX_put_flags_t::empty()) + .unwrap(); } txn.commit().unwrap(); } @@ -1217,7 +1266,7 @@ mod test { assert_eq!(cursor.set(b"a").unwrap(), Some(*b"1")); - cursor.del(WriteFlags::empty()).unwrap(); + cursor.del(ffi::MDBX_put_flags_t::empty()).unwrap(); assert_eq!( cursor @@ -1238,9 +1287,15 @@ mod test { let db = txn.open_db(None).unwrap(); let mut cursor = txn.cursor(&db).unwrap(); - cursor.put(b"key1", b"val1", WriteFlags::empty()).unwrap(); - cursor.put(b"key2", b"val2", WriteFlags::empty()).unwrap(); - cursor.put(b"key3", b"val3", WriteFlags::empty()).unwrap(); + cursor + .put(b"key1", b"val1", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + cursor + .put(b"key2", b"val2", ffi::MDBX_put_flags_t::empty()) + .unwrap(); + cursor + .put(b"key3", b"val3", ffi::MDBX_put_flags_t::empty()) + .unwrap(); assert_eq!( cursor.get_current().unwrap().unwrap(), @@ -1250,7 +1305,7 @@ mod test { ) ); - cursor.del(WriteFlags::empty()).unwrap(); + cursor.del(ffi::MDBX_put_flags_t::empty()).unwrap(); assert_eq!( cursor.last().unwrap().unwrap(), ( diff --git a/src/database.rs b/src/database.rs index 227a26c..fd5013b 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,10 +1,11 @@ use crate::{ environment::EnvironmentKind, - error::{mdbx_result, Result}, + error::Result, + mdbx_result, transaction::{txn_execute, TransactionKind}, Transaction, }; -use libc::c_uint; +use ffi::MDBX_db_flags_t; use std::{ffi::CString, marker::PhantomData, ptr}; /// A handle to an individual database in an environment. @@ -24,7 +25,7 @@ impl<'txn> Database<'txn> { pub(crate) fn new<'env, K: TransactionKind, E: EnvironmentKind>( txn: &'txn Transaction<'env, K, E>, name: Option<&str>, - flags: c_uint, + flags: MDBX_db_flags_t, ) -> Result { let c_name = name.map(|n| CString::new(n).unwrap()); let name_ptr = if let Some(c_name) = &c_name { @@ -33,7 +34,7 @@ impl<'txn> Database<'txn> { ptr::null() }; let mut dbi: ffi::MDBX_dbi = 0; - mdbx_result(txn_execute(&*txn.txn_mutex(), |txn| unsafe { + mdbx_result!(txn_execute(&*txn.txn_mutex(), |txn| unsafe { ffi::mdbx_dbi_open(txn, name_ptr, flags, &mut dbi) }))?; Ok(Self::new_from_ptr(dbi)) diff --git a/src/environment.rs b/src/environment.rs index 60e67ef..1d02886 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,15 +1,16 @@ use crate::{ database::Database, - error::{mdbx_result, Error, Result}, + error::{Error, Result}, flags::EnvironmentFlags, + mdbx_result, transaction::{RO, RW}, Mode, Transaction, TransactionKind, }; use byteorder::{ByteOrder, NativeEndian}; +use ffi::{MDBX_env_flags_t, MDBX_option_t::*}; use libc::c_uint; use mem::size_of; -#[cfg(unix)] -use std::os::unix::ffi::OsStrExt; +use os_str_bytes::OsStrBytes; use std::{ ffi::CString, fmt, @@ -34,7 +35,7 @@ mod private { } pub trait EnvironmentKind: private::Sealed + Debug + 'static { - const EXTRA_FLAGS: ffi::MDBX_env_flags_t; + const EXTRA_FLAGS: MDBX_env_flags_t; } #[derive(Debug)] @@ -43,10 +44,10 @@ pub struct NoWriteMap; pub struct WriteMap; impl EnvironmentKind for NoWriteMap { - const EXTRA_FLAGS: ffi::MDBX_env_flags_t = ffi::MDBX_ENV_DEFAULTS; + const EXTRA_FLAGS: MDBX_env_flags_t = ffi::MDBX_env_flags_t::MDBX_ENV_DEFAULTS; } impl EnvironmentKind for WriteMap { - const EXTRA_FLAGS: ffi::MDBX_env_flags_t = ffi::MDBX_WRITEMAP; + const EXTRA_FLAGS: MDBX_env_flags_t = ffi::MDBX_env_flags_t::MDBX_WRITEMAP; } #[derive(Copy, Clone, Debug)] @@ -146,14 +147,14 @@ where /// Flush the environment data buffers to disk. pub fn sync(&self, force: bool) -> Result { - mdbx_result(unsafe { ffi::mdbx_env_sync_ex(self.env(), force, false) }) + mdbx_result!(unsafe { ffi::mdbx_env_sync_ex(self.env(), force, false) }) } /// Retrieves statistics about this environment. pub fn stat(&self) -> Result { unsafe { let mut stat = Stat::new(); - mdbx_result(ffi::mdbx_env_stat_ex( + mdbx_result!(ffi::mdbx_env_stat_ex( self.env(), ptr::null(), stat.mdb_stat(), @@ -167,7 +168,7 @@ where pub fn info(&self) -> Result { unsafe { let mut info = Info(mem::zeroed()); - mdbx_result(ffi::mdbx_env_info_ex( + mdbx_result!(ffi::mdbx_env_info_ex( self.env(), ptr::null(), &mut info.0, @@ -430,7 +431,7 @@ where ) -> Result> { let mut env: *mut ffi::MDBX_env = ptr::null_mut(); unsafe { - mdbx_result(ffi::mdbx_env_create(&mut env))?; + mdbx_result!(ffi::mdbx_env_create(&mut env))?; if let Err(e) = (|| { if let Some(geometry) = &self.geometry { let mut min_size = -1; @@ -446,7 +447,7 @@ where } } - mdbx_result(ffi::mdbx_env_set_geometry( + mdbx_result!(ffi::mdbx_env_set_geometry( env, min_size, -1, @@ -461,30 +462,24 @@ where ))?; } for (opt, v) in [ - (ffi::MDBX_opt_max_db, self.max_dbs), - (ffi::MDBX_opt_rp_augment_limit, self.rp_augment_limit), - (ffi::MDBX_opt_loose_limit, self.loose_limit), - (ffi::MDBX_opt_dp_reserve_limit, self.dp_reserve_limit), - (ffi::MDBX_opt_txn_dp_limit, self.txn_dp_limit), - ( - ffi::MDBX_opt_spill_max_denominator, - self.spill_max_denominator, - ), - ( - ffi::MDBX_opt_spill_min_denominator, - self.spill_min_denominator, - ), + (MDBX_opt_max_db, self.max_dbs), + (MDBX_opt_rp_augment_limit, self.rp_augment_limit), + (MDBX_opt_loose_limit, self.loose_limit), + (MDBX_opt_dp_reserve_limit, self.dp_reserve_limit), + (MDBX_opt_txn_dp_limit, self.txn_dp_limit), + (MDBX_opt_spill_max_denominator, self.spill_max_denominator), + (MDBX_opt_spill_min_denominator, self.spill_min_denominator), ] { if let Some(v) = v { - mdbx_result(ffi::mdbx_env_set_option(env, opt, v))?; + mdbx_result!(ffi::mdbx_env_set_option(env, opt, v))?; } } - let path = match CString::new(path.as_os_str().as_bytes()) { + let path = match CString::new(path.as_os_str().to_raw_bytes()) { Ok(path) => path, Err(..) => return Err(crate::Error::Invalid), }; - mdbx_result(ffi::mdbx_env_open( + mdbx_result!(ffi::mdbx_env_open( env, path.as_ptr(), self.flags.make_flags() | E::EXTRA_FLAGS, @@ -508,7 +503,7 @@ where if let Mode::ReadWrite { .. } = self.flags.mode { let (tx, rx) = std::sync::mpsc::sync_channel(0); let e = EnvPtr(env.env); - std::thread::spawn(move || loop { + std::thread::spawn(move || { let _ = &e; loop { match rx.recv() { Ok(msg) => match msg { TxnManagerMessage::Begin { @@ -519,7 +514,7 @@ where let mut txn: *mut ffi::MDBX_txn = ptr::null_mut(); sender .send( - mdbx_result(unsafe { + mdbx_result!(unsafe { ffi::mdbx_txn_begin_ex( e.0, parent.0, @@ -534,12 +529,12 @@ where } TxnManagerMessage::Abort { tx, sender } => { sender - .send(mdbx_result(unsafe { ffi::mdbx_txn_abort(tx.0) })) + .send(mdbx_result!(unsafe { ffi::mdbx_txn_abort(tx.0) })) .unwrap(); } TxnManagerMessage::Commit { tx, sender } => { sender - .send(mdbx_result(unsafe { + .send(mdbx_result!(unsafe { ffi::mdbx_txn_commit_ex(tx.0, ptr::null_mut()) })) .unwrap(); @@ -547,7 +542,7 @@ where }, Err(_) => return, } - }); + } }); env.txn_manager = Some(tx); } @@ -707,7 +702,7 @@ mod test { let txn = env.begin_rw_txn().unwrap(); assert!(txn.open_db(Some("testdb")).is_err()); assert!(txn - .create_db(Some("testdb"), DatabaseFlags::empty()) + .create_db(Some("testdb"), ffi::MDBX_db_flags_t::empty()) .is_ok()); assert!(txn.open_db(Some("testdb")).is_ok()) } @@ -718,7 +713,8 @@ mod test { let env = Environment::new().set_max_dbs(10).open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - txn.create_db(Some("db"), DatabaseFlags::empty()).unwrap(); + txn.create_db(Some("db"), ffi::MDBX_db_flags_t::empty()) + .unwrap(); txn.open_db(Some("db")).unwrap(); } @@ -761,7 +757,7 @@ mod test { &tx.open_db(None).unwrap(), &value, &value, - WriteFlags::default(), + ffi::MDBX_put_flags_t::default(), ) .expect("tx.put"); tx.commit().expect("tx.commit"); @@ -813,7 +809,7 @@ mod test { &tx.open_db(None).unwrap(), &value, &value, - WriteFlags::default(), + ffi::MDBX_put_flags_t::default(), ) .expect("tx.put"); tx.commit().expect("tx.commit"); diff --git a/src/error.rs b/src/error.rs index ab69dfd..4a49a01 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,5 @@ -use libc::c_int; +use ffi::MDBX_error_t; use std::{ffi::CStr, fmt, result, str}; - /// An MDBX error kind. #[derive(Debug)] pub enum Error { @@ -32,74 +31,74 @@ pub enum Error { Access, TooLarge, DecodeError(Box), - Other(c_int), + Other(MDBX_error_t), } impl Error { /// Converts a raw error code to an [Error]. - pub fn from_err_code(err_code: c_int) -> Error { + pub fn from_err_code(err_code: MDBX_error_t) -> Error { match err_code { - ffi::MDBX_KEYEXIST => Error::KeyExist, - ffi::MDBX_NOTFOUND => Error::NotFound, - ffi::MDBX_PAGE_NOTFOUND => Error::PageNotFound, - ffi::MDBX_CORRUPTED => Error::Corrupted, - ffi::MDBX_PANIC => Error::Panic, - ffi::MDBX_VERSION_MISMATCH => Error::VersionMismatch, - ffi::MDBX_INVALID => Error::Invalid, - ffi::MDBX_MAP_FULL => Error::MapFull, - ffi::MDBX_DBS_FULL => Error::DbsFull, - ffi::MDBX_READERS_FULL => Error::ReadersFull, - ffi::MDBX_TXN_FULL => Error::TxnFull, - ffi::MDBX_CURSOR_FULL => Error::CursorFull, - ffi::MDBX_PAGE_FULL => Error::PageFull, - ffi::MDBX_UNABLE_EXTEND_MAPSIZE => Error::UnableExtendMapsize, - ffi::MDBX_INCOMPATIBLE => Error::Incompatible, - ffi::MDBX_BAD_RSLOT => Error::BadRslot, - ffi::MDBX_BAD_TXN => Error::BadTxn, - ffi::MDBX_BAD_VALSIZE => Error::BadValSize, - ffi::MDBX_BAD_DBI => Error::BadDbi, - ffi::MDBX_PROBLEM => Error::Problem, - ffi::MDBX_BUSY => Error::Busy, - ffi::MDBX_EMULTIVAL => Error::Multival, - ffi::MDBX_WANNA_RECOVERY => Error::WannaRecovery, - ffi::MDBX_EKEYMISMATCH => Error::KeyMismatch, - ffi::MDBX_EINVAL => Error::InvalidValue, - ffi::MDBX_EACCESS => Error::Access, - ffi::MDBX_TOO_LARGE => Error::TooLarge, + MDBX_error_t::MDBX_KEYEXIST => Error::KeyExist, + MDBX_error_t::MDBX_NOTFOUND => Error::NotFound, + MDBX_error_t::MDBX_PAGE_NOTFOUND => Error::PageNotFound, + MDBX_error_t::MDBX_CORRUPTED => Error::Corrupted, + MDBX_error_t::MDBX_PANIC => Error::Panic, + MDBX_error_t::MDBX_VERSION_MISMATCH => Error::VersionMismatch, + MDBX_error_t::MDBX_INVALID => Error::Invalid, + MDBX_error_t::MDBX_MAP_FULL => Error::MapFull, + MDBX_error_t::MDBX_DBS_FULL => Error::DbsFull, + MDBX_error_t::MDBX_READERS_FULL => Error::ReadersFull, + MDBX_error_t::MDBX_TXN_FULL => Error::TxnFull, + MDBX_error_t::MDBX_CURSOR_FULL => Error::CursorFull, + MDBX_error_t::MDBX_PAGE_FULL => Error::PageFull, + MDBX_error_t::MDBX_UNABLE_EXTEND_MAPSIZE => Error::UnableExtendMapsize, + MDBX_error_t::MDBX_INCOMPATIBLE => Error::Incompatible, + MDBX_error_t::MDBX_BAD_RSLOT => Error::BadRslot, + MDBX_error_t::MDBX_BAD_TXN => Error::BadTxn, + MDBX_error_t::MDBX_BAD_VALSIZE => Error::BadValSize, + MDBX_error_t::MDBX_BAD_DBI => Error::BadDbi, + MDBX_error_t::MDBX_PROBLEM => Error::Problem, + MDBX_error_t::MDBX_BUSY => Error::Busy, + MDBX_error_t::MDBX_EMULTIVAL => Error::Multival, + MDBX_error_t::MDBX_WANNA_RECOVERY => Error::WannaRecovery, + MDBX_error_t::MDBX_EKEYMISMATCH => Error::KeyMismatch, + MDBX_error_t::MDBX_EINVAL => Error::InvalidValue, + MDBX_error_t::MDBX_EACCESS => Error::Access, + MDBX_error_t::MDBX_TOO_LARGE => Error::TooLarge, other => Error::Other(other), } } /// Converts an [Error] to the raw error code. - fn to_err_code(&self) -> c_int { + fn to_err_code(&self) -> MDBX_error_t { match self { - Error::KeyExist => ffi::MDBX_KEYEXIST, - Error::NotFound => ffi::MDBX_NOTFOUND, - Error::PageNotFound => ffi::MDBX_PAGE_NOTFOUND, - Error::Corrupted => ffi::MDBX_CORRUPTED, - Error::Panic => ffi::MDBX_PANIC, - Error::VersionMismatch => ffi::MDBX_VERSION_MISMATCH, - Error::Invalid => ffi::MDBX_INVALID, - Error::MapFull => ffi::MDBX_MAP_FULL, - Error::DbsFull => ffi::MDBX_DBS_FULL, - Error::ReadersFull => ffi::MDBX_READERS_FULL, - Error::TxnFull => ffi::MDBX_TXN_FULL, - Error::CursorFull => ffi::MDBX_CURSOR_FULL, - Error::PageFull => ffi::MDBX_PAGE_FULL, - Error::UnableExtendMapsize => ffi::MDBX_UNABLE_EXTEND_MAPSIZE, - Error::Incompatible => ffi::MDBX_INCOMPATIBLE, - Error::BadRslot => ffi::MDBX_BAD_RSLOT, - Error::BadTxn => ffi::MDBX_BAD_TXN, - Error::BadValSize => ffi::MDBX_BAD_VALSIZE, - Error::BadDbi => ffi::MDBX_BAD_DBI, - Error::Problem => ffi::MDBX_PROBLEM, - Error::Busy => ffi::MDBX_BUSY, - Error::Multival => ffi::MDBX_EMULTIVAL, - Error::WannaRecovery => ffi::MDBX_WANNA_RECOVERY, - Error::KeyMismatch => ffi::MDBX_EKEYMISMATCH, - Error::InvalidValue => ffi::MDBX_EINVAL, - Error::Access => ffi::MDBX_EACCESS, - Error::TooLarge => ffi::MDBX_TOO_LARGE, + Error::KeyExist => MDBX_error_t::MDBX_KEYEXIST, + Error::NotFound => MDBX_error_t::MDBX_NOTFOUND, + Error::PageNotFound => MDBX_error_t::MDBX_PAGE_NOTFOUND, + Error::Corrupted => MDBX_error_t::MDBX_CORRUPTED, + Error::Panic => MDBX_error_t::MDBX_PANIC, + Error::VersionMismatch => MDBX_error_t::MDBX_VERSION_MISMATCH, + Error::Invalid => MDBX_error_t::MDBX_INVALID, + Error::MapFull => MDBX_error_t::MDBX_MAP_FULL, + Error::DbsFull => MDBX_error_t::MDBX_DBS_FULL, + Error::ReadersFull => MDBX_error_t::MDBX_READERS_FULL, + Error::TxnFull => MDBX_error_t::MDBX_TXN_FULL, + Error::CursorFull => MDBX_error_t::MDBX_CURSOR_FULL, + Error::PageFull => MDBX_error_t::MDBX_PAGE_FULL, + Error::UnableExtendMapsize => MDBX_error_t::MDBX_UNABLE_EXTEND_MAPSIZE, + Error::Incompatible => MDBX_error_t::MDBX_INCOMPATIBLE, + Error::BadRslot => MDBX_error_t::MDBX_BAD_RSLOT, + Error::BadTxn => MDBX_error_t::MDBX_BAD_TXN, + Error::BadValSize => MDBX_error_t::MDBX_BAD_VALSIZE, + Error::BadDbi => MDBX_error_t::MDBX_BAD_DBI, + Error::Problem => MDBX_error_t::MDBX_PROBLEM, + Error::Busy => MDBX_error_t::MDBX_BUSY, + Error::Multival => MDBX_error_t::MDBX_EMULTIVAL, + Error::WannaRecovery => MDBX_error_t::MDBX_WANNA_RECOVERY, + Error::KeyMismatch => MDBX_error_t::MDBX_EKEYMISMATCH, + Error::InvalidValue => MDBX_error_t::MDBX_EINVAL, + Error::Access => MDBX_error_t::MDBX_EACCESS, + Error::TooLarge => MDBX_error_t::MDBX_TOO_LARGE, Error::Other(err_code) => *err_code, _ => unreachable!(), } @@ -112,7 +111,7 @@ impl fmt::Display for Error { Error::DecodeError(reason) => write!(fmt, "{}", reason), other => { write!(fmt, "{}", unsafe { - let err = ffi::mdbx_strerror(other.to_err_code()); + let err = ffi::mdbx_strerror(other.to_err_code().0); str::from_utf8_unchecked(CStr::from_ptr(err).to_bytes()) }) } @@ -125,14 +124,21 @@ impl std::error::Error for Error {} /// An MDBX result. pub type Result = result::Result; -pub fn mdbx_result(err_code: c_int) -> Result { +pub fn _mdbx_result(err_code: MDBX_error_t) -> Result { match err_code { - ffi::MDBX_SUCCESS => Ok(false), - ffi::MDBX_RESULT_TRUE => Ok(true), + MDBX_error_t::MDBX_SUCCESS => Ok(false), + MDBX_error_t::MDBX_RESULT_TRUE => Ok(true), other => Err(Error::from_err_code(other)), } } +#[macro_export] +macro_rules! mdbx_result { + ($expr:expr) => { + crate::error::_mdbx_result(ffi::MDBX_error_t($expr)) + }; +} + #[macro_export] macro_rules! mdbx_try_optional { ($expr:expr) => {{ @@ -152,7 +158,7 @@ mod test { fn test_description() { assert_eq!("Permission denied", Error::from_err_code(13).to_string()); assert_eq!( - "MDBX_INVALID: File is not an MDBX file", + "MDBX_error_t::MDBX_INVALID: File is not an MDBX file", Error::Invalid.to_string() ); } diff --git a/src/flags.rs b/src/flags.rs index 20d288c..2fb9cfc 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -1,6 +1,4 @@ -use bitflags::bitflags; -use ffi::*; -use libc::c_uint; +use ffi::MDBX_env_flags_t; /// MDBX sync mode #[derive(Clone, Copy, Debug)] @@ -110,57 +108,58 @@ pub struct EnvironmentFlags { } impl EnvironmentFlags { - pub(crate) fn make_flags(&self) -> ffi::MDBX_env_flags_t { - let mut flags = 0; + pub(crate) fn make_flags(&self) -> MDBX_env_flags_t { + let mut flags = MDBX_env_flags_t::MDBX_ENV_DEFAULTS; if self.no_sub_dir { - flags |= ffi::MDBX_NOSUBDIR; + flags |= MDBX_env_flags_t::MDBX_NOSUBDIR; } if self.exclusive { - flags |= ffi::MDBX_EXCLUSIVE; + flags |= MDBX_env_flags_t::MDBX_EXCLUSIVE; } if self.accede { - flags |= ffi::MDBX_ACCEDE; + flags |= MDBX_env_flags_t::MDBX_ACCEDE; } match self.mode { Mode::ReadOnly => { - flags |= ffi::MDBX_RDONLY; + flags |= MDBX_env_flags_t::MDBX_RDONLY; } Mode::ReadWrite { sync_mode } => { flags |= match sync_mode { - SyncMode::Durable => ffi::MDBX_SYNC_DURABLE, - SyncMode::NoMetaSync => ffi::MDBX_NOMETASYNC, - SyncMode::SafeNoSync => ffi::MDBX_SAFE_NOSYNC, - SyncMode::UtterlyNoSync => ffi::MDBX_UTTERLY_NOSYNC, + SyncMode::Durable => MDBX_env_flags_t::MDBX_SYNC_DURABLE, + SyncMode::NoMetaSync => MDBX_env_flags_t::MDBX_NOMETASYNC, + SyncMode::SafeNoSync => MDBX_env_flags_t::MDBX_SAFE_NOSYNC, + SyncMode::UtterlyNoSync => MDBX_env_flags_t::MDBX_UTTERLY_NOSYNC, }; } } if self.no_rdahead { - flags |= ffi::MDBX_NORDAHEAD; + flags |= MDBX_env_flags_t::MDBX_NORDAHEAD; } if self.no_meminit { - flags |= ffi::MDBX_NOMEMINIT; + flags |= MDBX_env_flags_t::MDBX_NOMEMINIT; } if self.coalesce { - flags |= ffi::MDBX_COALESCE; + flags |= MDBX_env_flags_t::MDBX_COALESCE; } if self.liforeclaim { - flags |= ffi::MDBX_LIFORECLAIM; + flags |= MDBX_env_flags_t::MDBX_LIFORECLAIM; } - flags |= ffi::MDBX_NOTLS; + flags |= MDBX_env_flags_t::MDBX_NOTLS; flags } } +/* bitflags! { #[doc="Database options."] #[derive(Default)] @@ -175,19 +174,19 @@ bitflags! { const ACCEDE = MDBX_DB_ACCEDE; } } - bitflags! { #[doc="Write options."] #[derive(Default)] pub struct WriteFlags: c_uint { - const UPSERT = MDBX_UPSERT; - const NO_OVERWRITE = MDBX_NOOVERWRITE; - const NO_DUP_DATA = MDBX_NODUPDATA; - const CURRENT = MDBX_CURRENT; - const ALLDUPS = MDBX_ALLDUPS; - const RESERVE = MDBX_RESERVE; - const APPEND = MDBX_APPEND; - const APPEND_DUP = MDBX_APPENDDUP; - const MULTIPLE = MDBX_MULTIPLE; + const UPSERT = ffi::MDBX_put_flags_t::MDBX_UPSERT; + const NO_OVERWRITE = ffi::MDBX_put_flags_t::MDBX_NOOVERWRITE; + const NO_DUP_DATA = ffi::MDBX_put_flags_t::MDBX_NODUPDATA; + const CURRENT = ffi::MDBX_put_flags_t::MDBX_CURRENT; + const ALLDUPS = ffi::MDBX_put_flags_t::MDBX_ALLDUPS; + const RESERVE = ffi::MDBX_put_flags_t::MDBX_RESERVE; + const APPEND = ffi::MDBX_put_flags_t::MDBX_APPEND; + const APPEND_DUP = ffi::MDBX_put_flags_t::ffi::MDBX_put_flags_t::MDBX_APPENDDUP; + const MULTIPLE = ffi::MDBX_put_flags_t::MDBX_MULTIPLE; } } +*/ diff --git a/src/lib.rs b/src/lib.rs index 0e2ffe2..2cb3808 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,8 @@ pub use crate::{ transaction::{Transaction, TransactionKind, RO, RW}, }; +pub use ffi::{MDBX_db_flags_t,MDBX_env_flags_t,MDBX_error_t,MDBX_option_t}; + mod codec; mod cursor; mod database; @@ -56,9 +58,9 @@ mod test_utils { LittleEndian::write_u64(&mut value, height); let tx = env.begin_rw_txn().expect("begin_rw_txn"); let index = tx - .create_db(None, DatabaseFlags::DUP_SORT) + .create_db(None, ffi::MDBX_db_flags_t::DUP_SORT) .expect("open index db"); - tx.put(&index, &HEIGHT_KEY, &value, WriteFlags::empty()) + tx.put(&index, &HEIGHT_KEY, &value, ffi::MDBX_put_flags_t::empty()) .expect("tx.put"); tx.commit().expect("tx.commit"); } diff --git a/src/transaction.rs b/src/transaction.rs index 20df4ec..b1a35e7 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,13 +1,12 @@ use crate::{ database::Database, environment::{Environment, EnvironmentKind, NoWriteMap, TxnManagerMessage, TxnPtr}, - error::{mdbx_result, Result}, - flags::{DatabaseFlags, WriteFlags}, - Cursor, Error, Stat, TableObject, + error::Result, + mdbx_result, Cursor, Error, Stat, TableObject, }; -use ffi::{MDBX_txn_flags_t, MDBX_TXN_RDONLY, MDBX_TXN_READWRITE}; +use ffi::{MDBX_db_flags_t, MDBX_error_t, MDBX_put_flags_t, MDBX_txn_flags_t}; use indexmap::IndexSet; -use libc::{c_uint, c_void}; +use libc::c_void; use parking_lot::Mutex; use std::{ fmt, @@ -42,11 +41,11 @@ pub struct RW; impl TransactionKind for RO { const ONLY_CLEAN: bool = true; - const OPEN_FLAGS: MDBX_txn_flags_t = MDBX_TXN_RDONLY; + const OPEN_FLAGS: MDBX_txn_flags_t = MDBX_txn_flags_t::MDBX_TXN_RDONLY; } impl TransactionKind for RW { const ONLY_CLEAN: bool = false; - const OPEN_FLAGS: MDBX_txn_flags_t = MDBX_TXN_READWRITE; + const OPEN_FLAGS: MDBX_txn_flags_t = MDBX_txn_flags_t::MDBX_TXN_READWRITE; } /// An MDBX transaction. @@ -72,7 +71,7 @@ where pub(crate) fn new(env: &'env Environment) -> Result { let mut txn: *mut ffi::MDBX_txn = ptr::null_mut(); unsafe { - mdbx_result(ffi::mdbx_txn_begin_ex( + mdbx_result!(ffi::mdbx_txn_begin_ex( env.env(), ptr::null_mut(), K::OPEN_FLAGS, @@ -119,7 +118,7 @@ where /// /// This function retrieves the data associated with the given key in the /// database. If the database supports duplicate keys - /// ([DatabaseFlags::DUP_SORT]) then the first data item for the key will be + /// ([MDBX_db_flags_t::DUP_SORT]) then the first data item for the key will be /// returned. Retrieval of other items requires the use of /// [Cursor]. If the item is not in the database, then /// [None] will be returned. @@ -137,9 +136,9 @@ where }; txn_execute(&self.txn, |txn| unsafe { - match ffi::mdbx_get(txn, db.dbi(), &key_val, &mut data_val) { - ffi::MDBX_SUCCESS => Key::decode_val::(txn, &data_val).map(Some), - ffi::MDBX_NOTFOUND => Ok(None), + match MDBX_error_t(ffi::mdbx_get(txn, db.dbi(), &key_val, &mut data_val)) { + MDBX_error_t::MDBX_SUCCESS => Key::decode_val::(txn, &data_val).map(Some), + MDBX_error_t::MDBX_NOTFOUND => Ok(None), err_code => Err(Error::from_err_code(err_code)), } }) @@ -161,7 +160,7 @@ where let txnlck = self.txn.lock(); let txn = *txnlck; let result = if K::ONLY_CLEAN { - mdbx_result(unsafe { ffi::mdbx_txn_commit_ex(txn, ptr::null_mut()) }) + mdbx_result!(unsafe { ffi::mdbx_txn_commit_ex(txn, ptr::null_mut()) }) } else { let (sender, rx) = sync_channel(0); self.env @@ -200,25 +199,25 @@ where /// /// The database name may not contain the null character. pub fn open_db<'txn>(&'txn self, name: Option<&str>) -> Result> { - Database::new(self, name, 0) + Database::new(self, name, MDBX_db_flags_t::MDBX_DB_DEFAULTS) } /// Gets the option flags for the given database in the transaction. - pub fn db_flags<'txn>(&'txn self, db: &Database<'txn>) -> Result { - let mut flags: c_uint = 0; + pub fn db_flags<'txn>(&'txn self, db: &Database<'txn>) -> Result { + let mut flags: libc::c_uint = 0; unsafe { - mdbx_result(txn_execute(&self.txn, |txn| { + mdbx_result!(txn_execute(&self.txn, |txn| { ffi::mdbx_dbi_flags_ex(txn, db.dbi(), &mut flags, ptr::null_mut()) }))?; } - Ok(DatabaseFlags::from_bits_truncate(flags)) + Ok(unsafe { std::mem::transmute::(flags) }) } /// Retrieves database statistics. pub fn db_stat<'txn>(&'txn self, db: &Database<'txn>) -> Result { unsafe { let mut stat = Stat::new(); - mdbx_result(txn_execute(&self.txn, |txn| { + mdbx_result!(txn_execute(&self.txn, |txn| { ffi::mdbx_dbi_stat(txn, db.dbi(), stat.mdb_stat(), size_of::()) }))?; Ok(stat) @@ -246,9 +245,9 @@ where fn open_db_with_flags<'txn>( &'txn self, name: Option<&str>, - flags: DatabaseFlags, + flags: MDBX_db_flags_t, ) -> Result> { - Database::new(self, name, flags.bits()) + Database::new(self, name, flags) } /// Opens a handle to an MDBX database, creating the database if necessary. @@ -266,9 +265,9 @@ where pub fn create_db<'txn>( &'txn self, name: Option<&str>, - flags: DatabaseFlags, + flags: MDBX_db_flags_t, ) -> Result> { - self.open_db_with_flags(name, flags | DatabaseFlags::CREATE) + self.open_db_with_flags(name, flags | MDBX_db_flags_t::MDBX_CREATE) } /// Stores an item into a database. @@ -276,13 +275,13 @@ where /// This function stores key/data pairs in the database. The default /// behavior is to enter the new key/data pair, replacing any previously /// existing key if duplicates are disallowed, or adding a duplicate data - /// item if duplicates are allowed ([DatabaseFlags::DUP_SORT]). + /// item if duplicates are allowed ([MDBX_db_flags_t::DUP_SORT]). pub fn put<'txn>( &'txn self, db: &Database<'txn>, key: impl AsRef<[u8]>, data: impl AsRef<[u8]>, - flags: WriteFlags, + flags: MDBX_put_flags_t, ) -> Result<()> { let key = key.as_ref(); let data = data.as_ref(); @@ -294,8 +293,8 @@ where iov_len: data.len(), iov_base: data.as_ptr() as *mut c_void, }; - mdbx_result(txn_execute(&self.txn, |txn| unsafe { - ffi::mdbx_put(txn, db.dbi(), &key_val, &mut data_val, flags.bits()) + mdbx_result!(txn_execute(&self.txn, |txn| unsafe { + ffi::mdbx_put(txn, db.dbi(), &key_val, &mut data_val, flags) }))?; Ok(()) @@ -309,7 +308,7 @@ where db: &Database<'txn>, key: impl AsRef<[u8]>, len: usize, - flags: WriteFlags, + flags: MDBX_put_flags_t, ) -> Result<&'txn mut [u8]> { let key = key.as_ref(); let key_val: ffi::MDBX_val = ffi::MDBX_val { @@ -321,13 +320,13 @@ where iov_base: ptr::null_mut::(), }; unsafe { - mdbx_result(txn_execute(&self.txn, |txn| { + mdbx_result!(txn_execute(&self.txn, |txn| { ffi::mdbx_put( txn, db.dbi(), &key_val, &mut data_val, - flags.bits() | ffi::MDBX_RESERVE, + flags | MDBX_put_flags_t::MDBX_RESERVE, ) }))?; Ok(slice::from_raw_parts_mut( @@ -361,7 +360,7 @@ where iov_base: data.as_ptr() as *mut c_void, }); - mdbx_result({ + mdbx_result!({ txn_execute(&self.txn, |txn| { if let Some(d) = data_val { unsafe { ffi::mdbx_del(txn, db.dbi(), &key_val, &d) } @@ -379,7 +378,7 @@ where /// Empties the given database. All items will be removed. pub fn clear_db<'txn>(&'txn self, db: &Database<'txn>) -> Result<()> { - mdbx_result(txn_execute(&self.txn, |txn| unsafe { + mdbx_result!(txn_execute(&self.txn, |txn| unsafe { ffi::mdbx_drop(txn, db.dbi(), false) }))?; @@ -391,7 +390,7 @@ where /// # Safety /// Caller must close ALL other [Database] and [Cursor] instances pointing to the same dbi BEFORE calling this function. pub unsafe fn drop_db<'txn>(&'txn self, db: Database<'txn>) -> Result<()> { - mdbx_result(txn_execute(&self.txn, |txn| { + mdbx_result!(txn_execute(&self.txn, |txn| { ffi::mdbx_drop(txn, db.dbi(), true) }))?; @@ -408,7 +407,7 @@ where /// # Safety /// Caller must close ALL other [Database] and [Cursor] instances pointing to the same dbi BEFORE calling this function. pub unsafe fn close_db(&self, db: Database<'_>) -> Result<()> { - mdbx_result(ffi::mdbx_dbi_close(self.env.env(), db.dbi()))?; + mdbx_result!(ffi::mdbx_dbi_close(self.env.env(), db.dbi()))?; Ok(()) } @@ -511,9 +510,12 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + txn.put(&db, b"key1", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); let txn = env.begin_rw_txn().unwrap(); @@ -533,16 +535,25 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + let db = txn.create_db(None, MDBX_db_flags_t::DUP_SORT).unwrap(); + txn.put(&db, b"key1", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); let txn = env.begin_rw_txn().unwrap(); @@ -582,14 +593,15 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.create_db(None, Default::default()).unwrap(); - txn.put(&db, b"", b"hello", WriteFlags::empty()).unwrap(); + txn.put(&db, b"", b"hello", MDBX_put_flags_t::empty()) + .unwrap(); assert_eq!(txn.get(&db, b"").unwrap(), Some(*b"hello")); txn.commit().unwrap(); let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); assert_eq!(txn.get(&db, b"").unwrap(), Some(*b"hello")); - txn.put(&db, b"", b"", WriteFlags::empty()).unwrap(); + txn.put(&db, b"", b"", MDBX_put_flags_t::empty()).unwrap(); assert_eq!(txn.get(&db, b"").unwrap(), Some(*b"")); } @@ -601,7 +613,9 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); { - let mut writer = txn.reserve(&db, b"key1", 4, WriteFlags::empty()).unwrap(); + let mut writer = txn + .reserve(&db, b"key1", 4, MDBX_put_flags_t::empty()) + .unwrap(); writer.write_all(b"val1").unwrap(); } txn.commit().unwrap(); @@ -625,7 +639,7 @@ mod test { &txn.open_db(None).unwrap(), b"key1", b"val1", - WriteFlags::empty(), + MDBX_put_flags_t::empty(), ) .unwrap(); @@ -633,7 +647,7 @@ mod test { let nested = txn.begin_nested_txn().unwrap(); let db = nested.open_db(None).unwrap(); nested - .put(&db, b"key2", b"val2", WriteFlags::empty()) + .put(&db, b"key2", b"val2", MDBX_put_flags_t::empty()) .unwrap(); assert_eq!(nested.get(&db, b"key1").unwrap(), Some(*b"val1")); assert_eq!(nested.get(&db, b"key2").unwrap(), Some(*b"val2")); @@ -655,7 +669,7 @@ mod test { &txn.open_db(None).unwrap(), b"key", b"val", - WriteFlags::empty(), + MDBX_put_flags_t::empty(), ) .unwrap(); assert!(!txn.commit().unwrap()); @@ -683,14 +697,15 @@ mod test { { let txn = env.begin_rw_txn().unwrap(); txn.put( - &txn.create_db(Some("test"), DatabaseFlags::empty()).unwrap(), + &txn.create_db(Some("test"), MDBX_db_flags_t::empty()) + .unwrap(), b"key", b"val", - WriteFlags::empty(), + MDBX_put_flags_t::empty(), ) .unwrap(); // Workaround for MDBX dbi drop issue - txn.create_db(Some("canary"), DatabaseFlags::empty()) + txn.create_db(Some("canary"), MDBX_db_flags_t::empty()) .unwrap(); assert!(!txn.commit().unwrap()); } @@ -754,7 +769,7 @@ mod test { let db = txn.open_db(None).unwrap(); println!("wait2"); barrier.wait(); - txn.put(&db, key, val, WriteFlags::empty()).unwrap(); + txn.put(&db, key, val, MDBX_put_flags_t::empty()).unwrap(); txn.commit().unwrap(); println!("wait1"); @@ -784,7 +799,7 @@ mod test { &db, &format!("{}{}", key, i), &format!("{}{}", val, i), - WriteFlags::empty(), + MDBX_put_flags_t::empty(), ) .unwrap(); txn.commit().is_ok() @@ -811,10 +826,13 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - let db = txn.create_db(None, DatabaseFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + let db = txn.create_db(None, MDBX_db_flags_t::empty()).unwrap(); + txn.put(&db, b"key1", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); { @@ -839,9 +857,12 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); - txn.put(&db, b"key4", b"val4", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key5", b"val5", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key6", b"val6", WriteFlags::empty()).unwrap(); + txn.put(&db, b"key4", b"val4", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key5", b"val5", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key6", b"val6", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); { @@ -858,16 +879,25 @@ mod test { let env = Environment::new().open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap(); - txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key2", b"val3", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap(); + let db = txn.create_db(None, MDBX_db_flags_t::DUP_SORT).unwrap(); + txn.put(&db, b"key1", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key1", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key2", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key3", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); { @@ -890,9 +920,12 @@ mod test { let txn = env.begin_rw_txn().unwrap(); let db = txn.open_db(None).unwrap(); - txn.put(&db, b"key4", b"val1", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key4", b"val2", WriteFlags::empty()).unwrap(); - txn.put(&db, b"key4", b"val3", WriteFlags::empty()).unwrap(); + txn.put(&db, b"key4", b"val1", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key4", b"val2", MDBX_put_flags_t::empty()) + .unwrap(); + txn.put(&db, b"key4", b"val3", MDBX_put_flags_t::empty()) + .unwrap(); txn.commit().unwrap(); { diff --git a/update.libmdbx.sh b/update.libmdbx.sh new file mode 100755 index 0000000..cdf41cf --- /dev/null +++ b/update.libmdbx.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +DIR=$(cd "$(dirname "$0")"; pwd) +set -ex +cd $DIR/.. + +if [ ! -d "libmdbx" ] ; then +git clone git@github.com:erthink/libmdbx.git +cd libmdbx +else +cd libmdbx +git pull +fi + +make dist + +libmdbx=$DIR/mdbx-sys/libmdbx +rm -rf $libmdbx +cp -R dist $libmdbx