diff --git a/CLAUDE.md b/CLAUDE.md index 610c964..2e010d4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,8 @@ # mdbx Crate Notes +Include updates to the notes here if you discover important details while +working, or if the notes become outdated. + ## Crate Overview Rust bindings for libmdbx (MDBX database). Crate name: `signet-libmdbx`. diff --git a/Cargo.toml b/Cargo.toml index 0fee6b9..85b9f0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "signet-libmdbx" description = "Idiomatic and safe MDBX wrapper" -version = "0.3.1" +version = "0.4.0" edition = "2024" rust-version = "1.92" license = "MIT OR Apache-2.0" diff --git a/benches/cursor.rs b/benches/cursor.rs index aa60c5e..9b52387 100644 --- a/benches/cursor.rs +++ b/benches/cursor.rs @@ -12,6 +12,9 @@ fn bench_get_seq_iter(c: &mut Criterion) { let (_dir, env) = setup_bench_db(n); let txn = env.begin_ro_txn().unwrap(); let db = txn.open_db(None).unwrap(); + // Note: setup_bench_db creates a named database which adds metadata to the + // main database, so actual item count is n + 1 + let actual_items = n + 1; c.bench_function("bench_get_seq_iter", |b| { b.iter(|| { let mut cursor = txn.cursor(db).unwrap(); @@ -42,7 +45,8 @@ fn bench_get_seq_iter(c: &mut Criterion) { iterate(&mut cursor).unwrap(); black_box(i); - assert_eq!(count, n); + // Both loops iterate all items since iter() repositions exhausted cursors + assert_eq!(count, actual_items * 2); }) }); } @@ -53,6 +57,9 @@ fn bench_get_seq_cursor(c: &mut Criterion) { let (_dir, env) = setup_bench_db(n); let txn = env.begin_ro_txn().unwrap(); let db = txn.open_db(None).unwrap(); + // Note: setup_bench_db creates a named database which adds metadata to the + // main database, so actual item count is n + 1 + let actual_items = n + 1; c.bench_function("bench_get_seq_cursor", |b| { b.iter(|| { let (i, count) = txn @@ -63,7 +70,7 @@ fn bench_get_seq_cursor(c: &mut Criterion) { .fold((0, 0), |(i, count), (key, val)| (i + *key + *val, count + 1)); black_box(i); - assert_eq!(count, n); + assert_eq!(count, actual_items); }) }); } @@ -80,6 +87,10 @@ fn bench_get_seq_raw(c: &mut Criterion) { let mut data = MDBX_val { iov_len: 0, iov_base: ptr::null_mut() }; let mut cursor: *mut MDBX_cursor = ptr::null_mut(); + // Note: setup_bench_db creates a named database which adds metadata to the + // main database, so actual item count is n + 1 + let actual_items = n + 1; + c.bench_function("bench_get_seq_raw", |b| { b.iter(|| unsafe { txn.txn_execute(|txn| { @@ -93,7 +104,7 @@ fn bench_get_seq_raw(c: &mut Criterion) { } black_box(i); - assert_eq!(count, n); + assert_eq!(count, actual_items); mdbx_cursor_close(cursor); }) .unwrap(); diff --git a/mdbx-sys/Cargo.toml b/mdbx-sys/Cargo.toml index 5e3c853..d739dcc 100644 --- a/mdbx-sys/Cargo.toml +++ b/mdbx-sys/Cargo.toml @@ -1,17 +1,12 @@ [package] name = "signet-mdbx-sys" description = "Raw bindings for libmdbx" -version = "0.0.1" +version = "0.1.0" edition = "2024" rust-version = "1.92" license = "Apache-2.0" homepage = "https://github.com/init4tech/signet-mdbx" repository = "https://github.com/init4tech/signet-mdbx" -[features] -default = [] -bindgen = ["dep:bindgen"] - [build-dependencies] cc = "1.2.15" -bindgen = { version = "0.72", default-features = false, optional = true } diff --git a/mdbx-sys/Dockerfile.bindgen b/mdbx-sys/Dockerfile.bindgen new file mode 100644 index 0000000..f1e2736 --- /dev/null +++ b/mdbx-sys/Dockerfile.bindgen @@ -0,0 +1,6 @@ +FROM rust:latest +RUN apt-get update && apt-get install -y libclang-dev && rm -rf /var/lib/apt/lists/* +RUN rustup component add rustfmt +RUN cargo install bindgen-cli +WORKDIR /work +ENTRYPOINT ["bindgen"] diff --git a/mdbx-sys/README.md b/mdbx-sys/README.md new file mode 100644 index 0000000..97096e5 --- /dev/null +++ b/mdbx-sys/README.md @@ -0,0 +1,67 @@ +# signet-mdbx-sys + +Raw FFI bindings for [libmdbx]. + +## Bindings + +Platform-specific bindings are pre-generated and committed: + +- `src/bindings_macos.rs` - macOS and other Unix-like systems +- `src/bindings_linux.rs` - Linux +- `src/bindings_windows.rs` - Windows + +### Regenerating Bindings + +When updating libmdbx, regenerate bindings on each target platform. + +#### Linux (via Docker) + +Generate bindings: + +```bash +# First build the Docker image +docker build -t mdbx-bindgen -f Dockerfile.bindgen . + +# Then run bindgen inside the container +docker run --rm -v "$(pwd)":/work mdbx-bindgen \ + libmdbx/mdbx.h \ + --allowlist-var "^(MDBX|mdbx)_.*" \ + --allowlist-type "^(MDBX|mdbx)_.*" \ + --allowlist-function "^(MDBX|mdbx)_.*" \ + --no-layout-tests \ + --no-doc-comments \ + --no-prepend-enum-name \ + --merge-extern-blocks \ + -o src/bindings_linux.rs +``` + +#### macOS / Windows / Linux (locally) + +Install bindgen-cli and run directly: + +```bash +# Install bindgen-cli if not already installed +cargo install bindgen-cli + +# Generate bindings for your platform +bindgen libmdbx/mdbx.h \ + --allowlist-var "^(MDBX|mdbx)_.*" \ + --allowlist-type "^(MDBX|mdbx)_.*" \ + --allowlist-function "^(MDBX|mdbx)_.*" \ + --no-layout-tests \ + --no-doc-comments \ + --no-prepend-enum-name \ + --merge-extern-blocks \ + -o src/bindings_macos.rs + # or src/bindings_windows.rs + # or src/bindings_linux.rs +``` + +Requires libclang. On macOS: + +```bash +brew install llvm +export LIBCLANG_PATH=$(brew --prefix llvm)/lib +``` + +[libmdbx]: https://github.com/erthink/libmdbx diff --git a/mdbx-sys/build.rs b/mdbx-sys/build.rs index 79cf4c7..6d271b4 100644 --- a/mdbx-sys/build.rs +++ b/mdbx-sys/build.rs @@ -1,31 +1,11 @@ use std::{env, path::PathBuf}; -#[cfg(feature = "bindgen")] -use std::path::Path; - fn main() { let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let mdbx = manifest_dir.join("libmdbx"); println!("cargo:rerun-if-changed={}", mdbx.display()); - // Binding regeneration requires both the `bindgen` feature AND the - // `MDBX_REGENERATE_BINDINGS` env var. This prevents accidental regeneration - // when running `cargo build --all-features` on the workspace. - // - // To regenerate bindings intentionally: - // MDBX_REGENERATE_BINDINGS=1 cargo build -p signet-mdbx-sys --features bindgen - #[cfg(feature = "bindgen")] - if env::var("MDBX_REGENERATE_BINDINGS").is_ok() { - let bindings = PathBuf::from(env::var("OUT_DIR").unwrap()).join("bindings.rs"); - generate_bindings(&mdbx, &bindings); - - // Also write to src/bindings.rs for easy commit - let src_bindings = manifest_dir.join("src").join("bindings.rs"); - std::fs::copy(&bindings, &src_bindings).expect("Failed to copy bindings to src/"); - println!("cargo:warning=Regenerated bindings. Don't forget to commit src/bindings.rs"); - } - let mut cc = cc::Build::new(); cc.flag_if_supported("-Wno-unused-parameter").flag_if_supported("-Wuninitialized"); @@ -36,97 +16,18 @@ fn main() { let flags = format!("{:?}", cc.get_compiler().cflags_env()); cc.define("MDBX_BUILD_FLAGS", flags.as_str()).define("MDBX_TXN_CHECKOWNER", "0"); - // Enable debugging on debug builds #[cfg(debug_assertions)] cc.define("MDBX_DEBUG", "1").define("MDBX_ENABLE_PROFGC", "1"); - // Disables debug logging on optimized builds #[cfg(not(debug_assertions))] cc.define("MDBX_DEBUG", "0").define("NDEBUG", None); - // Propagate `-C target-cpu=native` - let rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(); + let rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap_or_default(); if rustflags.contains("target-cpu=native") - && env::var("CARGO_CFG_TARGET_ENV").unwrap() != "msvc" + && env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default() != "msvc" { cc.flag("-march=native"); } cc.file(mdbx.join("mdbx.c")).compile("libmdbx.a"); } - -#[cfg(feature = "bindgen")] -fn generate_bindings(mdbx: &Path, out_file: &Path) { - use bindgen::{ - Formatter, - callbacks::{IntKind, ParseCallbacks}, - }; - - #[derive(Debug)] - struct Callbacks; - - impl ParseCallbacks for Callbacks { - fn int_macro(&self, name: &str, _value: i64) -> Option { - match name { - "MDBX_SUCCESS" - | "MDBX_KEYEXIST" - | "MDBX_NOTFOUND" - | "MDBX_PAGE_NOTFOUND" - | "MDBX_CORRUPTED" - | "MDBX_PANIC" - | "MDBX_VERSION_MISMATCH" - | "MDBX_INVALID" - | "MDBX_MAP_FULL" - | "MDBX_DBS_FULL" - | "MDBX_READERS_FULL" - | "MDBX_TLS_FULL" - | "MDBX_TXN_FULL" - | "MDBX_CURSOR_FULL" - | "MDBX_PAGE_FULL" - | "MDBX_MAP_RESIZED" - | "MDBX_INCOMPATIBLE" - | "MDBX_BAD_RSLOT" - | "MDBX_BAD_TXN" - | "MDBX_BAD_VALSIZE" - | "MDBX_BAD_DBI" - | "MDBX_LOG_DONTCHANGE" - | "MDBX_DBG_DONTCHANGE" - | "MDBX_RESULT_TRUE" - | "MDBX_UNABLE_EXTEND_MAPSIZE" - | "MDBX_PROBLEM" - | "MDBX_LAST_LMDB_ERRCODE" - | "MDBX_BUSY" - | "MDBX_EMULTIVAL" - | "MDBX_EBADSIGN" - | "MDBX_WANNA_RECOVERY" - | "MDBX_EKEYMISMATCH" - | "MDBX_TOO_LARGE" - | "MDBX_THREAD_MISMATCH" - | "MDBX_TXN_OVERLAPPING" - | "MDBX_LAST_ERRCODE" => Some(IntKind::Int), - _ => Some(IntKind::UInt), - } - } - } - - let bindings = bindgen::Builder::default() - .header(mdbx.join("mdbx.h").to_string_lossy()) - .allowlist_var("^(MDBX|mdbx)_.*") - .allowlist_type("^(MDBX|mdbx)_.*") - .allowlist_function("^(MDBX|mdbx)_.*") - .size_t_is_usize(true) - .merge_extern_blocks(true) - .parse_callbacks(Box::new(Callbacks)) - .layout_tests(false) - .prepend_enum_name(false) - .generate_comments(false) - .formatter(Formatter::Rustfmt) - .generate() - .expect( - "Unable to generate bindings. Ensure LIBCLANG_PATH is set.\n\ - On macOS: export LIBCLANG_PATH=$(brew --prefix llvm)/lib\n\ - export DYLD_FALLBACK_LIBRARY_PATH=$(brew --prefix llvm)/lib\n\ - On Linux: apt-get install libclang-dev", - ); - bindings.write_to_file(out_file).expect("Couldn't write bindings!"); -} diff --git a/mdbx-sys/src/bindings_linux.rs b/mdbx-sys/src/bindings_linux.rs new file mode 100644 index 0000000..8f601fe --- /dev/null +++ b/mdbx-sys/src/bindings_linux.rs @@ -0,0 +1,1325 @@ +/* automatically generated by rust-bindgen 0.72.1 */ + +#[doc = r" If Bindgen could only determine the size and alignment of a"] +#[doc = r" type, it is represented like this."] +#[derive(PartialEq, Copy, Clone, Debug, Hash)] +#[repr(C)] +pub struct __BindgenOpaqueArray(pub [T; N]); +impl Default for __BindgenOpaqueArray { + fn default() -> Self { + Self([::default(); N]) + } +} +pub const MDBX_VERSION_MAJOR: u32 = 0; +pub const MDBX_VERSION_MINOR: u32 = 13; +pub const MDBX_LOCKNAME: &[u8; 10] = b"/mdbx.lck\0"; +pub const MDBX_DATANAME: &[u8; 10] = b"/mdbx.dat\0"; +pub const MDBX_LOCK_SUFFIX: &[u8; 5] = b"-lck\0"; +pub type va_list = __BindgenOpaqueArray; +pub type __mode_t = ::std::os::raw::c_uint; +pub type __pid_t = ::std::os::raw::c_int; +pub type pid_t = __pid_t; +pub type pthread_t = ::std::os::raw::c_ulong; +pub type mode_t = __mode_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct iovec { + pub iov_base: *mut ::std::os::raw::c_void, + pub iov_len: usize, +} +pub type mdbx_filehandle_t = ::std::os::raw::c_int; +pub type mdbx_pid_t = pid_t; +pub type mdbx_tid_t = pthread_t; +pub type mdbx_mode_t = mode_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_version_info { + pub major: u16, + pub minor: u16, + pub patch: u16, + pub tweak: u16, + pub semver_prerelease: *const ::std::os::raw::c_char, + pub git: MDBX_version_info__bindgen_ty_1, + pub sourcery: *const ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_version_info__bindgen_ty_1 { + pub datetime: *const ::std::os::raw::c_char, + pub tree: *const ::std::os::raw::c_char, + pub commit: *const ::std::os::raw::c_char, + pub describe: *const ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_build_info { + pub datetime: *const ::std::os::raw::c_char, + pub target: *const ::std::os::raw::c_char, + pub options: *const ::std::os::raw::c_char, + pub compiler: *const ::std::os::raw::c_char, + pub flags: *const ::std::os::raw::c_char, + pub metadata: *const ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_env { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_txn { + _unused: [u8; 0], +} +pub type MDBX_dbi = u32; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_cursor { + _unused: [u8; 0], +} +pub type MDBX_val = iovec; +pub const MDBX_MAX_DBI: MDBX_constants = 32765; +pub const MDBX_MAXDATASIZE: MDBX_constants = 2147418112; +pub const MDBX_MIN_PAGESIZE: MDBX_constants = 256; +pub const MDBX_MAX_PAGESIZE: MDBX_constants = 65536; +pub type MDBX_constants = ::std::os::raw::c_uint; +pub const MDBX_LOG_FATAL: MDBX_log_level = 0; +pub const MDBX_LOG_ERROR: MDBX_log_level = 1; +pub const MDBX_LOG_WARN: MDBX_log_level = 2; +pub const MDBX_LOG_NOTICE: MDBX_log_level = 3; +pub const MDBX_LOG_VERBOSE: MDBX_log_level = 4; +pub const MDBX_LOG_DEBUG: MDBX_log_level = 5; +pub const MDBX_LOG_TRACE: MDBX_log_level = 6; +pub const MDBX_LOG_EXTRA: MDBX_log_level = 7; +pub const MDBX_LOG_DONTCHANGE: MDBX_log_level = -1; +pub type MDBX_log_level = ::std::os::raw::c_int; +pub use self::MDBX_log_level as MDBX_log_level_t; +pub const MDBX_DBG_NONE: MDBX_debug_flags = 0; +pub const MDBX_DBG_ASSERT: MDBX_debug_flags = 1; +pub const MDBX_DBG_AUDIT: MDBX_debug_flags = 2; +pub const MDBX_DBG_JITTER: MDBX_debug_flags = 4; +pub const MDBX_DBG_DUMP: MDBX_debug_flags = 8; +pub const MDBX_DBG_LEGACY_MULTIOPEN: MDBX_debug_flags = 16; +pub const MDBX_DBG_LEGACY_OVERLAP: MDBX_debug_flags = 32; +pub const MDBX_DBG_DONT_UPGRADE: MDBX_debug_flags = 64; +pub const MDBX_DBG_DONTCHANGE: MDBX_debug_flags = -1; +pub type MDBX_debug_flags = ::std::os::raw::c_int; +pub use self::MDBX_debug_flags as MDBX_debug_flags_t; +pub type MDBX_debug_func = ::std::option::Option< + unsafe extern "C" fn( + loglevel: MDBX_log_level_t, + function: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + fmt: *const ::std::os::raw::c_char, + args: va_list, + ), +>; +pub type MDBX_debug_func_nofmt = ::std::option::Option< + unsafe extern "C" fn( + loglevel: MDBX_log_level_t, + function: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + msg: *const ::std::os::raw::c_char, + length: ::std::os::raw::c_uint, + ), +>; +pub type MDBX_assert_func = ::std::option::Option< + unsafe extern "C" fn( + env: *const MDBX_env, + msg: *const ::std::os::raw::c_char, + function: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_uint, + ), +>; +pub const MDBX_ENV_DEFAULTS: MDBX_env_flags = 0; +pub const MDBX_VALIDATION: MDBX_env_flags = 8192; +pub const MDBX_NOSUBDIR: MDBX_env_flags = 16384; +pub const MDBX_RDONLY: MDBX_env_flags = 131072; +pub const MDBX_EXCLUSIVE: MDBX_env_flags = 4194304; +pub const MDBX_ACCEDE: MDBX_env_flags = 1073741824; +pub const MDBX_WRITEMAP: MDBX_env_flags = 524288; +pub const MDBX_NOSTICKYTHREADS: MDBX_env_flags = 2097152; +pub const MDBX_NOTLS: MDBX_env_flags = 2097152; +pub const MDBX_NORDAHEAD: MDBX_env_flags = 8388608; +pub const MDBX_NOMEMINIT: MDBX_env_flags = 16777216; +pub const MDBX_COALESCE: MDBX_env_flags = 33554432; +pub const MDBX_LIFORECLAIM: MDBX_env_flags = 67108864; +pub const MDBX_PAGEPERTURB: MDBX_env_flags = 134217728; +pub const MDBX_SYNC_DURABLE: MDBX_env_flags = 0; +pub const MDBX_NOMETASYNC: MDBX_env_flags = 262144; +pub const MDBX_SAFE_NOSYNC: MDBX_env_flags = 65536; +pub const MDBX_MAPASYNC: MDBX_env_flags = 65536; +pub const MDBX_UTTERLY_NOSYNC: MDBX_env_flags = 1114112; +pub type MDBX_env_flags = ::std::os::raw::c_uint; +pub use self::MDBX_env_flags as MDBX_env_flags_t; +pub const MDBX_TXN_READWRITE: MDBX_txn_flags = 0; +pub const MDBX_TXN_RDONLY: MDBX_txn_flags = 131072; +pub const MDBX_TXN_RDONLY_PREPARE: MDBX_txn_flags = 16908288; +pub const MDBX_TXN_TRY: MDBX_txn_flags = 268435456; +pub const MDBX_TXN_NOMETASYNC: MDBX_txn_flags = 262144; +pub const MDBX_TXN_NOSYNC: MDBX_txn_flags = 65536; +pub const MDBX_TXN_INVALID: MDBX_txn_flags = -2147483648; +pub const MDBX_TXN_FINISHED: MDBX_txn_flags = 1; +pub const MDBX_TXN_ERROR: MDBX_txn_flags = 2; +pub const MDBX_TXN_DIRTY: MDBX_txn_flags = 4; +pub const MDBX_TXN_SPILLS: MDBX_txn_flags = 8; +pub const MDBX_TXN_HAS_CHILD: MDBX_txn_flags = 16; +pub const MDBX_TXN_PARKED: MDBX_txn_flags = 32; +pub const MDBX_TXN_AUTOUNPARK: MDBX_txn_flags = 64; +pub const MDBX_TXN_OUSTED: MDBX_txn_flags = 128; +pub const MDBX_TXN_BLOCKED: MDBX_txn_flags = 51; +pub type MDBX_txn_flags = ::std::os::raw::c_int; +pub use self::MDBX_txn_flags as MDBX_txn_flags_t; +pub const MDBX_DB_DEFAULTS: MDBX_db_flags = 0; +pub const MDBX_REVERSEKEY: MDBX_db_flags = 2; +pub const MDBX_DUPSORT: MDBX_db_flags = 4; +pub const MDBX_INTEGERKEY: MDBX_db_flags = 8; +pub const MDBX_DUPFIXED: MDBX_db_flags = 16; +pub const MDBX_INTEGERDUP: MDBX_db_flags = 32; +pub const MDBX_REVERSEDUP: MDBX_db_flags = 64; +pub const MDBX_CREATE: MDBX_db_flags = 262144; +pub const MDBX_DB_ACCEDE: MDBX_db_flags = 1073741824; +pub type MDBX_db_flags = ::std::os::raw::c_uint; +pub use self::MDBX_db_flags as MDBX_db_flags_t; +pub const MDBX_UPSERT: MDBX_put_flags = 0; +pub const MDBX_NOOVERWRITE: MDBX_put_flags = 16; +pub const MDBX_NODUPDATA: MDBX_put_flags = 32; +pub const MDBX_CURRENT: MDBX_put_flags = 64; +pub const MDBX_ALLDUPS: MDBX_put_flags = 128; +pub const MDBX_RESERVE: MDBX_put_flags = 65536; +pub const MDBX_APPEND: MDBX_put_flags = 131072; +pub const MDBX_APPENDDUP: MDBX_put_flags = 262144; +pub const MDBX_MULTIPLE: MDBX_put_flags = 524288; +pub type MDBX_put_flags = ::std::os::raw::c_uint; +pub use self::MDBX_put_flags as MDBX_put_flags_t; +pub const MDBX_CP_DEFAULTS: MDBX_copy_flags = 0; +pub const MDBX_CP_COMPACT: MDBX_copy_flags = 1; +pub const MDBX_CP_FORCE_DYNAMIC_SIZE: MDBX_copy_flags = 2; +pub const MDBX_CP_DONT_FLUSH: MDBX_copy_flags = 4; +pub const MDBX_CP_THROTTLE_MVCC: MDBX_copy_flags = 8; +pub const MDBX_CP_DISPOSE_TXN: MDBX_copy_flags = 16; +pub const MDBX_CP_RENEW_TXN: MDBX_copy_flags = 32; +pub type MDBX_copy_flags = ::std::os::raw::c_uint; +pub use self::MDBX_copy_flags as MDBX_copy_flags_t; +pub const MDBX_FIRST: MDBX_cursor_op = 0; +pub const MDBX_FIRST_DUP: MDBX_cursor_op = 1; +pub const MDBX_GET_BOTH: MDBX_cursor_op = 2; +pub const MDBX_GET_BOTH_RANGE: MDBX_cursor_op = 3; +pub const MDBX_GET_CURRENT: MDBX_cursor_op = 4; +pub const MDBX_GET_MULTIPLE: MDBX_cursor_op = 5; +pub const MDBX_LAST: MDBX_cursor_op = 6; +pub const MDBX_LAST_DUP: MDBX_cursor_op = 7; +pub const MDBX_NEXT: MDBX_cursor_op = 8; +pub const MDBX_NEXT_DUP: MDBX_cursor_op = 9; +pub const MDBX_NEXT_MULTIPLE: MDBX_cursor_op = 10; +pub const MDBX_NEXT_NODUP: MDBX_cursor_op = 11; +pub const MDBX_PREV: MDBX_cursor_op = 12; +pub const MDBX_PREV_DUP: MDBX_cursor_op = 13; +pub const MDBX_PREV_NODUP: MDBX_cursor_op = 14; +pub const MDBX_SET: MDBX_cursor_op = 15; +pub const MDBX_SET_KEY: MDBX_cursor_op = 16; +pub const MDBX_SET_RANGE: MDBX_cursor_op = 17; +pub const MDBX_PREV_MULTIPLE: MDBX_cursor_op = 18; +pub const MDBX_SET_LOWERBOUND: MDBX_cursor_op = 19; +pub const MDBX_SET_UPPERBOUND: MDBX_cursor_op = 20; +pub const MDBX_TO_KEY_LESSER_THAN: MDBX_cursor_op = 21; +pub const MDBX_TO_KEY_LESSER_OR_EQUAL: MDBX_cursor_op = 22; +pub const MDBX_TO_KEY_EQUAL: MDBX_cursor_op = 23; +pub const MDBX_TO_KEY_GREATER_OR_EQUAL: MDBX_cursor_op = 24; +pub const MDBX_TO_KEY_GREATER_THAN: MDBX_cursor_op = 25; +pub const MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN: MDBX_cursor_op = 26; +pub const MDBX_TO_EXACT_KEY_VALUE_LESSER_OR_EQUAL: MDBX_cursor_op = 27; +pub const MDBX_TO_EXACT_KEY_VALUE_EQUAL: MDBX_cursor_op = 28; +pub const MDBX_TO_EXACT_KEY_VALUE_GREATER_OR_EQUAL: MDBX_cursor_op = 29; +pub const MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN: MDBX_cursor_op = 30; +pub const MDBX_TO_PAIR_LESSER_THAN: MDBX_cursor_op = 31; +pub const MDBX_TO_PAIR_LESSER_OR_EQUAL: MDBX_cursor_op = 32; +pub const MDBX_TO_PAIR_EQUAL: MDBX_cursor_op = 33; +pub const MDBX_TO_PAIR_GREATER_OR_EQUAL: MDBX_cursor_op = 34; +pub const MDBX_TO_PAIR_GREATER_THAN: MDBX_cursor_op = 35; +pub const MDBX_SEEK_AND_GET_MULTIPLE: MDBX_cursor_op = 36; +pub type MDBX_cursor_op = ::std::os::raw::c_uint; +pub const MDBX_SUCCESS: MDBX_error = 0; +pub const MDBX_RESULT_FALSE: MDBX_error = 0; +pub const MDBX_RESULT_TRUE: MDBX_error = -1; +pub const MDBX_KEYEXIST: MDBX_error = -30799; +pub const MDBX_FIRST_LMDB_ERRCODE: MDBX_error = -30799; +pub const MDBX_NOTFOUND: MDBX_error = -30798; +pub const MDBX_PAGE_NOTFOUND: MDBX_error = -30797; +pub const MDBX_CORRUPTED: MDBX_error = -30796; +pub const MDBX_PANIC: MDBX_error = -30795; +pub const MDBX_VERSION_MISMATCH: MDBX_error = -30794; +pub const MDBX_INVALID: MDBX_error = -30793; +pub const MDBX_MAP_FULL: MDBX_error = -30792; +pub const MDBX_DBS_FULL: MDBX_error = -30791; +pub const MDBX_READERS_FULL: MDBX_error = -30790; +pub const MDBX_TXN_FULL: MDBX_error = -30788; +pub const MDBX_CURSOR_FULL: MDBX_error = -30787; +pub const MDBX_PAGE_FULL: MDBX_error = -30786; +pub const MDBX_UNABLE_EXTEND_MAPSIZE: MDBX_error = -30785; +pub const MDBX_INCOMPATIBLE: MDBX_error = -30784; +pub const MDBX_BAD_RSLOT: MDBX_error = -30783; +pub const MDBX_BAD_TXN: MDBX_error = -30782; +pub const MDBX_BAD_VALSIZE: MDBX_error = -30781; +pub const MDBX_BAD_DBI: MDBX_error = -30780; +pub const MDBX_PROBLEM: MDBX_error = -30779; +pub const MDBX_LAST_LMDB_ERRCODE: MDBX_error = -30779; +pub const MDBX_BUSY: MDBX_error = -30778; +pub const MDBX_FIRST_ADDED_ERRCODE: MDBX_error = -30778; +pub const MDBX_EMULTIVAL: MDBX_error = -30421; +pub const MDBX_EBADSIGN: MDBX_error = -30420; +pub const MDBX_WANNA_RECOVERY: MDBX_error = -30419; +pub const MDBX_EKEYMISMATCH: MDBX_error = -30418; +pub const MDBX_TOO_LARGE: MDBX_error = -30417; +pub const MDBX_THREAD_MISMATCH: MDBX_error = -30416; +pub const MDBX_TXN_OVERLAPPING: MDBX_error = -30415; +pub const MDBX_BACKLOG_DEPLETED: MDBX_error = -30414; +pub const MDBX_DUPLICATED_CLK: MDBX_error = -30413; +pub const MDBX_DANGLING_DBI: MDBX_error = -30412; +pub const MDBX_OUSTED: MDBX_error = -30411; +pub const MDBX_MVCC_RETARDED: MDBX_error = -30410; +pub const MDBX_LAST_ADDED_ERRCODE: MDBX_error = -30410; +pub const MDBX_ENODATA: MDBX_error = 61; +pub const MDBX_EINVAL: MDBX_error = 22; +pub const MDBX_EACCESS: MDBX_error = 13; +pub const MDBX_ENOMEM: MDBX_error = 12; +pub const MDBX_EROFS: MDBX_error = 30; +pub const MDBX_ENOSYS: MDBX_error = 38; +pub const MDBX_EIO: MDBX_error = 5; +pub const MDBX_EPERM: MDBX_error = 1; +pub const MDBX_EINTR: MDBX_error = 4; +pub const MDBX_ENOFILE: MDBX_error = 2; +pub const MDBX_EREMOTE: MDBX_error = 121; +pub const MDBX_EDEADLK: MDBX_error = 35; +pub type MDBX_error = ::std::os::raw::c_int; +pub use self::MDBX_error as MDBX_error_t; +pub const MDBX_opt_max_db: MDBX_option = 0; +pub const MDBX_opt_max_readers: MDBX_option = 1; +pub const MDBX_opt_sync_bytes: MDBX_option = 2; +pub const MDBX_opt_sync_period: MDBX_option = 3; +pub const MDBX_opt_rp_augment_limit: MDBX_option = 4; +pub const MDBX_opt_loose_limit: MDBX_option = 5; +pub const MDBX_opt_dp_reserve_limit: MDBX_option = 6; +pub const MDBX_opt_txn_dp_limit: MDBX_option = 7; +pub const MDBX_opt_txn_dp_initial: MDBX_option = 8; +pub const MDBX_opt_spill_max_denominator: MDBX_option = 9; +pub const MDBX_opt_spill_min_denominator: MDBX_option = 10; +pub const MDBX_opt_spill_parent4child_denominator: MDBX_option = 11; +pub const MDBX_opt_merge_threshold_16dot16_percent: MDBX_option = 12; +pub const MDBX_opt_writethrough_threshold: MDBX_option = 13; +pub const MDBX_opt_prefault_write_enable: MDBX_option = 14; +pub const MDBX_opt_gc_time_limit: MDBX_option = 15; +pub const MDBX_opt_prefer_waf_insteadof_balance: MDBX_option = 16; +pub const MDBX_opt_subpage_limit: MDBX_option = 17; +pub const MDBX_opt_subpage_room_threshold: MDBX_option = 18; +pub const MDBX_opt_subpage_reserve_prereq: MDBX_option = 19; +pub const MDBX_opt_subpage_reserve_limit: MDBX_option = 20; +pub type MDBX_option = ::std::os::raw::c_uint; +pub use self::MDBX_option as MDBX_option_t; +pub const MDBX_ENV_JUST_DELETE: MDBX_env_delete_mode = 0; +pub const MDBX_ENV_ENSURE_UNUSED: MDBX_env_delete_mode = 1; +pub const MDBX_ENV_WAIT_FOR_UNUSED: MDBX_env_delete_mode = 2; +pub type MDBX_env_delete_mode = ::std::os::raw::c_uint; +pub use self::MDBX_env_delete_mode as MDBX_env_delete_mode_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_stat { + pub ms_psize: u32, + pub ms_depth: u32, + pub ms_branch_pages: u64, + pub ms_leaf_pages: u64, + pub ms_overflow_pages: u64, + pub ms_entries: u64, + pub ms_mod_txnid: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo { + pub mi_geo: MDBX_envinfo__bindgen_ty_1, + pub mi_mapsize: u64, + pub mi_last_pgno: u64, + pub mi_recent_txnid: u64, + pub mi_latter_reader_txnid: u64, + pub mi_self_latter_reader_txnid: u64, + pub mi_meta_txnid: [u64; 3usize], + pub mi_meta_sign: [u64; 3usize], + pub mi_maxreaders: u32, + pub mi_numreaders: u32, + pub mi_dxb_pagesize: u32, + pub mi_sys_pagesize: u32, + pub mi_bootid: MDBX_envinfo__bindgen_ty_2, + pub mi_unsync_volume: u64, + pub mi_autosync_threshold: u64, + pub mi_since_sync_seconds16dot16: u32, + pub mi_autosync_period_seconds16dot16: u32, + pub mi_since_reader_check_seconds16dot16: u32, + pub mi_mode: u32, + pub mi_pgop_stat: MDBX_envinfo__bindgen_ty_3, + pub mi_dxbid: MDBX_envinfo__bindgen_ty_4, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo__bindgen_ty_1 { + pub lower: u64, + pub upper: u64, + pub current: u64, + pub shrink: u64, + pub grow: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo__bindgen_ty_2 { + pub current: MDBX_envinfo__bindgen_ty_2__bindgen_ty_1, + pub meta: [MDBX_envinfo__bindgen_ty_2__bindgen_ty_1; 3usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo__bindgen_ty_2__bindgen_ty_1 { + pub x: u64, + pub y: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo__bindgen_ty_3 { + pub newly: u64, + pub cow: u64, + pub clone: u64, + pub split: u64, + pub merge: u64, + pub spill: u64, + pub unspill: u64, + pub wops: u64, + pub prefault: u64, + pub mincore: u64, + pub msync: u64, + pub fsync: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_envinfo__bindgen_ty_4 { + pub x: u64, + pub y: u64, +} +pub const MDBX_warmup_default: MDBX_warmup_flags = 0; +pub const MDBX_warmup_force: MDBX_warmup_flags = 1; +pub const MDBX_warmup_oomsafe: MDBX_warmup_flags = 2; +pub const MDBX_warmup_lock: MDBX_warmup_flags = 4; +pub const MDBX_warmup_touchlimit: MDBX_warmup_flags = 8; +pub const MDBX_warmup_release: MDBX_warmup_flags = 16; +pub type MDBX_warmup_flags = ::std::os::raw::c_uint; +pub use self::MDBX_warmup_flags as MDBX_warmup_flags_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_txn_info { + pub txn_id: u64, + pub txn_reader_lag: u64, + pub txn_space_used: u64, + pub txn_space_limit_soft: u64, + pub txn_space_limit_hard: u64, + pub txn_space_retired: u64, + pub txn_space_leftover: u64, + pub txn_space_dirty: u64, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_commit_latency { + pub preparation: u32, + pub gc_wallclock: u32, + pub audit: u32, + pub write: u32, + pub sync: u32, + pub ending: u32, + pub whole: u32, + pub gc_cputime: u32, + pub gc_prof: MDBX_commit_latency__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_commit_latency__bindgen_ty_1 { + pub wloops: u32, + pub coalescences: u32, + pub wipes: u32, + pub flushes: u32, + pub kicks: u32, + pub work_counter: u32, + pub work_rtime_monotonic: u32, + pub work_xtime_cpu: u32, + pub work_rsteps: u32, + pub work_xpages: u32, + pub work_majflt: u32, + pub self_counter: u32, + pub self_rtime_monotonic: u32, + pub self_xtime_cpu: u32, + pub self_rsteps: u32, + pub self_xpages: u32, + pub self_majflt: u32, + pub pnl_merge_work: MDBX_commit_latency__bindgen_ty_1__bindgen_ty_1, + pub pnl_merge_self: MDBX_commit_latency__bindgen_ty_1__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_commit_latency__bindgen_ty_1__bindgen_ty_1 { + pub time: u32, + pub volume: u64, + pub calls: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_canary { + pub x: u64, + pub y: u64, + pub z: u64, + pub v: u64, +} +pub type MDBX_cmp_func = ::std::option::Option< + unsafe extern "C" fn(a: *const MDBX_val, b: *const MDBX_val) -> ::std::os::raw::c_int, +>; +pub type MDBX_table_enum_func = ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut ::std::os::raw::c_void, + txn: *const MDBX_txn, + name: *const MDBX_val, + flags: MDBX_db_flags_t, + stat: *const MDBX_stat, + dbi: MDBX_dbi, + ) -> ::std::os::raw::c_int, +>; +pub const MDBX_DBI_DIRTY: MDBX_dbi_state = 1; +pub const MDBX_DBI_STALE: MDBX_dbi_state = 2; +pub const MDBX_DBI_FRESH: MDBX_dbi_state = 4; +pub const MDBX_DBI_CREAT: MDBX_dbi_state = 8; +pub type MDBX_dbi_state = ::std::os::raw::c_uint; +pub use self::MDBX_dbi_state as MDBX_dbi_state_t; +pub type MDBX_preserve_func = ::std::option::Option< + unsafe extern "C" fn( + context: *mut ::std::os::raw::c_void, + target: *mut MDBX_val, + src: *const ::std::os::raw::c_void, + bytes: usize, + ) -> ::std::os::raw::c_int, +>; +pub type MDBX_predicate_func = ::std::option::Option< + unsafe extern "C" fn( + context: *mut ::std::os::raw::c_void, + key: *mut MDBX_val, + value: *mut MDBX_val, + arg: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +pub type MDBX_reader_list_func = ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut ::std::os::raw::c_void, + num: ::std::os::raw::c_int, + slot: ::std::os::raw::c_int, + pid: mdbx_pid_t, + thread: mdbx_tid_t, + txnid: u64, + lag: u64, + bytes_used: usize, + bytes_retained: usize, + ) -> ::std::os::raw::c_int, +>; +pub type MDBX_hsr_func = ::std::option::Option< + unsafe extern "C" fn( + env: *const MDBX_env, + txn: *const MDBX_txn, + pid: mdbx_pid_t, + tid: mdbx_tid_t, + laggard: u64, + gap: ::std::os::raw::c_uint, + space: usize, + retry: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, +>; +pub const MDBX_CHK_DEFAULTS: MDBX_chk_flags = 0; +pub const MDBX_CHK_READWRITE: MDBX_chk_flags = 1; +pub const MDBX_CHK_SKIP_BTREE_TRAVERSAL: MDBX_chk_flags = 2; +pub const MDBX_CHK_SKIP_KV_TRAVERSAL: MDBX_chk_flags = 4; +pub const MDBX_CHK_IGNORE_ORDER: MDBX_chk_flags = 8; +pub type MDBX_chk_flags = ::std::os::raw::c_uint; +pub use self::MDBX_chk_flags as MDBX_chk_flags_t; +pub const MDBX_chk_severity_prio_shift: MDBX_chk_severity = 4; +pub const MDBX_chk_severity_kind_mask: MDBX_chk_severity = 15; +pub const MDBX_chk_fatal: MDBX_chk_severity = 0; +pub const MDBX_chk_error: MDBX_chk_severity = 17; +pub const MDBX_chk_warning: MDBX_chk_severity = 34; +pub const MDBX_chk_notice: MDBX_chk_severity = 51; +pub const MDBX_chk_result: MDBX_chk_severity = 68; +pub const MDBX_chk_resolution: MDBX_chk_severity = 85; +pub const MDBX_chk_processing: MDBX_chk_severity = 86; +pub const MDBX_chk_info: MDBX_chk_severity = 103; +pub const MDBX_chk_verbose: MDBX_chk_severity = 120; +pub const MDBX_chk_details: MDBX_chk_severity = 137; +pub const MDBX_chk_extra: MDBX_chk_severity = 154; +pub type MDBX_chk_severity = ::std::os::raw::c_uint; +pub use self::MDBX_chk_severity as MDBX_chk_severity_t; +pub const MDBX_chk_none: MDBX_chk_stage = 0; +pub const MDBX_chk_init: MDBX_chk_stage = 1; +pub const MDBX_chk_lock: MDBX_chk_stage = 2; +pub const MDBX_chk_meta: MDBX_chk_stage = 3; +pub const MDBX_chk_tree: MDBX_chk_stage = 4; +pub const MDBX_chk_gc: MDBX_chk_stage = 5; +pub const MDBX_chk_space: MDBX_chk_stage = 6; +pub const MDBX_chk_maindb: MDBX_chk_stage = 7; +pub const MDBX_chk_tables: MDBX_chk_stage = 8; +pub const MDBX_chk_conclude: MDBX_chk_stage = 9; +pub const MDBX_chk_unlock: MDBX_chk_stage = 10; +pub const MDBX_chk_finalize: MDBX_chk_stage = 11; +pub type MDBX_chk_stage = ::std::os::raw::c_uint; +pub use self::MDBX_chk_stage as MDBX_chk_stage_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_line { + pub ctx: *mut MDBX_chk_context, + pub severity: u8, + pub scope_depth: u8, + pub empty: u8, + pub begin: *mut ::std::os::raw::c_char, + pub end: *mut ::std::os::raw::c_char, + pub out: *mut ::std::os::raw::c_char, +} +pub type MDBX_chk_line_t = MDBX_chk_line; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_issue { + pub next: *mut MDBX_chk_issue, + pub count: usize, + pub caption: *const ::std::os::raw::c_char, +} +pub type MDBX_chk_issue_t = MDBX_chk_issue; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct MDBX_chk_scope { + pub issues: *mut MDBX_chk_issue_t, + pub internal: *mut MDBX_chk_internal, + pub object: *const ::std::os::raw::c_void, + pub stage: MDBX_chk_stage_t, + pub verbosity: MDBX_chk_severity_t, + pub subtotal_issues: usize, + pub usr_z: MDBX_chk_scope__bindgen_ty_1, + pub usr_v: MDBX_chk_scope__bindgen_ty_1, + pub usr_o: MDBX_chk_scope__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union MDBX_chk_scope__bindgen_ty_1 { + pub ptr: *mut ::std::os::raw::c_void, + pub number: usize, +} +pub type MDBX_chk_scope_t = MDBX_chk_scope; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_user_table_cookie { + _unused: [u8; 0], +} +pub type MDBX_chk_user_table_cookie_t = MDBX_chk_user_table_cookie; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_histogram { + pub amount: usize, + pub count: usize, + pub ones: usize, + pub pad: usize, + pub ranges: [MDBX_chk_histogram__bindgen_ty_1; 9usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_histogram__bindgen_ty_1 { + pub begin: usize, + pub end: usize, + pub amount: usize, + pub count: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_table { + pub cookie: *mut MDBX_chk_user_table_cookie_t, + pub name: MDBX_val, + pub flags: MDBX_db_flags_t, + pub id: ::std::os::raw::c_int, + pub payload_bytes: usize, + pub lost_bytes: usize, + pub pages: MDBX_chk_table__bindgen_ty_1, + pub histogram: MDBX_chk_table__bindgen_ty_2, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_table__bindgen_ty_1 { + pub all: usize, + pub empty: usize, + pub other: usize, + pub branch: usize, + pub leaf: usize, + pub nested_branch: usize, + pub nested_leaf: usize, + pub nested_subleaf: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_table__bindgen_ty_2 { + pub deep: MDBX_chk_histogram, + pub large_pages: MDBX_chk_histogram, + pub nested_tree: MDBX_chk_histogram, + pub key_len: MDBX_chk_histogram, + pub val_len: MDBX_chk_histogram, +} +pub type MDBX_chk_table_t = MDBX_chk_table; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_context { + pub internal: *mut MDBX_chk_internal, + pub env: *mut MDBX_env, + pub txn: *mut MDBX_txn, + pub scope: *mut MDBX_chk_scope_t, + pub scope_nesting: u8, + pub result: MDBX_chk_context__bindgen_ty_1, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_context__bindgen_ty_1 { + pub total_payload_bytes: usize, + pub table_total: usize, + pub table_processed: usize, + pub total_unused_bytes: usize, + pub unused_pages: usize, + pub processed_pages: usize, + pub reclaimable_pages: usize, + pub gc_pages: usize, + pub alloc_pages: usize, + pub backed_pages: usize, + pub problems_meta: usize, + pub tree_problems: usize, + pub gc_tree_problems: usize, + pub kv_tree_problems: usize, + pub problems_gc: usize, + pub problems_kv: usize, + pub total_problems: usize, + pub steady_txnid: u64, + pub recent_txnid: u64, + pub tables: *const *const MDBX_chk_table_t, +} +pub type MDBX_chk_context_t = MDBX_chk_context; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_callbacks { + pub check_break: + ::std::option::Option bool>, + pub scope_push: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + outer: *mut MDBX_chk_scope_t, + inner: *mut MDBX_chk_scope_t, + fmt: *const ::std::os::raw::c_char, + args: va_list, + ) -> ::std::os::raw::c_int, + >, + pub scope_conclude: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + outer: *mut MDBX_chk_scope_t, + inner: *mut MDBX_chk_scope_t, + err: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >, + pub scope_pop: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + outer: *mut MDBX_chk_scope_t, + inner: *mut MDBX_chk_scope_t, + ), + >, + pub issue: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + object: *const ::std::os::raw::c_char, + entry_number: u64, + issue: *const ::std::os::raw::c_char, + extra_fmt: *const ::std::os::raw::c_char, + extra_args: va_list, + ), + >, + pub table_filter: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + name: *const MDBX_val, + flags: MDBX_db_flags_t, + ) -> *mut MDBX_chk_user_table_cookie_t, + >, + pub table_conclude: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + table: *const MDBX_chk_table_t, + cursor: *mut MDBX_cursor, + err: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >, + pub table_dispose: ::std::option::Option< + unsafe extern "C" fn(ctx: *mut MDBX_chk_context_t, table: *const MDBX_chk_table_t), + >, + pub table_handle_kv: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + table: *const MDBX_chk_table_t, + entry_number: usize, + key: *const MDBX_val, + value: *const MDBX_val, + ) -> ::std::os::raw::c_int, + >, + pub stage_begin: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + arg1: MDBX_chk_stage_t, + ) -> ::std::os::raw::c_int, + >, + pub stage_end: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + arg1: MDBX_chk_stage_t, + err: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int, + >, + pub print_begin: ::std::option::Option< + unsafe extern "C" fn( + ctx: *mut MDBX_chk_context_t, + severity: MDBX_chk_severity_t, + ) -> *mut MDBX_chk_line_t, + >, + pub print_flush: ::std::option::Option, + pub print_done: ::std::option::Option, + pub print_chars: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut MDBX_chk_line_t, + str_: *const ::std::os::raw::c_char, + len: usize, + ), + >, + pub print_format: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut MDBX_chk_line_t, + fmt: *const ::std::os::raw::c_char, + args: va_list, + ), + >, + pub print_size: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut MDBX_chk_line_t, + prefix: *const ::std::os::raw::c_char, + value: u64, + suffix: *const ::std::os::raw::c_char, + ), + >, +} +pub type MDBX_chk_callbacks_t = MDBX_chk_callbacks; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct MDBX_chk_internal { + pub _address: u8, +} +unsafe extern "C" { + pub static mdbx_version: MDBX_version_info; + pub static mdbx_build: MDBX_build_info; + pub fn mdbx_setup_debug( + log_level: MDBX_log_level_t, + debug_flags: MDBX_debug_flags_t, + logger: MDBX_debug_func, + ) -> ::std::os::raw::c_int; + pub fn mdbx_setup_debug_nofmt( + log_level: MDBX_log_level_t, + debug_flags: MDBX_debug_flags_t, + logger: MDBX_debug_func_nofmt, + logger_buffer: *mut ::std::os::raw::c_char, + logger_buffer_size: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_assert(env: *mut MDBX_env, func: MDBX_assert_func) + -> ::std::os::raw::c_int; + pub fn mdbx_dump_val( + key: *const MDBX_val, + buf: *mut ::std::os::raw::c_char, + bufsize: usize, + ) -> *const ::std::os::raw::c_char; + pub fn mdbx_panic(fmt: *const ::std::os::raw::c_char, ...) -> !; + pub fn mdbx_assert_fail( + env: *const MDBX_env, + msg: *const ::std::os::raw::c_char, + func: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_uint, + ) -> !; + pub fn mdbx_strerror(errnum: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char; + pub fn mdbx_strerror_r( + errnum: ::std::os::raw::c_int, + buf: *mut ::std::os::raw::c_char, + buflen: usize, + ) -> *const ::std::os::raw::c_char; + pub fn mdbx_liberr2str(errnum: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char; + pub fn mdbx_env_create(penv: *mut *mut MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_option( + env: *mut MDBX_env, + option: MDBX_option_t, + value: u64, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_option( + env: *const MDBX_env, + option: MDBX_option_t, + pvalue: *mut u64, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_open( + env: *mut MDBX_env, + pathname: *const ::std::os::raw::c_char, + flags: MDBX_env_flags_t, + mode: mdbx_mode_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_delete( + pathname: *const ::std::os::raw::c_char, + mode: MDBX_env_delete_mode_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_copy( + env: *mut MDBX_env, + dest: *const ::std::os::raw::c_char, + flags: MDBX_copy_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_copy2pathname( + txn: *mut MDBX_txn, + dest: *const ::std::os::raw::c_char, + flags: MDBX_copy_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_copy2fd( + env: *mut MDBX_env, + fd: mdbx_filehandle_t, + flags: MDBX_copy_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_copy2fd( + txn: *mut MDBX_txn, + fd: mdbx_filehandle_t, + flags: MDBX_copy_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_stat_ex( + env: *const MDBX_env, + txn: *const MDBX_txn, + stat: *mut MDBX_stat, + bytes: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_info_ex( + env: *const MDBX_env, + txn: *const MDBX_txn, + info: *mut MDBX_envinfo, + bytes: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_sync_ex( + env: *mut MDBX_env, + force: bool, + nonblock: bool, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_close_ex(env: *mut MDBX_env, dont_sync: bool) -> ::std::os::raw::c_int; + pub fn mdbx_env_resurrect_after_fork(env: *mut MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_env_warmup( + env: *const MDBX_env, + txn: *const MDBX_txn, + flags: MDBX_warmup_flags_t, + timeout_seconds_16dot16: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_flags( + env: *mut MDBX_env, + flags: MDBX_env_flags_t, + onoff: bool, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_flags( + env: *const MDBX_env, + flags: *mut ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_path( + env: *const MDBX_env, + dest: *mut *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_fd( + env: *const MDBX_env, + fd: *mut mdbx_filehandle_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_geometry( + env: *mut MDBX_env, + size_lower: isize, + size_now: isize, + size_upper: isize, + growth_step: isize, + shrink_threshold: isize, + pagesize: isize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_is_readahead_reasonable(volume: usize, redundancy: isize) -> ::std::os::raw::c_int; + pub fn mdbx_limits_dbsize_min(pagesize: isize) -> isize; + pub fn mdbx_limits_dbsize_max(pagesize: isize) -> isize; + pub fn mdbx_limits_keysize_max(pagesize: isize, flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_keysize_min(flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_valsize_max(pagesize: isize, flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_valsize_min(flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_pairsize4page_max(pagesize: isize, flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_valsize4page_max(pagesize: isize, flags: MDBX_db_flags_t) -> isize; + pub fn mdbx_limits_txnsize_max(pagesize: isize) -> isize; + pub fn mdbx_default_pagesize() -> usize; + pub fn mdbx_get_sysraminfo( + page_size: *mut isize, + total_pages: *mut isize, + avail_pages: *mut isize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_maxkeysize_ex( + env: *const MDBX_env, + flags: MDBX_db_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_maxvalsize_ex( + env: *const MDBX_env, + flags: MDBX_db_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_maxkeysize(env: *const MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_pairsize4page_max( + env: *const MDBX_env, + flags: MDBX_db_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_valsize4page_max( + env: *const MDBX_env, + flags: MDBX_db_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_userctx( + env: *mut MDBX_env, + ctx: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_userctx(env: *const MDBX_env) -> *mut ::std::os::raw::c_void; + pub fn mdbx_txn_begin_ex( + env: *mut MDBX_env, + parent: *mut MDBX_txn, + flags: MDBX_txn_flags_t, + txn: *mut *mut MDBX_txn, + context: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_set_userctx( + txn: *mut MDBX_txn, + ctx: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_get_userctx(txn: *const MDBX_txn) -> *mut ::std::os::raw::c_void; + pub fn mdbx_txn_info( + txn: *const MDBX_txn, + info: *mut MDBX_txn_info, + scan_rlt: bool, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_env(txn: *const MDBX_txn) -> *mut MDBX_env; + pub fn mdbx_txn_flags(txn: *const MDBX_txn) -> MDBX_txn_flags_t; + pub fn mdbx_txn_id(txn: *const MDBX_txn) -> u64; + pub fn mdbx_txn_commit_ex( + txn: *mut MDBX_txn, + latency: *mut MDBX_commit_latency, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_abort(txn: *mut MDBX_txn) -> ::std::os::raw::c_int; + pub fn mdbx_txn_break(txn: *mut MDBX_txn) -> ::std::os::raw::c_int; + pub fn mdbx_txn_reset(txn: *mut MDBX_txn) -> ::std::os::raw::c_int; + pub fn mdbx_txn_park(txn: *mut MDBX_txn, autounpark: bool) -> ::std::os::raw::c_int; + pub fn mdbx_txn_unpark(txn: *mut MDBX_txn, restart_if_ousted: bool) -> ::std::os::raw::c_int; + pub fn mdbx_txn_renew(txn: *mut MDBX_txn) -> ::std::os::raw::c_int; + pub fn mdbx_canary_put(txn: *mut MDBX_txn, canary: *const MDBX_canary) + -> ::std::os::raw::c_int; + pub fn mdbx_canary_get(txn: *const MDBX_txn, canary: *mut MDBX_canary) + -> ::std::os::raw::c_int; + pub fn mdbx_dbi_open( + txn: *mut MDBX_txn, + name: *const ::std::os::raw::c_char, + flags: MDBX_db_flags_t, + dbi: *mut MDBX_dbi, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_open2( + txn: *mut MDBX_txn, + name: *const MDBX_val, + flags: MDBX_db_flags_t, + dbi: *mut MDBX_dbi, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_open_ex( + txn: *mut MDBX_txn, + name: *const ::std::os::raw::c_char, + flags: MDBX_db_flags_t, + dbi: *mut MDBX_dbi, + keycmp: MDBX_cmp_func, + datacmp: MDBX_cmp_func, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_open_ex2( + txn: *mut MDBX_txn, + name: *const MDBX_val, + flags: MDBX_db_flags_t, + dbi: *mut MDBX_dbi, + keycmp: MDBX_cmp_func, + datacmp: MDBX_cmp_func, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_rename( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + name: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_rename2( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + name: *const MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_enumerate_tables( + txn: *const MDBX_txn, + func: MDBX_table_enum_func, + ctx: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_key_from_jsonInteger(json_integer: i64) -> u64; + pub fn mdbx_key_from_double(ieee754_64bit: f64) -> u64; + pub fn mdbx_key_from_ptrdouble(ieee754_64bit: *const f64) -> u64; + pub fn mdbx_key_from_float(ieee754_32bit: f32) -> u32; + pub fn mdbx_key_from_ptrfloat(ieee754_32bit: *const f32) -> u32; + pub fn mdbx_jsonInteger_from_key(arg1: MDBX_val) -> i64; + pub fn mdbx_double_from_key(arg1: MDBX_val) -> f64; + pub fn mdbx_float_from_key(arg1: MDBX_val) -> f32; + pub fn mdbx_int32_from_key(arg1: MDBX_val) -> i32; + pub fn mdbx_int64_from_key(arg1: MDBX_val) -> i64; + pub fn mdbx_dbi_stat( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + stat: *mut MDBX_stat, + bytes: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_dupsort_depthmask( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + mask: *mut u32, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_flags_ex( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + flags: *mut ::std::os::raw::c_uint, + state: *mut ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_close(env: *mut MDBX_env, dbi: MDBX_dbi) -> ::std::os::raw::c_int; + pub fn mdbx_drop(txn: *mut MDBX_txn, dbi: MDBX_dbi, del: bool) -> ::std::os::raw::c_int; + pub fn mdbx_get( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + key: *const MDBX_val, + data: *mut MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_get_ex( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + key: *mut MDBX_val, + data: *mut MDBX_val, + values_count: *mut usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_get_equal_or_great( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + key: *mut MDBX_val, + data: *mut MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_put( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + key: *const MDBX_val, + data: *mut MDBX_val, + flags: MDBX_put_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_replace( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + key: *const MDBX_val, + new_data: *mut MDBX_val, + old_data: *mut MDBX_val, + flags: MDBX_put_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_replace_ex( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + key: *const MDBX_val, + new_data: *mut MDBX_val, + old_data: *mut MDBX_val, + flags: MDBX_put_flags_t, + preserver: MDBX_preserve_func, + preserver_context: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_del( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + key: *const MDBX_val, + data: *const MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_create(context: *mut ::std::os::raw::c_void) -> *mut MDBX_cursor; + pub fn mdbx_cursor_set_userctx( + cursor: *mut MDBX_cursor, + ctx: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_get_userctx(cursor: *const MDBX_cursor) -> *mut ::std::os::raw::c_void; + pub fn mdbx_cursor_bind( + txn: *mut MDBX_txn, + cursor: *mut MDBX_cursor, + dbi: MDBX_dbi, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_unbind(cursor: *mut MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_reset(cursor: *mut MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_open( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + cursor: *mut *mut MDBX_cursor, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_close(cursor: *mut MDBX_cursor); + pub fn mdbx_cursor_close2(cursor: *mut MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_txn_release_all_cursors_ex( + txn: *const MDBX_txn, + unbind: bool, + count: *mut usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_renew(txn: *mut MDBX_txn, cursor: *mut MDBX_cursor) + -> ::std::os::raw::c_int; + pub fn mdbx_cursor_txn(cursor: *const MDBX_cursor) -> *mut MDBX_txn; + pub fn mdbx_cursor_dbi(cursor: *const MDBX_cursor) -> MDBX_dbi; + pub fn mdbx_cursor_copy( + src: *const MDBX_cursor, + dest: *mut MDBX_cursor, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_compare( + left: *const MDBX_cursor, + right: *const MDBX_cursor, + ignore_multival: bool, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_get( + cursor: *mut MDBX_cursor, + key: *mut MDBX_val, + data: *mut MDBX_val, + op: MDBX_cursor_op, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_ignord(cursor: *mut MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_scan( + cursor: *mut MDBX_cursor, + predicate: MDBX_predicate_func, + context: *mut ::std::os::raw::c_void, + start_op: MDBX_cursor_op, + turn_op: MDBX_cursor_op, + arg: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_scan_from( + cursor: *mut MDBX_cursor, + predicate: MDBX_predicate_func, + context: *mut ::std::os::raw::c_void, + from_op: MDBX_cursor_op, + from_key: *mut MDBX_val, + from_value: *mut MDBX_val, + turn_op: MDBX_cursor_op, + arg: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_get_batch( + cursor: *mut MDBX_cursor, + count: *mut usize, + pairs: *mut MDBX_val, + limit: usize, + op: MDBX_cursor_op, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_put( + cursor: *mut MDBX_cursor, + key: *const MDBX_val, + data: *mut MDBX_val, + flags: MDBX_put_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_del( + cursor: *mut MDBX_cursor, + flags: MDBX_put_flags_t, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_count( + cursor: *const MDBX_cursor, + count: *mut usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_count_ex( + cursor: *const MDBX_cursor, + count: *mut usize, + stat: *mut MDBX_stat, + bytes: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_eof(cursor: *const MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_on_first(cursor: *const MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_on_first_dup(cursor: *const MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_on_last(cursor: *const MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_cursor_on_last_dup(cursor: *const MDBX_cursor) -> ::std::os::raw::c_int; + pub fn mdbx_estimate_distance( + first: *const MDBX_cursor, + last: *const MDBX_cursor, + distance_items: *mut isize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_estimate_move( + cursor: *const MDBX_cursor, + key: *mut MDBX_val, + data: *mut MDBX_val, + move_op: MDBX_cursor_op, + distance_items: *mut isize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_estimate_range( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + begin_key: *const MDBX_val, + begin_data: *const MDBX_val, + end_key: *const MDBX_val, + end_data: *const MDBX_val, + distance_items: *mut isize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_is_dirty( + txn: *const MDBX_txn, + ptr: *const ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_dbi_sequence( + txn: *mut MDBX_txn, + dbi: MDBX_dbi, + result: *mut u64, + increment: u64, + ) -> ::std::os::raw::c_int; + pub fn mdbx_cmp( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + a: *const MDBX_val, + b: *const MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_get_keycmp(flags: MDBX_db_flags_t) -> MDBX_cmp_func; + pub fn mdbx_dcmp( + txn: *const MDBX_txn, + dbi: MDBX_dbi, + a: *const MDBX_val, + b: *const MDBX_val, + ) -> ::std::os::raw::c_int; + pub fn mdbx_get_datacmp(flags: MDBX_db_flags_t) -> MDBX_cmp_func; + pub fn mdbx_reader_list( + env: *const MDBX_env, + func: MDBX_reader_list_func, + ctx: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int; + pub fn mdbx_reader_check( + env: *mut MDBX_env, + dead: *mut ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; + pub fn mdbx_txn_straggler( + txn: *const MDBX_txn, + percent: *mut ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; + pub fn mdbx_thread_register(env: *const MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_thread_unregister(env: *const MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_env_set_hsr( + env: *mut MDBX_env, + hsr_callback: MDBX_hsr_func, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_get_hsr(env: *const MDBX_env) -> MDBX_hsr_func; + pub fn mdbx_txn_lock(env: *mut MDBX_env, dont_wait: bool) -> ::std::os::raw::c_int; + pub fn mdbx_txn_unlock(env: *mut MDBX_env) -> ::std::os::raw::c_int; + pub fn mdbx_env_open_for_recovery( + env: *mut MDBX_env, + pathname: *const ::std::os::raw::c_char, + target_meta: ::std::os::raw::c_uint, + writeable: bool, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_turn_for_recovery( + env: *mut MDBX_env, + target_meta: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; + pub fn mdbx_preopen_snapinfo( + pathname: *const ::std::os::raw::c_char, + info: *mut MDBX_envinfo, + bytes: usize, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_chk( + env: *mut MDBX_env, + cb: *const MDBX_chk_callbacks_t, + ctx: *mut MDBX_chk_context_t, + flags: MDBX_chk_flags_t, + verbosity: MDBX_chk_severity_t, + timeout_seconds_16dot16: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; + pub fn mdbx_env_chk_encount_problem(ctx: *mut MDBX_chk_context_t) -> ::std::os::raw::c_int; +} diff --git a/mdbx-sys/src/bindings.rs b/mdbx-sys/src/bindings_macos.rs similarity index 99% rename from mdbx-sys/src/bindings.rs rename to mdbx-sys/src/bindings_macos.rs index e72a528..c40f67e 100644 --- a/mdbx-sys/src/bindings.rs +++ b/mdbx-sys/src/bindings_macos.rs @@ -1,7 +1,7 @@ /* automatically generated by rust-bindgen 0.72.1 */ -pub const MDBX_VERSION_MAJOR: ::std::os::raw::c_uint = 0; -pub const MDBX_VERSION_MINOR: ::std::os::raw::c_uint = 13; +pub const MDBX_VERSION_MAJOR: u32 = 0; +pub const MDBX_VERSION_MINOR: u32 = 13; pub const MDBX_LOCKNAME: &[u8; 10] = b"/mdbx.lck\0"; pub const MDBX_DATANAME: &[u8; 10] = b"/mdbx.dat\0"; pub const MDBX_LOCK_SUFFIX: &[u8; 5] = b"-lck\0"; diff --git a/mdbx-sys/src/bindings_windows.rs b/mdbx-sys/src/bindings_windows.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/mdbx-sys/src/bindings_windows.rs @@ -0,0 +1 @@ + diff --git a/mdbx-sys/src/lib.rs b/mdbx-sys/src/lib.rs index d2edb6f..2f674b9 100644 --- a/mdbx-sys/src/lib.rs +++ b/mdbx-sys/src/lib.rs @@ -7,13 +7,18 @@ )] #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, clippy::all)] -#![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(feature = "bindgen")] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +#[cfg(target_os = "linux")] +mod bindings_linux; +#[cfg(target_os = "linux")] +pub use bindings_linux::*; -#[cfg(not(feature = "bindgen"))] -mod bindings; +#[cfg(target_os = "windows")] +mod bindings_windows; +#[cfg(target_os = "windows")] +pub use bindings_windows::*; -#[cfg(not(feature = "bindgen"))] -pub use bindings::*; +#[cfg(not(any(target_os = "linux", target_os = "windows")))] +mod bindings_macos; +#[cfg(not(any(target_os = "linux", target_os = "windows")))] +pub use bindings_macos::*; diff --git a/src/sys/txn_manager.rs b/src/sys/txn_manager.rs index 3373f9f..9561527 100644 --- a/src/sys/txn_manager.rs +++ b/src/sys/txn_manager.rs @@ -417,7 +417,7 @@ mod read_transactions { let tx = env.begin_ro_txn().unwrap(); sleep(READ_TRANSACTIONS_CHECK_INTERVAL); - assert!(tx.commit().is_ok()) + tx.commit().unwrap(); } } } diff --git a/src/tx/cursor.rs b/src/tx/cursor.rs index 65c7350..d7201d9 100644 --- a/src/tx/cursor.rs +++ b/src/tx/cursor.rs @@ -87,6 +87,17 @@ where self.db.flags() } + /// Returns `true` if the cursor is at EOF or not positioned. + /// + /// This can be used to check if the cursor has valid data before + /// performing operations that depend on cursor position. + pub fn is_eof(&self) -> bool { + self.txn + .txn_execute(|_| unsafe { ffi::mdbx_cursor_eof(self.cursor) }) + .unwrap_or(ffi::MDBX_RESULT_TRUE) + == ffi::MDBX_RESULT_TRUE + } + /// Validates that the database has the DUP_SORT flag set. #[inline(always)] fn require_dup_sort(&self) -> MdbxResult<()> { @@ -165,8 +176,10 @@ where where Value: TableObject<'tx>, { - let (_, v, _) = codec_try_optional!(self.get::<(), Value>(key, data, op)); - + let (_, v, result_true) = codec_try_optional!(self.get::<(), Value>(key, data, op)); + if result_true { + return Ok(None); + } Ok(Some(v)) } @@ -180,8 +193,10 @@ where Key: TableObject<'tx>, Value: TableObject<'tx>, { - let (k, v, _) = codec_try_optional!(self.get(key, data, op)); - + let (k, v, result_true) = codec_try_optional!(self.get(key, data, op)); + if result_true { + return Ok(None); + } Ok(Some((k.unwrap(), v))) } @@ -423,6 +438,9 @@ where /// until the end of the database. For new cursors, the iterator will begin /// with the first item in the database. /// + /// If the cursor is at EOF or not positioned (e.g., after exhausting a + /// previous iteration), it will be repositioned to the first item. + /// /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), /// the duplicate data items of each key will be returned before moving on /// to the next key. @@ -432,6 +450,13 @@ where Key: TableObject<'tx>, Value: TableObject<'tx>, { + if self.is_eof() { + // Reposition to first item + match self.first::() { + Ok(Some(first)) => return IterKeyVals::from_ref_with(self, first), + Ok(None) | Err(_) => return IterKeyVals::end_from_ref(self), + } + } IterKeyVals::from_ref(self) } @@ -449,9 +474,9 @@ where /// Iterate over database items starting from the beginning of the database. /// - /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), the - /// duplicate data items of each key will be returned before moving on to - /// the next key. + /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), + /// the duplicate data items of each key will be returned before moving on + /// to the next key. pub fn iter_start<'cur, Key, Value>( &'cur mut self, ) -> ReadResult> @@ -469,9 +494,9 @@ where /// Iterate over database items starting from the given key. /// - /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), the - /// duplicate data items of each key will be returned before moving on to - /// the next key. + /// For databases with duplicate data items ([`DatabaseFlags::DUP_SORT`]), + /// the duplicate data items of each key will be returned before moving on + /// to the next key. pub fn iter_from<'cur, Key, Value>( &'cur mut self, key: &[u8], @@ -497,11 +522,20 @@ where /// current cursor position, and continue until the end of the database. /// For new cursors, the iterator will begin with the first key in the /// database. + /// + /// If the cursor is at EOF or not positioned (e.g., after exhausting a + /// previous iteration), it will be repositioned to the first item. pub fn iter_dup<'cur, Key, Value>(&'cur mut self) -> IterDup<'tx, 'cur, K, Key, Value> where Key: TableObject<'tx>, Value: TableObject<'tx>, { + if self.is_eof() { + match self.first::() { + Ok(Some(first)) => return IterDup::from_ref_with(self, first), + Ok(None) | Err(_) => return IterDup::end_from_ref(self), + } + } IterDup::from_ref(self) } diff --git a/tests/cursor.rs b/tests/cursor.rs index 5679d81..fcc1d51 100644 --- a/tests/cursor.rs +++ b/tests/cursor.rs @@ -1,6 +1,6 @@ #![allow(missing_docs)] use signet_libmdbx::*; -use std::borrow::Cow; +use std::{borrow::Cow, hint::black_box}; use tempfile::tempdir; /// Convenience @@ -455,12 +455,12 @@ fn test_dup_sort_methods_work_on_dupsort_db() { cursor.first::<(), ()>().unwrap(); // These should work without error on a DUPSORT database - assert!(cursor.first_dup::<()>().is_ok()); - assert!(cursor.last_dup::<()>().is_ok()); - assert!(cursor.next_dup::<(), ()>().is_ok()); - assert!(cursor.prev_dup::<(), ()>().is_ok()); - assert!(cursor.get_both::<()>(b"key1", b"val1").is_ok()); - assert!(cursor.get_both_range::<()>(b"key1", b"val").is_ok()); + cursor.first_dup::<()>().unwrap(); + cursor.last_dup::<()>().unwrap(); + cursor.next_dup::<(), ()>().unwrap(); + cursor.prev_dup::<(), ()>().unwrap(); + cursor.get_both::<()>(b"key1", b"val1").unwrap(); + cursor.get_both_range::<()>(b"key1", b"val").unwrap(); } #[test] @@ -477,8 +477,94 @@ fn test_dup_fixed_methods_work_on_dupfixed_db() { cursor.first::<(), ()>().unwrap(); // These should work without error on a DUPFIXED database - assert!(cursor.get_multiple::<()>().is_ok()); + cursor.get_multiple::<()>().unwrap(); // next_multiple and prev_multiple may return None but shouldn't error - assert!(cursor.next_multiple::<(), ()>().is_ok()); - assert!(cursor.prev_multiple::<(), ()>().is_ok()); + cursor.next_multiple::<(), ()>().unwrap(); + cursor.prev_multiple::<(), ()>().unwrap(); +} + +#[test] +fn test_iter_exhausted_cursor_repositions() { + let dir = tempdir().unwrap(); + let env = Environment::builder().open(dir.path()).unwrap(); + + let txn = env.begin_rw_txn().unwrap(); + let db = txn.open_db(None).unwrap(); + for i in 0u8..100 { + txn.put(db.dbi(), [i], [i], WriteFlags::empty()).unwrap(); + } + txn.commit().unwrap(); + + let txn = env.begin_ro_txn().unwrap(); + let db = txn.open_db(None).unwrap(); + let mut cursor = txn.cursor(db).unwrap(); + + // Loop 1: iterate through all items + let count1 = cursor.iter::<[u8; 1], [u8; 1]>().count(); + assert_eq!(count1, 100); + + // After exhaustion, is_eof should be true + assert!(cursor.is_eof()); + + // Loop 2: iter() should reposition and iterate all items again + let count2 = cursor.iter::<[u8; 1], [u8; 1]>().count(); + assert_eq!(count2, 100); + + // Total count should be 200 + assert_eq!(count1 + count2, 200); +} + +#[test] +fn test_iter_benchmark_pattern() { + // This test mirrors the exact logic of bench_get_seq_iter + let dir = tempdir().unwrap(); + let env = Environment::builder().open(dir.path()).unwrap(); + + let n = 100u32; + + let txn = env.begin_rw_txn().unwrap(); + let db = txn.open_db(None).unwrap(); + for i in 0..n { + let key = format!("key{i}"); + let data = format!("data{i}"); + txn.put(db.dbi(), key.as_bytes(), data.as_bytes(), WriteFlags::empty()).unwrap(); + } + txn.commit().unwrap(); + + // Setup like benchmark: transaction and db outside the "iteration" + let txn = env.begin_ro_txn().unwrap(); + let db = txn.open_db(None).unwrap(); + + // Run the benchmark closure multiple times to match criterion behavior + for _ in 0..3 { + let mut cursor = txn.cursor(db).unwrap(); + let mut count = 0u32; + + // Loop 1: iterate with map(Result::unwrap), using ObjectLength like benchmark + for (key_len, data_len) in cursor.iter::().map(Result::unwrap) { + black_box(*key_len + *data_len); + count += 1; + } + + // Loop 2: iterate with filter_map(Result::ok) + for (key_len, data_len) in + cursor.iter::().filter_map(Result::ok) + { + black_box(*key_len + *data_len); + count += 1; + } + + // Loop 3: internal iterate function (doesn't affect count) + fn iterate(cursor: &mut Cursor) -> ReadResult<()> { + for result in cursor.iter::() { + let (key_len, data_len) = result?; + black_box(*key_len + *data_len); + } + Ok(()) + } + iterate(&mut cursor).unwrap(); + + // With the fix, both loops should iterate all items + assert_eq!(count, n * 2); + } } diff --git a/tests/environment.rs b/tests/environment.rs index cf3cf58..c2b9fe0 100644 --- a/tests/environment.rs +++ b/tests/environment.rs @@ -11,10 +11,10 @@ fn test_open() { assert!(Environment::builder().set_flags(Mode::ReadOnly.into()).open(dir.path()).is_err()); // opening non-existent env should succeed - assert!(Environment::builder().open(dir.path()).is_ok()); + Environment::builder().open(dir.path()).unwrap(); // opening env with read-only should succeed - assert!(Environment::builder().set_flags(Mode::ReadOnly.into()).open(dir.path()).is_ok()); + Environment::builder().set_flags(Mode::ReadOnly.into()).open(dir.path()).unwrap(); } #[test] @@ -25,16 +25,16 @@ fn test_begin_txn() { // writable environment let env = Environment::builder().open(dir.path()).unwrap(); - assert!(env.begin_rw_txn().is_ok()); - assert!(env.begin_ro_txn().is_ok()); + env.begin_rw_txn().unwrap(); + env.begin_ro_txn().unwrap(); } { // read-only environment let env = Environment::builder().set_flags(Mode::ReadOnly.into()).open(dir.path()).unwrap(); - assert!(env.begin_rw_txn().is_err()); - assert!(env.begin_ro_txn().is_ok()); + env.begin_rw_txn().unwrap_err(); + env.begin_ro_txn().unwrap(); } } @@ -44,8 +44,8 @@ fn test_open_db() { let env = Environment::builder().set_max_dbs(1).open(dir.path()).unwrap(); let txn = env.begin_ro_txn().unwrap(); - assert!(txn.open_db(None).is_ok()); - assert!(txn.open_db(Some("testdb")).is_err()); + txn.open_db(None).unwrap(); + txn.open_db(Some("testdb")).unwrap_err(); } #[test] @@ -54,9 +54,9 @@ fn test_create_db() { let env = Environment::builder().set_max_dbs(11).open(dir.path()).unwrap(); let txn = env.begin_rw_txn().unwrap(); - assert!(txn.open_db(Some("testdb")).is_err()); - assert!(txn.create_db(Some("testdb"), DatabaseFlags::empty()).is_ok()); - assert!(txn.open_db(Some("testdb")).is_ok()) + txn.open_db(Some("testdb")).unwrap_err(); + txn.create_db(Some("testdb"), DatabaseFlags::empty()).unwrap(); + txn.open_db(Some("testdb")).unwrap(); } #[test]