### Configure Static Library Installation Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Handles installation logic for the static library, accounting for CMake version differences in handling library components. ```cmake if(MDBX_INSTALL_STATIC) if(CMAKE_VERSION VERSION_LESS 3.12) install( TARGETS mdbx-static EXPORT libmdbx LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) else() install( TARGETS mdbx-static EXPORT libmdbx LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel NAMELINK_COMPONENT devel OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) endif() endif(MDBX_INSTALL_STATIC) ``` -------------------------------- ### Configure Tools and Man Pages Installation Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Installs libmdbx command-line utilities and associated man pages if the build options are enabled. ```cmake if(MDBX_BUILD_TOOLS) if(NOT DEFINED MDBX_TOOLS_INSTALL_DESTINATION) set(MDBX_TOOLS_INSTALL_DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() install(TARGETS mdbx_chk mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_drop mdbx_defrag RUNTIME DESTINATION ${MDBX_TOOLS_INSTALL_DESTINATION} COMPONENT runtime) if(MDBX_INSTALL_MANPAGES) if(NOT DEFINED MDBX_MAN_INSTALL_DESTINATION) set(MDBX_MAN_INSTALL_DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif() install( FILES "${MDBX_SOURCE_DIR}/man1/mdbx_chk.1" "${MDBX_SOURCE_DIR}/man1/mdbx_stat.1" "${MDBX_SOURCE_DIR}/man1/mdbx_copy.1" "${MDBX_SOURCE_DIR}/man1/mdbx_dump.1" "${MDBX_SOURCE_DIR}/man1/mdbx_load.1" "${MDBX_SOURCE_DIR}/man1/mdbx_drop.1" DESTINATION ${MDBX_MAN_INSTALL_DESTINATION} COMPONENT doc) endif() endif(MDBX_BUILD_TOOLS) ``` -------------------------------- ### Define library setup macro Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt A macro to handle platform-specific library linking, including threading and system-specific dependencies. ```cmake macro(libmdbx_setup_libs TARGET MODE) if(CMAKE_VERSION VERSION_LESS 3.1) target_link_libraries(${TARGET} ${MODE} ${CMAKE_THREAD_LIBS_INIT}) else() target_link_libraries(${TARGET} ${MODE} Threads::Threads) endif() if(WIN32) target_link_libraries( ${TARGET} ${MODE} ntdll user32 kernel32 advapi32 ole32) if(MDBX_NTDLL_EXTRA_IMPLIB AND MDBX_WITHOUT_MSVC_CRT) target_link_libraries(${TARGET} ${MODE} ntdll_extra) endif() elseif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" OR ${CMAKE_SYSTEM_NAME} STREQUAL "Solaris") target_link_libraries(${TARGET} ${MODE} kstat) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") target_link_libraries(${TARGET} ${MODE} log) endif() if(LIBCXX_FILESYSTEM AND MDBX_BUILD_CXX) if(CMAKE_COMPILER_IS_ELBRUSCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 1.25.23 AND NOT CMAKE_VERSION VERSION_LESS 3.13) target_link_options(${TARGET} PUBLIC "-Wl,--allow-multiple-definition") endif() target_link_libraries(${TARGET} PUBLIC ${LIBCXX_FILESYSTEM}) endif() endmacro() ``` -------------------------------- ### Start and Manage MDBX Transactions Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates starting read-write and read-only transactions, opening a database, performing a put operation, committing the transaction, and reading data. Read-only transactions do not block writers. ```c #include "mdbx.h" #include #include int transaction_examples(MDBX_env *env) { MDBX_txn *txn = NULL; MDBX_txn *nested_txn = NULL; MDBX_dbi dbi; int rc; // Start a read-write transaction rc = mdbx_txn_begin(env, NULL, 0, &txn); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_txn_begin failed: %s\n", mdbx_strerror(rc)); return rc; } // Open/create database within transaction rc = mdbx_dbi_open(txn, NULL, MDBX_CREATE, &dbi); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); return rc; } // Perform operations... MDBX_val key = {.iov_base = "mykey", .iov_len = 5}; MDBX_val data = {.iov_base = "myvalue", .iov_len = 7}; mdbx_put(txn, dbi, &key, &data, 0); // Commit transaction rc = mdbx_txn_commit(txn); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_txn_commit failed: %s\n", mdbx_strerror(rc)); } // Read-only transaction example rc = mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); if (rc == MDBX_SUCCESS) { // Read operations... rc = mdbx_get(txn, dbi, &key, &data); if (rc == MDBX_SUCCESS) { printf("Value: %.*s\n", (int)data.iov_len, (char*)data.iov_base); } mdbx_txn_abort(txn); // or mdbx_txn_commit() - same for read-only } return MDBX_SUCCESS; } ``` -------------------------------- ### C Example: Get MDBX Environment Statistics Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Retrieves and prints detailed statistics about the MDBX database environment, including page size, tree depth, page counts, total entries, map size, and reader information. ```c #include "mdbx.h" #include void print_database_stats(MDBX_env *env) { MDBX_stat stat; MDBX_envinfo info; int rc; rc = mdbx_env_stat_ex(env, NULL, &stat, sizeof(stat)); if (rc == MDBX_SUCCESS) { printf("Database Statistics:\n"); printf(" Page size: %u bytes\n", stat.ms_psize); printf(" B-tree depth: %u\n", stat.ms_depth); printf(" Branch pages: %llu\n", (unsigned long long)stat.ms_branch_pages); printf(" Leaf pages: %llu\n", (unsigned long long)stat.ms_leaf_pages); printf(" Overflow pages: %llu\n", (unsigned long long)stat.ms_overflow_pages); printf(" Total entries: %llu\n", (unsigned long long)stat.ms_entries); } rc = mdbx_env_info_ex(env, NULL, &info, sizeof(info)); if (rc == MDBX_SUCCESS) { printf("\nEnvironment Info:\n"); printf(" Map size: %llu bytes\n", (unsigned long long)info.mi_mapsize); printf(" Last page number: %llu\n", (unsigned long long)info.mi_last_pgno); printf(" Last txn ID: %llu\n", (unsigned long long)info.mi_recent_txnid); printf(" Max readers: %u\n", info.mi_maxreaders); printf(" Current readers: %u\n", info.mi_numreaders); printf("\nGeometry:\n"); printf(" Size lower: %llu\n", (unsigned long long)info.mi_geo.lower); printf(" Size current: %llu\n", (unsigned long long)info.mi_geo.current); printf(" Size upper: %llu\n", (unsigned long long)info.mi_geo.upper); } } ``` -------------------------------- ### Open libmdbx Environment Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Opens a database environment at a specified path. Includes examples for standard read-write access and read-only mode. ```c #include "mdbx.h" #include #include int main(void) { MDBX_env *env = NULL; int rc; rc = mdbx_env_create(&env); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_create: %s\n", mdbx_strerror(rc)); return EXIT_FAILURE; } // Open with common flags: // MDBX_NOSUBDIR: Use single file instead of directory // MDBX_LIFORECLAIM: LIFO recycling for better write-back cache efficiency rc = mdbx_env_open(env, "./mydb.mdbx", MDBX_NOSUBDIR | MDBX_LIFORECLAIM, 0664); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_open failed: (%d) %s\n", rc, mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } printf("Database opened successfully\n"); // Use the environment... mdbx_env_close(env); return EXIT_SUCCESS; } // Opening read-only database: int open_readonly(void) { MDBX_env *env = NULL; mdbx_env_create(&env); int rc = mdbx_env_open(env, "./mydb.mdbx", MDBX_RDONLY | MDBX_NOSUBDIR, 0); if (rc == MDBX_SUCCESS) { printf("Opened database in read-only mode\n"); mdbx_env_close(env); } return rc; } ``` -------------------------------- ### Configure Shared Library Installation Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Sets the installation destination for shared libraries based on the operating system and handles version-specific install commands for CMake versions before and after 3.12. ```cmake if(NOT DEFINED MDBX_DLL_INSTALL_DESTINATION) if(WIN32) set(MDBX_DLL_INSTALL_DESTINATION ${CMAKE_INSTALL_BINDIR}) else() set(MDBX_DLL_INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() endif() if(MDBX_BUILD_SHARED_LIBRARY) if(CMAKE_VERSION VERSION_LESS 3.12) install( TARGETS mdbx EXPORT libmdbx LIBRARY DESTINATION ${MDBX_DLL_INSTALL_DESTINATION} COMPONENT runtime ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) else() install( TARGETS mdbx EXPORT libmdbx LIBRARY DESTINATION ${MDBX_DLL_INSTALL_DESTINATION} COMPONENT runtime NAMELINK_COMPONENT devel OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel) endif() endif(MDBX_BUILD_SHARED_LIBRARY) ``` -------------------------------- ### Define target setup macro Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt A macro to configure standard compiler properties, optimization flags, and visibility settings for a given target. ```cmake macro(target_setup_options TARGET) if(DEFINED INTERPROCEDURAL_OPTIMIZATION) set_target_properties(${TARGET} PROPERTIES INTERPROCEDURAL_OPTIMIZATION $) endif() if(NOT C_FALLBACK_GNU11 AND NOT C_FALLBACK_11) set_target_properties(${TARGET} PROPERTIES C_STANDARD ${MDBX_C_STANDARD} C_STANDARD_REQUIRED ON) endif() if(MDBX_BUILD_CXX) if(NOT CXX_FALLBACK_GNU11 AND NOT CXX_FALLBACK_11) set_target_properties(${TARGET} PROPERTIES CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON) endif() if(MSVC AND NOT MSVC_VERSION LESS 1910) target_compile_options(${TARGET} INTERFACE "/Zc:__cplusplus") endif() endif() if(CC_HAS_FASTMATH AND NOT (CMAKE_COMPILER_IS_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10)) target_compile_options(${TARGET} PRIVATE "-ffast-math") endif() if(CC_HAS_VISIBILITY) target_compile_options(${TARGET} PRIVATE "-fvisibility=hidden") endif() if(BUILD_FOR_NATIVE_CPU AND CC_HAS_ARCH_NATIVE) target_compile_options(${TARGET} PRIVATE "-march=native") endif() endmacro() ``` -------------------------------- ### Build static library target Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Configures the static library target, including compilation definitions, setup options, and include directories. ```cmake if(MDBX_INSTALL_STATIC) add_library(mdbx-static STATIC ${LIBMDBX_SOURCES}) else() add_library(mdbx-static STATIC EXCLUDE_FROM_ALL ${LIBMDBX_SOURCES}) endif() set_target_properties(mdbx-static PROPERTIES PUBLIC_HEADER "${LIBMDBX_PUBLIC_HEADERS}") target_compile_definitions(mdbx-static PRIVATE MDBX_BUILD_SHARED_LIBRARY=0) target_setup_options(mdbx-static) libmdbx_setup_libs(mdbx-static INTERFACE) if(MDBX_BUILD_SHARED_LIBRARY) set_target_properties(mdbx-static PROPERTIES OUTPUT_NAME mdbx-static) set(MDBX_LIBRARY mdbx) else() set_target_properties(mdbx-static PROPERTIES OUTPUT_NAME mdbx) set(MDBX_LIBRARY mdbx-static) endif() target_include_directories(mdbx-static INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") ``` -------------------------------- ### C Example: Working with Sorted Duplicates in MDBX Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates how to create a DUPSORT table, insert multiple values for a key, count values, iterate through them, and delete specific or all values for a key. ```c #include "mdbx.h" #include #include int dupsort_example(MDBX_env *env) { MDBX_txn *txn; MDBX_dbi dbi; MDBX_cursor *cursor; MDBX_val key, data; int rc; // Create DUPSORT table mdbx_txn_begin(env, NULL, 0, &txn); rc = mdbx_dbi_open(txn, "tags", MDBX_CREATE | MDBX_DUPSORT, &dbi); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); return rc; } // Insert multiple values for same key key.iov_base = "article:42"; key.iov_len = 10; const char *tags[] = {"technology", "programming", "database", "performance"}; for (int i = 0; i < 4; i++) { data.iov_base = (void*)tags[i]; data.iov_len = strlen(tags[i]); mdbx_put(txn, dbi, &key, &data, 0); } // Count values for a key mdbx_cursor_open(txn, dbi, &cursor); key.iov_base = "article:42"; key.iov_len = 10; rc = mdbx_cursor_get(cursor, &key, &data, MDBX_SET); if (rc == MDBX_SUCCESS) { size_t count; mdbx_cursor_count(cursor, &count); printf("Article has %zu tags\n", count); // Iterate all values for this key printf("Tags: "); rc = mdbx_cursor_get(cursor, &key, &data, MDBX_FIRST_DUP); while (rc == MDBX_SUCCESS) { printf("%.*s ", (int)data.iov_len, (char*)data.iov_base); rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT_DUP); } printf("\n"); } // Delete specific value data.iov_base = "programming"; data.iov_len = 11; mdbx_del(txn, dbi, &key, &data); // Deletes only this tag // Delete all values for key // mdbx_del(txn, dbi, &key, NULL); // Would delete all tags mdbx_cursor_close(cursor); return mdbx_txn_commit(txn); } ``` -------------------------------- ### Position and Retrieve Data with mdbx_cursor_get Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates various ways to position a cursor and retrieve data using flags like MDBX_FIRST, MDBX_LAST, MDBX_SET, and MDBX_SET_RANGE. Includes an example of iterating through a prefix range. ```c #include "mdbx.h" #include #include int cursor_positioning(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn; MDBX_cursor *cursor; MDBX_val key, data; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); mdbx_cursor_open(txn, dbi, &cursor); // Go to first entry rc = mdbx_cursor_get(cursor, &key, &data, MDBX_FIRST); if (rc == MDBX_SUCCESS) { printf("First: %.*s\n", (int)key.iov_len, (char*)key.iov_base); } // Go to last entry rc = mdbx_cursor_get(cursor, &key, &data, MDBX_LAST); if (rc == MDBX_SUCCESS) { printf("Last: %.*s\n", (int)key.iov_len, (char*)key.iov_base); } // Find exact key key.iov_base = "user:1001"; key.iov_len = 9; rc = mdbx_cursor_get(cursor, &key, &data, MDBX_SET); if (rc == MDBX_SUCCESS) { printf("Found exact key\n"); } // Find key >= given key (range query start) key.iov_base = "user:"; key.iov_len = 5; rc = mdbx_cursor_get(cursor, &key, &data, MDBX_SET_RANGE); if (rc == MDBX_SUCCESS) { printf("First user key: %.*s\n", (int)key.iov_len, (char*)key.iov_base); // Iterate prefix range while (rc == MDBX_SUCCESS) { if (key.iov_len < 5 || memcmp(key.iov_base, "user:", 5) != 0) break; // Exit when prefix no longer matches printf(" %.*s = %.*s\n", (int)key.iov_len, (char*)key.iov_base, (int)data.iov_len, (char*)data.iov_base); rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT); } } mdbx_cursor_close(cursor); mdbx_txn_abort(txn); return MDBX_SUCCESS; } ``` -------------------------------- ### Configure libmdbx build targets with CMake Source: https://github.com/dqdkfa/libmdbx.git/blob/master/ut_and_examples/CMakeLists.txt Defines executable targets for C and C++ examples, sets standard requirements, and configures test execution. ```cmake # Copyright (c) 2020-2026 Леонид Юрьев aka Leonid Yuriev ############################################### # SPDX-License-Identifier: Apache-2.0 # project(mdbx_ut_and_examples) if(NOT DEFINED MDBX_LIBRARY) set(MDBX_LIBRARY mdbx) endif() if(MDBX_BUILD_CXX AND CMAKE_CXX_COMPILER_LOADED AND NOT MDBX_CXX_STANDARD LESS 17) add_executable(mdbx_modern_example example-mdbx.c++) set_target_properties(mdbx_modern_example PROPERTIES CXX_STANDARD ${MDBX_CXX_STANDARD} CXX_STANDARD_REQUIRED ON) target_link_libraries(mdbx_modern_example ${MDBX_LIBRARY}) if(DEFINED INTERPROCEDURAL_OPTIMIZATION) set_target_properties(mdbx_modern_example PROPERTIES INTERPROCEDURAL_OPTIMIZATION $) endif() else() message(NOTICE "The C++ example will be skipped, since C++17 standard is unavailable or C++ API of libmdbx was disabled.") set(MDBX_BUILD_CXX FALSE) endif() add_executable(mdbx_legacy_example example-mdbx.c) target_link_libraries(mdbx_legacy_example ${MDBX_LIBRARY}) if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CROSSCOMPILING_EMULATOR) message(NOTICE "No emulator to run cross-compiled tests") add_test(NAME fake_since_no_crosscompiling_emulator COMMAND ${CMAKE_COMMAND} -E echo "No emulator to run cross-compiled tests") else() add_test(NAME c_api COMMAND mdbx_legacy_example) if(MDBX_BUILD_CXX) add_test(NAME c++_api COMMAND mdbx_modern_example) endif() endif() if(UNIX) add_executable(pcrf_simulator pcrf/pcrf_simulator.c) target_link_libraries(pcrf_simulator ${MDBX_LIBRARY}) endif() ``` -------------------------------- ### Store Data with mdbx_cursor_put Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Stores data using a cursor, offering more control than mdbx_put. This example shows append-optimized inserts for sequential keys and updating data at the current cursor position. ```c #include "mdbx.h" #include int cursor_put_examples(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn; MDBX_cursor *cursor; MDBX_val key, data; int rc; mdbx_txn_begin(env, NULL, 0, &txn); mdbx_cursor_open(txn, dbi, &cursor); // Append-optimized insert (for sequential keys) for (int i = 1000; i < 1010; i++) { char kbuf[32], vbuf[64]; snprintf(kbuf, sizeof(kbuf), "seq:%06d", i); snprintf(vbuf, sizeof(vbuf), "Sequential value %d", i); key.iov_base = kbuf; key.iov_len = strlen(kbuf); data.iov_base = vbuf; data.iov_len = strlen(vbuf); // MDBX_APPEND: optimized for sequential ascending keys rc = mdbx_cursor_put(cursor, &key, &data, MDBX_APPEND); if (rc != MDBX_SUCCESS && rc != MDBX_EKEYMISMATCH) { fprintf(stderr, "Append failed: %s\n", mdbx_strerror(rc)); } } // Update current position key.iov_base = "seq:001005"; key.iov_len = 10; mdbx_cursor_get(cursor, &key, &data, MDBX_SET); data.iov_base = "Updated value at position"; data.iov_len = 25; rc = mdbx_cursor_put(cursor, &key, &data, MDBX_CURRENT); mdbx_cursor_close(cursor); return mdbx_txn_commit(txn); } ``` -------------------------------- ### Open and Iterate Database with mdbx_cursor_open Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Opens a cursor for navigating a database within a read-only transaction. Cursors must be closed before the transaction ends. This example iterates through all key-value pairs. ```c #include "mdbx.h" #include int cursor_iteration(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn; MDBX_cursor *cursor; MDBX_val key, data; int rc; rc = mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); if (rc != MDBX_SUCCESS) return rc; rc = mdbx_cursor_open(txn, dbi, &cursor); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); return rc; } // Iterate all key-value pairs printf("Database contents:\n"); while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) { printf(" Key: %.*s => Value: %.*s\n", (int)key.iov_len, (char*)key.iov_base, (int)data.iov_len, (char*)data.iov_base); } if (rc != MDBX_NOTFOUND) { fprintf(stderr, "Cursor error: %s\n", mdbx_strerror(rc)); } mdbx_cursor_close(cursor); mdbx_txn_abort(txn); return MDBX_SUCCESS; } ``` -------------------------------- ### Conditional Subdirectory Inclusion Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Adds the tests and examples subdirectory if enabled. ```cmake if(MDBX_ENABLE_TESTS) add_subdirectory(ut_and_examples) endif() ``` -------------------------------- ### Handle Errors with C API Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Provides examples for retrieving human-readable error descriptions using mdbx_strerror and thread-safe alternatives. Use these to interpret return codes from MDBX functions. ```c #include "mdbx.h" #include void handle_mdbx_error(int rc, const char *operation) { if (rc != MDBX_SUCCESS) { // Get error description const char *errmsg = mdbx_strerror(rc); fprintf(stderr, "%s failed: (%d) %s\n", operation, rc, errmsg); // Handle specific errors switch (rc) { case MDBX_KEYEXIST: fprintf(stderr, " -> Key already exists\n"); break; case MDBX_NOTFOUND: fprintf(stderr, " -> Key not found\n"); break; case MDBX_MAP_FULL: fprintf(stderr, " -> Database is full, increase mapsize\n"); break; case MDBX_TXN_FULL: fprintf(stderr, " -> Transaction has too many dirty pages\n"); break; case MDBX_CORRUPTED: fprintf(stderr, " -> Database corruption detected!\n"); break; case MDBX_BUSY: fprintf(stderr, " -> Database is busy (another writer?)\n"); break; default: break; } } } // Thread-safe error string void thread_safe_error_handling(int rc) { char buffer[256]; const char *msg = mdbx_strerror_r(rc, buffer, sizeof(buffer)); printf("Error: %s\n", msg); } ``` -------------------------------- ### Manage Buffers and Slices in C++ Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Shows how to create buffers from various encodings and perform zero-copy wrapping of numeric types. Useful for handling keys and values with specific formatting requirements. ```cpp #include #include void buffer_examples() { using buffer = mdbx::buffer; // Create buffers from various sources buffer b1("Hello, World!"); buffer b2 = buffer::hex("48656c6c6f"); // Hex encoded buffer b3 = buffer::base64("SGVsbG8="); // Base64 encoded // Numeric keys auto key_u64 = buffer::key_from_u64(12345); auto key_double = buffer::key_from_double(3.14159); auto key_json = buffer::key_from_jsonInteger(42); // Slice wrapping for zero-copy uint64_t numeric_id = 0xDEADBEEF; auto slice = mdbx::slice::wrap(numeric_id); // Convert to string representations std::cout << "Hex: " << b1.as_hex_string() << std::endl; std::cout << "Base58: " << mdbx::to_base58(b1).as_string() << std::endl; std::cout << "Base64: " << mdbx::to_base64(b1).as_string() << std::endl; } ``` -------------------------------- ### Perform Basic Database Operations in C++ Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates environment creation, write transactions with map creation, and read transactions using cursors. Requires linking against libmdbx and including mdbx.h++. ```cpp #include #include #include int main() { try { // Remove existing database for clean start mdbx::env::remove("./example.mdbx"); // Create environment with builder pattern auto operate_params = mdbx::env::operate_parameters(); operate_params.max_maps = 10; mdbx::env_managed env("./example.mdbx", mdbx::env_managed::create_parameters(), operate_params); // Write transaction with automatic commit/abort { auto txn = env.start_write(); auto map = txn.create_map("users", mdbx::key_mode::usual, mdbx::value_mode::single); // Insert data using slices txn.insert(map, mdbx::slice("user:1"), mdbx::slice("Alice")); txn.insert(map, mdbx::slice("user:2"), mdbx::slice("Bob")); txn.upsert(map, mdbx::slice("user:3"), mdbx::slice("Charlie")); txn.commit(); } // Read transaction { auto txn = env.start_read(); auto map = txn.open_map("users"); // Get single value auto result = txn.get(map, mdbx::slice("user:1")); if (result) { std::cout << "Found: " << result.value.as_string() << std::endl; } // Cursor iteration auto cursor = txn.open_cursor(map); cursor.to_first(); while (!cursor.eof()) { auto pair = cursor.current(); std::cout << pair.key.as_string() << " => " << pair.value.as_string() << std::endl; cursor.to_next(false); } } std::cout << "Success!" << std::endl; return 0; } catch (const mdbx::exception &e) { std::cerr << "MDBX error: " << e.what() << std::endl; return 1; } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } } ``` -------------------------------- ### Full Database Application in C Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates the complete lifecycle of a libmdbx database, from environment creation to cleanup. Uses a macro-based error checking pattern to ensure resources are released on failure. ```c #include "mdbx.h" #include #include #include #define CHECK(rc, msg) do { \ if ((rc) != MDBX_SUCCESS) { \ fprintf(stderr, "%s: %s\n", (msg), mdbx_strerror(rc)); \ goto cleanup; \ } \ } while(0) int main(void) { MDBX_env *env = NULL; MDBX_txn *txn = NULL; MDBX_dbi dbi = 0; MDBX_cursor *cursor = NULL; int rc; // 1. Create and configure environment rc = mdbx_env_create(&env); CHECK(rc, "mdbx_env_create"); rc = mdbx_env_set_geometry(env, 0, 0, 64*1024*1024, -1, -1, -1); CHECK(rc, "mdbx_env_set_geometry"); // 2. Delete old database and open fresh mdbx_env_delete("./demo.mdbx", MDBX_ENV_JUST_DELETE); rc = mdbx_env_open(env, "./demo.mdbx", MDBX_NOSUBDIR | MDBX_LIFORECLAIM, 0664); CHECK(rc, "mdbx_env_open"); // 3. Write some data rc = mdbx_txn_begin(env, NULL, 0, &txn); CHECK(rc, "mdbx_txn_begin (write)"); rc = mdbx_dbi_open(txn, NULL, 0, &dbi); CHECK(rc, "mdbx_dbi_open"); // Insert sample records for (int i = 1; i <= 5; i++) { char key[32], value[64]; snprintf(key, sizeof(key), "record:%03d", i); snprintf(value, sizeof(value), "Data for record %d - libmdbx demo", i); MDBX_val k = {.iov_base = key, .iov_len = strlen(key)}; MDBX_val v = {.iov_base = value, .iov_len = strlen(value)}; rc = mdbx_put(txn, dbi, &k, &v, 0); CHECK(rc, "mdbx_put"); } rc = mdbx_txn_commit(txn); txn = NULL; CHECK(rc, "mdbx_txn_commit"); printf("Inserted 5 records\n"); // 4. Read and display all data rc = mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); CHECK(rc, "mdbx_txn_begin (read)"); rc = mdbx_cursor_open(txn, dbi, &cursor); CHECK(rc, "mdbx_cursor_open"); printf("\nDatabase contents:\n"); printf("==================\n"); MDBX_val key, data; while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) { printf(" %.*s => %.*s\n", (int)key.iov_len, (char*)key.iov_base, (int)data.iov_len, (char*)data.iov_base); } if (rc != MDBX_NOTFOUND) { CHECK(rc, "mdbx_cursor_get"); } // 5. Get database statistics MDBX_stat stat; rc = mdbx_dbi_stat(txn, dbi, &stat, sizeof(stat)); CHECK(rc, "mdbx_dbi_stat"); printf("\nStatistics:\n"); printf(" Entries: %llu\n", (unsigned long long)stat.ms_entries); printf(" Depth: %u\n", stat.ms_depth); printf(" Page size: %u bytes\n", stat.ms_psize); rc = MDBX_SUCCESS; cleanup: if (cursor) mdbx_cursor_close(cursor); if (txn) mdbx_txn_abort(txn); if (dbi) mdbx_dbi_close(env, dbi); if (env) mdbx_env_close(env); return (rc == MDBX_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE; } ``` -------------------------------- ### Create and Configure libmdbx Environment Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Initializes an MDBX_env handle and configures geometry and database limits before opening. The handle must be released with mdbx_env_close. ```c #include "mdbx.h" #include #include int main(void) { MDBX_env *env = NULL; int rc; // Create environment handle rc = mdbx_env_create(&env); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_create failed: (%d) %s\n", rc, mdbx_strerror(rc)); return EXIT_FAILURE; } // Configure environment before opening rc = mdbx_env_set_geometry(env, -1, // size_lower: default -1, // size_now: default 128ULL * 1024 * 1024, // size_upper: 128MB max -1, // growth_step: default -1, // shrink_threshold: default -1); // pagesize: default if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_set_geometry failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } // Set maximum number of named databases rc = mdbx_env_set_maxdbs(env, 10); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_set_maxdbs failed: %s\n", mdbx_strerror(rc)); } // Environment is ready for mdbx_env_open() printf("Environment created successfully\n"); mdbx_env_close(env); return EXIT_SUCCESS; } ``` -------------------------------- ### Retrieve Compiler Information Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Executes a shell command to get the compiler version or falls back to CMake variables if the command fails. ```cmake execute_process( COMMAND sh -c "${CMAKE_C_COMPILER} --version | head -1" OUTPUT_VARIABLE MDBX_BUILD_COMPILER OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET RESULT_VARIABLE rc) if(rc OR NOT MDBX_BUILD_COMPILER) string(STRIP "${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}" MDBX_BUILD_COMPILER) endif() ``` -------------------------------- ### Log Build Options Source: https://github.com/dqdkfa/libmdbx.git/blob/master/CMakeLists.txt Iterates through a list of build options and logs their resolved values to the console. ```cmake set(options VERSION C_COMPILER CXX_COMPILER MDBX_BUILD_TARGET MDBX_BUILD_TYPE ${MDBX_BUILD_OPTIONS}) foreach(item IN LISTS options) if(DEFINED ${item}) set(value "${${item}}") elseif(DEFINED MDBX_${item}) set(item MDBX_${item}) set(value "${${item}}") elseif(DEFINED CMAKE_${item}) set(item CMAKE_${item}) set(value "${${item}}") else() set(value "AUTO (not pre-defined explicitly)") endif() message(STATUS "${item}: ${value}") endforeach(item) ``` -------------------------------- ### Get Environment Statistics Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Retrieves detailed statistics about the MDBX environment, including page size, tree depth, page counts, entry count, map size, and geometry. ```APIDOC ## Get Environment Statistics ### Description This section details the `mdbx_env_stat_ex` and `mdbx_env_info_ex` functions, which are used to retrieve comprehensive statistics about the MDBX database environment. These statistics include information about the database's structure, size, and usage. ### Method N/A (This is a conceptual example of API usage, not a specific HTTP endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response N/A ### Code Example (C) ```c #include "mdbx.h" #include void print_database_stats(MDBX_env *env) { MDBX_stat stat; MDBX_envinfo info; int rc; rc = mdbx_env_stat_ex(env, NULL, &stat, sizeof(stat)); if (rc == MDBX_SUCCESS) { printf("Database Statistics:\n"); printf(" Page size: %u bytes\n", stat.ms_psize); printf(" B-tree depth: %u\n", stat.ms_depth); printf(" Branch pages: %llu\n", (unsigned long long)stat.ms_branch_pages); printf(" Leaf pages: %llu\n", (unsigned long long)stat.ms_leaf_pages); printf(" Overflow pages: %llu\n", (unsigned long long)stat.ms_overflow_pages); printf(" Total entries: %llu\n", (unsigned long long)stat.ms_entries); } rc = mdbx_env_info_ex(env, NULL, &info, sizeof(info)); if (rc == MDBX_SUCCESS) { printf("\nEnvironment Info:\n"); printf(" Map size: %llu bytes\n", (unsigned long long)info.mi_mapsize); printf(" Last page number: %llu\n", (unsigned long long)info.mi_last_pgno); printf(" Last txn ID: %llu\n", (unsigned long long)info.mi_recent_txnid); printf(" Max readers: %u\n", info.mi_maxreaders); printf(" Current readers: %u\n", info.mi_numreaders); printf("\nGeometry:\n"); printf(" Size lower: %llu\n", (unsigned long long)info.mi_geo.lower); printf(" Size current: %llu\n", (unsigned long long)info.mi_geo.current); printf(" Size upper: %llu\n", (unsigned long long)info.mi_geo.upper); } } ``` ``` -------------------------------- ### Store Data with mdbx_put Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Demonstrates various ways to store key/data pairs using `mdbx_put`. Includes simple upserts, insert-only operations with `MDBX_NOOVERWRITE`, update-only with `MDBX_CURRENT`, and reserving space for large values with `MDBX_RESERVE`. ```c #include "mdbx.h" #include #include int put_examples(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn; int rc; rc = mdbx_txn_begin(env, NULL, 0, &txn); if (rc != MDBX_SUCCESS) return rc; // Simple upsert (insert or update) MDBX_val key = {.iov_base = "user:1001", .iov_len = 9}; MDBX_val data = {.iov_base = "John Doe", .iov_len = 8}; rc = mdbx_put(txn, dbi, &key, &data, MDBX_UPSERT); if (rc != MDBX_SUCCESS) { fprintf(stderr, "Upsert failed: %s\n", mdbx_strerror(rc)); mdbx_txn_abort(txn); return rc; } // Insert only (fail if key exists) MDBX_val key2 = {.iov_base = "user:1002", .iov_len = 9}; MDBX_val data2 = {.iov_base = "Jane Smith", .iov_len = 10}; rc = mdbx_put(txn, dbi, &key2, &data2, MDBX_NOOVERWRITE); if (rc == MDBX_KEYEXIST) { printf("Key already exists, not overwritten\n"); } // Update only (fail if key doesn't exist) data.iov_base = "John Updated"; data.iov_len = 12; rc = mdbx_put(txn, dbi, &key, &data, MDBX_CURRENT); if (rc == MDBX_NOTFOUND) { printf("Key not found, cannot update\n"); } // Reserve space for large value MDBX_val key3 = {.iov_base = "large_data", .iov_len = 10}; MDBX_val reserved = {.iov_base = NULL, .iov_len = 1024}; rc = mdbx_put(txn, dbi, &key3, &reserved, MDBX_RESERVE); if (rc == MDBX_SUCCESS) { // Fill the reserved space memset(reserved.iov_base, 'X', 1024); } return mdbx_txn_commit(txn); } ``` -------------------------------- ### Retrieve Data with mdbx_get Source: https://context7.com/dqdkfa/libmdbx.git/llms.txt Shows how to retrieve data associated with a key using `mdbx_get` within a read-only transaction. Includes handling for found keys, not found keys, and errors. Also demonstrates `mdbx_get_equal_or_great` for finding keys that match or are greater than a search key. ```c #include "mdbx.h" #include int get_example(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn; MDBX_val key, data; int rc; // Start read-only transaction rc = mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); if (rc != MDBX_SUCCESS) return rc; key.iov_base = "user:1001"; key.iov_len = 9; rc = mdbx_get(txn, dbi, &key, &data); switch (rc) { case MDBX_SUCCESS: printf("Found: %.*s\n", (int)data.iov_len, (char*)data.iov_base); // WARNING: data.iov_base points directly to mmap'd database // Do NOT modify it! Copy if needed. break; case MDBX_NOTFOUND: printf("Key not found\n"); break; default: fprintf(stderr, "Error: %s\n", mdbx_strerror(rc)); } mdbx_txn_abort(txn); return rc; } ``` ```c // Get with equal-or-greater semantics int get_equal_or_greater(MDBX_env *env, MDBX_dbi dbi, const char *search_key) { MDBX_txn *txn; MDBX_val key, data; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); key.iov_base = (void*)search_key; key.iov_len = strlen(search_key); // Get equal or next greater key rc = mdbx_get_equal_or_great(txn, dbi, &key, &data); if (rc == MDBX_SUCCESS) { printf("Found key: %.*s, value: %.*s\n", (int)key.iov_len, (char*)key.iov_base, (int)data.iov_len, (char*)data.iov_base); } else if (rc == MDBX_RESULT_TRUE) { printf("Exact match not found, got next: %.*s\n", (int)key.iov_len, (char*)key.iov_base); } mdbx_txn_abort(txn); return rc; } ```