### Build Legacy C Example Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Compiles the legacy C example and links the MDBX library. ```cmake add_executable(mdbx_legacy_example example-mdbx.c) target_link_libraries(mdbx_legacy_example ${MDBX_LIBRARY}) ``` -------------------------------- ### MDBX C Database Operations Example Source: https://context7.com/mithril-mine/libmdbx/llms.txt This C code demonstrates a full MDBX database lifecycle, including opening, creating tables, inserting, retrieving, iterating, and deleting data. It requires the MDBX library to be installed. ```c #include #include #include #include typedef struct { MDBX_env *env; MDBX_dbi dbi_main; MDBX_dbi dbi_index; } Database; int db_open(Database *db, const char *path) { int rc; MDBX_txn *txn = NULL; rc = mdbx_env_create(&db->env); if (rc != MDBX_SUCCESS) return rc; mdbx_env_set_maxdbs(db->env, 4); mdbx_env_set_geometry(db->env, 1024 * 1024, // 1MB min -1, 100 * 1024 * 1024, // 100MB max 1024 * 1024, // 1MB growth 2 * 1024 * 1024, // 2MB shrink threshold -1); rc = mdbx_env_open(db->env, path, MDBX_CREATE | MDBX_WRITEMAP | MDBX_LIFORECLAIM, 0664); if (rc != MDBX_SUCCESS) { mdbx_env_close(db->env); return rc; } rc = mdbx_txn_begin(db->env, NULL, MDBX_TXN_READWRITE, &txn); if (rc != MDBX_SUCCESS) { mdbx_env_close(db->env); return rc; } rc = mdbx_dbi_open(txn, "main", MDBX_CREATE, &db->dbi_main); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); mdbx_env_close(db->env); return rc; } rc = mdbx_dbi_open(txn, "index", MDBX_CREATE | MDBX_DUPSORT, &db->dbi_index); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); mdbx_env_close(db->env); return rc; } return mdbx_txn_commit(txn); } int db_put(Database *db, const char *key, const char *value) { MDBX_txn *txn = NULL; MDBX_val k, v; int rc; rc = mdbx_txn_begin(db->env, NULL, MDBX_TXN_READWRITE, &txn); if (rc != MDBX_SUCCESS) return rc; k.iov_base = (void*)key; k.iov_len = strlen(key); v.iov_base = (void*)value; v.iov_len = strlen(value); rc = mdbx_put(txn, db->dbi_main, &k, &v, MDBX_UPSERT); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); return rc; } return mdbx_txn_commit(txn); } char* db_get(Database *db, const char *key) { MDBX_txn *txn = NULL; MDBX_val k, v; char *result = NULL; int rc; rc = mdbx_txn_begin(db->env, NULL, MDBX_TXN_RDONLY, &txn); if (rc != MDBX_SUCCESS) return NULL; k.iov_base = (void*)key; k.iov_len = strlen(key); rc = mdbx_get(txn, db->dbi_main, &k, &v); if (rc == MDBX_SUCCESS) { result = malloc(v.iov_len + 1); if (result) { memcpy(result, v.iov_base, v.iov_len); result[v.iov_len] = '\0'; } } mdbx_txn_abort(txn); return result; } int db_delete(Database *db, const char *key) { MDBX_txn *txn = NULL; MDBX_val k; int rc; rc = mdbx_txn_begin(db->env, NULL, MDBX_TXN_READWRITE, &txn); if (rc != MDBX_SUCCESS) return rc; k.iov_base = (void*)key; k.iov_len = strlen(key); rc = mdbx_del(txn, db->dbi_main, &k, NULL); if (rc != MDBX_SUCCESS && rc != MDBX_NOTFOUND) { mdbx_txn_abort(txn); return rc; } return mdbx_txn_commit(txn); } void db_iterate(Database *db) { MDBX_txn *txn = NULL; MDBX_cursor *cursor = NULL; MDBX_val k, v; int rc; rc = mdbx_txn_begin(db->env, NULL, MDBX_TXN_RDONLY, &txn); if (rc != MDBX_SUCCESS) return; rc = mdbx_cursor_open(txn, db->dbi_main, &cursor); if (rc != MDBX_SUCCESS) { mdbx_txn_abort(txn); return; } printf("Database contents:\n"); rc = mdbx_cursor_get(cursor, &k, &v, MDBX_FIRST); while (rc == MDBX_SUCCESS) { printf(" '%.*s' = '%.*s'\n", (int)k.iov_len, (char*)k.iov_base, (int)v.iov_len, (char*)v.iov_base); rc = mdbx_cursor_get(cursor, &k, &v, MDBX_NEXT); } mdbx_cursor_close(cursor); mdbx_txn_abort(txn); } void db_close(Database *db) { mdbx_env_close(db->env); } int main() { Database db = {0}; char *value; if (db_open(&db, "./example.mdbx") != MDBX_SUCCESS) { fprintf(stderr, "Failed to open database\n"); return 1; } // Insert data db_put(&db, "user:1", "{\"name\":\"Alice\",\"age\":30}"); db_put(&db, "user:2", "{\"name\":\"Bob\",\"age\":25}"); db_put(&db, "config:theme", "dark"); // Retrieve data value = db_get(&db, "user:1"); if (value) { printf("user:1 = %s\n", value); free(value); } // List all entries db_iterate(&db); // Delete db_delete(&db, "user:2"); db_close(&db); return 0; } ``` -------------------------------- ### Install MDBX Manpages Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs manpages for MDBX tools if MDBX_INSTALL_MANPAGES is enabled. The destination is configurable. ```cmake 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) ``` -------------------------------- ### Install MDBX Tools Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs various MDBX command-line tools. The runtime destination is configurable. ```cmake install(TARGETS mdbx_chk mdbx_stat mdbx_copy mdbx_dump mdbx_load mdbx_drop mdbx_defrag RUNTIME DESTINATION ${MDBX_TOOLS_INSTALL_DESTINATION} COMPONENT runtime) ``` -------------------------------- ### Build Modern C++ Example Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Compiles the modern C++ example if C++17 is available and the C++ API is enabled. Sets C++ standard and links the MDBX library. ```cmake 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}) ``` -------------------------------- ### Project and Subproject Setup Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Configures the main project or subproject build. Enables C language and sets up Apple-specific build targets if necessary. ```cmake if(DEFINED PROJECT_NAME) option(MDBX_FORCE_BUILD_AS_MAIN_PROJECT "Force libmdbx to full control build options even it added as a subdirectory to your project." OFF) endif() if(DEFINED PROJECT_NAME AND NOT MDBX_FORCE_BUILD_AS_MAIN_PROJECT) set(SUBPROJECT ON) set(NOT_SUBPROJECT OFF) enable_language(C) else() set(SUBPROJECT OFF) set(NOT_SUBPROJECT ON) # Setup Apple stuff which should be set prior to the first project() or enable_language() if(APPLE) # Enable universal binaries for macOS (target arm64 and x86_64) if(NOT DEFINED CMAKE_OSX_ARCHITECTURES) set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") endif() # Set the minimum macOS deployment target if not already defined if(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET) set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0") endif() endif() project(libmdbx C) endif() ``` -------------------------------- ### Open and Manage MDBX Databases Source: https://context7.com/mithril-mine/libmdbx/llms.txt Shows how to open default, named, DUPSORT, INTEGERKEY, and DUPFIXED databases using mdbx_dbi_open. Includes examples of inserting data with different configurations. ```c #include #include #include #include void open_various_tables(MDBX_env *env) { MDBX_txn *txn = NULL; MDBX_dbi dbi_default, dbi_dupsort, dbi_intkey, dbi_custom; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_READWRITE, &txn); // Open unnamed (default) database rc = mdbx_dbi_open(txn, NULL, MDBX_CREATE, &dbi_default); if (rc == MDBX_SUCCESS) { printf("Opened default database\n"); } // Open named database with sorted duplicates rc = mdbx_dbi_open(txn, "tags", MDBX_CREATE | MDBX_DUPSORT, &dbi_dupsort); if (rc == MDBX_SUCCESS) { printf("Opened 'tags' with DUPSORT\n"); // Insert multiple values for same key MDBX_val key = {.iov_base = "article:1", .iov_len = 9}; MDBX_val val1 = {.iov_base = "tech", .iov_len = 4}; MDBX_val val2 = {.iov_base = "database", .iov_len = 8}; MDBX_val val3 = {.iov_base = "nosql", .iov_len = 5}; mdbx_put(txn, dbi_dupsort, &key, &val1, 0); mdbx_put(txn, dbi_dupsort, &key, &val2, 0); mdbx_put(txn, dbi_dupsort, &key, &val3, 0); printf("Added 3 tags to article:1\n"); } // Open database with integer keys (native byte order) rc = mdbx_dbi_open(txn, "timestamps", MDBX_CREATE | MDBX_INTEGERKEY, &dbi_intkey); if (rc == MDBX_SUCCESS) { printf("Opened 'timestamps' with INTEGERKEY\n"); // Insert with integer key uint64_t ts = 1700000000; MDBX_val key = {.iov_base = &ts, .iov_len = sizeof(ts)}; MDBX_val data = {.iov_base = "event_data", .iov_len = 10}; mdbx_put(txn, dbi_intkey, &key, &data, 0); } // Open with DUPFIXED for fixed-size duplicate values rc = mdbx_dbi_open(txn, "user_ids", MDBX_CREATE | MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP, &dbi_custom); if (rc == MDBX_SUCCESS) { printf("Opened 'user_ids' for efficient integer sets\n"); } mdbx_txn_commit(txn); } ``` -------------------------------- ### Install MDBX Static Library (CMake < 3.12) Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs the MDBX static library, its export set, and headers. This configuration is for CMake versions older than 3.12. ```cmake 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) ``` -------------------------------- ### Skip C++ Example Build Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Prints a notice and disables C++ build if C++17 is unavailable or the C++ API is disabled. ```cmake 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) ``` -------------------------------- ### mdbx_dbi_open - Open or Create Database Table Source: https://context7.com/mithril-mine/libmdbx/llms.txt Provides examples of opening and creating database tables (DBI) within an MDBX environment, including options for default, DUPSORT, INTEGERKEY, and DUPFIXED flags. ```APIDOC ## mdbx_dbi_open ### Description Opens or creates a named database table within the environment. ### Method (Implicitly part of MDBX API, not a direct HTTP method) ### Endpoint (N/A - C function) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body (N/A - Operates on environment and transaction) ### Request Example ```c // Open default database rc = mdbx_dbi_open(txn, NULL, MDBX_CREATE, &dbi_default); // Open database with sorted duplicates rc = mdbx_dbi_open(txn, "tags", MDBX_CREATE | MDBX_DUPSORT, &dbi_dupsort); // Open database with integer keys rc = mdbx_dbi_open(txn, "timestamps", MDBX_CREATE | MDBX_INTEGERKEY, &dbi_intkey); ``` ### Response #### Success Response (0) Indicates the operation was successful. #### Response Example (N/A - Returns an integer status code) ### Error Handling Returns an integer status code indicating success or failure (e.g., MDBX_SUCCESS). ``` -------------------------------- ### Install MDBX Static Library (CMake >= 3.12) Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs the MDBX static library, its export set, and headers. This configuration is for CMake versions 3.12 and newer, utilizing NAMELINK_COMPONENT. ```cmake 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) ``` -------------------------------- ### Install MDBX Shared Library (CMake < 3.12) Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs the MDBX shared library, its export set, and headers. This configuration is for CMake versions older than 3.12. ```cmake 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) ``` -------------------------------- ### Install MDBX Shared Library (CMake >= 3.12) Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Installs the MDBX shared library, its export set, and headers. This configuration is for CMake versions 3.12 and newer, utilizing NAMELINK_COMPONENT. ```cmake 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) ``` -------------------------------- ### Include Utility Modules Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Includes necessary CMake utility modules for finding packages, messages, and installation directories. ```cmake include(CheckFunctionExists) include(FindPackageMessage) include(GNUInstallDirs) ``` -------------------------------- ### Define C API Test Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Adds a test for the C API using the legacy example executable. ```cmake add_test(NAME c_api COMMAND mdbx_legacy_example) ``` -------------------------------- ### Configure RPATH and DLL Crutch for Tools Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Sets up runtime search paths (RPATH) for libraries and defines a 'DLL Crutch' for Windows if needed. This ensures that tools can find the shared MDBX library during the build and installation process. ```cmake if(MDBX_BUILD_SHARED_LIBRARY AND MDBX_LINK_TOOLS_NONSTATIC) set(TOOL_MDBX_LIB mdbx) # use, i.e. don't skip the full RPATH for the build tree set(CMAKE_SKIP_BUILD_RPATH FALSE) # when building, don't use the install RPATH already (but later on when installing) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # add the automatically determined parts of the RPATH which point to directories outside the build tree to the install # RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # the RPATH to be used when installing, but only if it's not a system directory list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) if(isSystemDir EQUAL -1) if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(CMAKE_INSTALL_RPATH "@executable_path/../lib") else() set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") endif() endif() if(WIN32) # Windows don't have RPATH feature, therefore we should prepare PATH or copy DLL(s) set(TOOL_MDBX_DLLCRUTCH "Crutch for ${CMAKE_SYSTEM_NAME}") if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_VERSION VERSION_LESS 3.0) # will use LOCATION property to compose DLLPATH cmake_policy(SET CMP0026 OLD) endif() else() set(TOOL_MDBX_DLLCRUTCH FALSE) endif() else() set(TOOL_MDBX_LIB mdbx-static) set(TOOL_MDBX_DLLCRUTCH FALSE) endif() ``` -------------------------------- ### Begin and Commit MDBX Transaction Source: https://context7.com/mithril-mine/libmdbx/llms.txt Creates a new transaction for database operations, which can be read-only or read-write and nested. This example demonstrates opening a named database, performing a put operation, and committing the transaction. Ensure proper error handling and transaction abortion on failure. ```c #include #include #include int main() { MDBX_env *env = NULL; MDBX_txn *txn = NULL; MDBX_dbi dbi; int rc; // Setup environment mdbx_env_create(&env); mdbx_env_set_maxdbs(env, 2); mdbx_env_open(env, "./testdb", MDBX_CREATE, 0664); // Begin a read-write transaction rc = mdbx_txn_begin(env, NULL, MDBX_TXN_READWRITE, &txn); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_txn_begin failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return 1; } // Open/create a named database within the transaction rc = mdbx_dbi_open(txn, "mydb", MDBX_CREATE, &dbi); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_dbi_open failed: %s\n", mdbx_strerror(rc)); mdbx_txn_abort(txn); mdbx_env_close(env); return 1; } // Store a key-value pair MDBX_val key = {.iov_base = "hello", .iov_len = 5}; MDBX_val data = {.iov_base = "world", .iov_len = 5}; rc = mdbx_put(txn, dbi, &key, &data, MDBX_UPSERT); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_put failed: %s\n", mdbx_strerror(rc)); mdbx_txn_abort(txn); mdbx_env_close(env); return 1; } // Commit the transaction rc = mdbx_txn_commit(txn); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_txn_commit failed: %s\n", mdbx_strerror(rc)); } else { printf("Transaction committed successfully\n"); } mdbx_env_close(env); return 0; } ``` -------------------------------- ### Retrieve Data with MDBX Get Source: https://context7.com/mithril-mine/libmdbx/llms.txt Demonstrates retrieving a single key-value pair using mdbx_get in a read-only transaction. Handles success, key not found, and other errors. ```c #include #include #include void retrieve_data(MDBX_env *env, MDBX_dbi dbi, const char *keystr) { MDBX_txn *txn = NULL; MDBX_val key, data; int rc; // Begin read-only transaction for retrieval rc = mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); if (rc != MDBX_SUCCESS) { fprintf(stderr, "Begin failed: %s\n", mdbx_strerror(rc)); return; } key.iov_base = (void*)keystr; key.iov_len = strlen(keystr); rc = mdbx_get(txn, dbi, &key, &data); switch (rc) { case MDBX_SUCCESS: printf("Found: key='%.*s' value='%.*s' (len=%zu)\n", (int)key.iov_len, (char*)key.iov_base, (int)data.iov_len, (char*)data.iov_base, data.iov_len); break; case MDBX_NOTFOUND: printf("Key '%s' not found\n", keystr); break; default: fprintf(stderr, "Get failed: %s\n", mdbx_strerror(rc)); } mdbx_txn_abort(txn); // Read-only, so abort is fine } ``` -------------------------------- ### Get Compiler Version Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Executes the C compiler to get its version information. Falls back to using compiler ID and version if execution 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() ``` -------------------------------- ### Environment Management - mdbx_env_open Source: https://context7.com/mithril-mine/libmdbx/llms.txt Opens an environment instance for use. The environment must have been created with `mdbx_env_create()`. Various flags control the behavior including read-only mode, write mapping, and sync modes. ```APIDOC ## mdbx_env_open ### Description Opens an environment instance for use. The environment must have been created with `mdbx_env_create()`. Various flags control the behavior including read-only mode, write mapping, and sync modes. ### Method C Function ### Endpoint N/A (Library Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c #include #include #include #include int main() { MDBX_env *env = NULL; int rc; rc = mdbx_env_create(&env); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_create failed: %s\n", mdbx_strerror(rc)); return EXIT_FAILURE; } // Set maximum number of named databases mdbx_env_set_maxdbs(env, 4); // Open environment with standard flags // MDBX_NOSUBDIR: Use pathname as the database file (not a directory) // MDBX_WRITEMAP: Use writeable memory map for better performance // MDBX_LIFORECLAIM: LIFO policy for GC recycling (better write performance) rc = mdbx_env_open(env, "./testdb.mdbx", MDBX_NOSUBDIR | MDBX_CREATE | MDBX_WRITEMAP | MDBX_LIFORECLAIM, 0664); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_open failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } // Get environment info MDBX_envinfo info; rc = mdbx_env_info_ex(env, NULL, &info, sizeof(info)); if (rc == MDBX_SUCCESS) { printf("Database opened successfully\n"); printf(" Map size: %lu bytes\n", (unsigned long)info.mi_mapsize); printf(" Page size: %u bytes\n", info.mi_dxb_pagesize); printf(" Max readers: %u\n", info.mi_maxreaders); } mdbx_env_close(env); return EXIT_SUCCESS; } ``` ### Response #### Success Response (0) Returns `MDBX_SUCCESS` on successful opening. #### Response Example ``` Database opened successfully Map size: 104857600 bytes Page size: 4096 bytes Max readers: 128 ``` ``` -------------------------------- ### Get Value Count with MDBX Get Ex Source: https://context7.com/mithril-mine/libmdbx/llms.txt Retrieves the first data item for a key and the count of duplicate values using mdbx_get_ex. Useful for DUPSORT tables. ```c #include #include #include void get_with_count(MDBX_env *env, MDBX_dbi dbi, const char *keystr) { MDBX_txn *txn = NULL; MDBX_val key, data; size_t count = 0; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); key.iov_base = (void*)keystr; key.iov_len = strlen(keystr); // Get value and count of duplicates (for DUPSORT tables) rc = mdbx_get_ex(txn, dbi, &key, &data, &count); if (rc == MDBX_SUCCESS) { printf("Key '%s' has %zu value(s)\n", keystr, count); printf("First value: %.*s\n", (int)data.iov_len, (char*)data.iov_base); } mdbx_txn_abort(txn); } ``` -------------------------------- ### Database Cursor Operations with mdbx_cursor_open Source: https://context7.com/mithril-mine/libmdbx/llms.txt Illustrates how to open a database cursor, retrieve records sequentially using MDBX_FIRST and MDBX_NEXT, and handle potential errors. Cursors must be closed after use. ```c #include #include void cursor_basics(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn = NULL; MDBX_cursor *cursor = NULL; MDBX_val key, data; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_RDONLY, &txn); rc = mdbx_cursor_open(txn, dbi, &cursor); if (rc != MDBX_SUCCESS) { fprintf(stderr, "Cursor open failed: %s\n", mdbx_strerror(rc)); mdbx_txn_abort(txn); return; } // Iterate through all records printf("All records:\n"); rc = mdbx_cursor_get(cursor, &key, &data, MDBX_FIRST); while (rc == MDBX_SUCCESS) { 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); } if (rc != MDBX_NOTFOUND) { fprintf(stderr, "Iteration error: %s\n", mdbx_strerror(rc)); } mdbx_cursor_close(cursor); mdbx_txn_abort(txn); } ``` -------------------------------- ### mdbx_cursor_open - Create and Use Cursor Source: https://context7.com/mithril-mine/libmdbx/llms.txt Illustrates how to open a cursor for navigating through an MDBX database and how to retrieve records sequentially using `mdbx_cursor_get`. ```APIDOC ## mdbx_cursor_open ### Description Creates a cursor for navigating through a database table. ### Method `mdbx_cursor_open` ### Parameters - **txn** (*MDBX_txn **) - Transaction handle. - **dbi** (*MDBX_dbi*) - Database identifier. - **cursor** (*MDBX_cursor * **) - Pointer to the cursor handle to be created. ### Request Example ```c rc = mdbx_cursor_open(txn, dbi, &cursor); ``` ## Cursor Operations (General) ### Description Operations performed using an MDBX cursor for data retrieval. ### Method `mdbx_cursor_get` ### Parameters - **cursor** (*MDBX_cursor **) - Cursor handle. - **key** (*MDBX_val **) - Pointer to store the retrieved key. - **data** (*MDBX_val **) - Pointer to store the retrieved data. - **op** (*uint32_t*) - Operation code (e.g., `MDBX_FIRST`, `MDBX_NEXT`). ### Request Example ```c // Iterate through all records rc = mdbx_cursor_get(cursor, &key, &data, MDBX_FIRST); while (rc == MDBX_SUCCESS) { // Process key and data rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT); } ``` ### Response - **MDBX_SUCCESS**: Successfully retrieved a key-value pair. - **MDBX_NOTFOUND**: No more records found or the requested record does not exist. - Other MDBX error codes indicate failure. ``` -------------------------------- ### Display Build Options Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Iterates through a list of options and prints their defined values or indicates if they are auto-detected. ```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) ``` -------------------------------- ### Configure Interprocedural Optimization Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Enables interprocedural optimization for the modern C++ example if the INTERPROCEDURAL_OPTIMIZATION variable is defined. ```cmake if(DEFINED INTERPROCEDURAL_OPTIMIZATION) set_target_properties(mdbx_modern_example PROPERTIES INTERPROCEDURAL_OPTIMIZATION $) endif() ``` -------------------------------- ### Open MDBX Environment Source: https://context7.com/mithril-mine/libmdbx/llms.txt Opens an MDBX environment instance. Use flags like MDBX_NOSUBDIR, MDBX_WRITEMAP, and MDBX_LIFORECLAIM to control behavior. Retrieves environment information after opening. ```c #include #include #include #include int main() { MDBX_env *env = NULL; int rc; rc = mdbx_env_create(&env); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_create failed: %s\n", mdbx_strerror(rc)); return EXIT_FAILURE; } // Set maximum number of named databases mdbx_env_set_maxdbs(env, 4); // Open environment with standard flags // MDBX_NOSUBDIR: Use pathname as the database file (not a directory) // MDBX_WRITEMAP: Use writeable memory map for better performance // MDBX_LIFORECLAIM: LIFO policy for GC recycling (better write performance) rc = mdbx_env_open(env, "./testdb.mdbx", MDBX_NOSUBDIR | MDBX_CREATE | MDBX_WRITEMAP | MDBX_LIFORECLAIM, 0664); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_open failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } // Get environment info MDBX_envinfo info; rc = mdbx_env_info_ex(env, NULL, &info, sizeof(info)); if (rc == MDBX_SUCCESS) { printf("Database opened successfully\n"); printf(" Map size: %lu bytes\n", (unsigned long)info.mi_mapsize); printf(" Page size: %u bytes\n", info.mi_dxb_pagesize); printf(" Max readers: %u\n", info.mi_maxreaders); } mdbx_env_close(env); return EXIT_SUCCESS; } ``` -------------------------------- ### Demonstrate MDBX Put Operations Source: https://context7.com/mithril-mine/libmdbx/llms.txt Illustrates various modes for mdbx_put: UPSERT, NOOVERWRITE, CURRENT, RESERVE, and APPEND. Ensure keys are sorted for APPEND. ```c #include #include #include void demonstrate_put_operations(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn = NULL; MDBX_val key, data; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_READWRITE, &txn); // 1. UPSERT: Insert or update (default behavior) key.iov_base = "user:1001"; key.iov_len = strlen("user:1001"); data.iov_base = "{\"name\":\"Alice\",\"age\":30}"; data.iov_len = strlen(data.iov_base); rc = mdbx_put(txn, dbi, &key, &data, MDBX_UPSERT); printf("UPSERT: %s\n", rc == MDBX_SUCCESS ? "OK" : mdbx_strerror(rc)); // 2. NOOVERWRITE: Insert only if key doesn't exist key.iov_base = "user:1002"; key.iov_len = strlen("user:1002"); data.iov_base = "{\"name\":\"Bob\",\"age\":25}"; data.iov_len = strlen(data.iov_base); rc = mdbx_put(txn, dbi, &key, &data, MDBX_NOOVERWRITE); if (rc == MDBX_KEYEXIST) { printf("NOOVERWRITE: Key already exists\n"); } else { printf("NOOVERWRITE: %s\n", rc == MDBX_SUCCESS ? "OK" : mdbx_strerror(rc)); } // 3. CURRENT: Update only if key exists key.iov_base = "user:1001"; key.iov_len = strlen("user:1001"); data.iov_base = "{\"name\":\"Alice\",\"age\":31}"; data.iov_len = strlen(data.iov_base); rc = mdbx_put(txn, dbi, &key, &data, MDBX_CURRENT); if (rc == MDBX_NOTFOUND) { printf("CURRENT: Key not found, cannot update\n"); } else { printf("CURRENT: %s\n", rc == MDBX_SUCCESS ? "OK" : mdbx_strerror(rc)); } // 4. RESERVE: Allocate space without copying data key.iov_base = "large:data"; key.iov_len = strlen("large:data"); data.iov_len = 1024; // Reserve 1KB rc = mdbx_put(txn, dbi, &key, &data, MDBX_RESERVE); if (rc == MDBX_SUCCESS) { // data.iov_base now points to reserved memory memset(data.iov_base, 'X', data.iov_len); printf("RESERVE: Reserved and filled %zu bytes\n", data.iov_len); } // 5. APPEND: Fast bulk loading (keys must be in order) char keystr[32]; for (int i = 1; i <= 100; i++) { snprintf(keystr, sizeof(keystr), "zzzz:%05d", i); // Ensures ascending order key.iov_base = keystr; key.iov_len = strlen(keystr); data.iov_base = "bulk data"; data.iov_len = 9; rc = mdbx_put(txn, dbi, &key, &data, MDBX_APPEND); if (rc == MDBX_EKEYMISMATCH) { printf("APPEND: Keys must be in sorted order!\n"); break; } } if (rc == MDBX_SUCCESS) { printf("APPEND: Bulk inserted 100 records\n"); } mdbx_txn_commit(txn); } ``` -------------------------------- ### Build PCRF Simulator Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Compiles the PCRF simulator executable on UNIX systems and links the MDBX library. ```cmake if(UNIX) add_executable(pcrf_simulator pcrf/pcrf_simulator.c) target_link_libraries(pcrf_simulator ${MDBX_LIBRARY}) endif() ``` -------------------------------- ### Get Target Compile Options Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Retrieves compile options for a given target and appends them to MDBX_BUILD_FLAGS. Ensures no duplicate flags. ```cmake get_target_property(options_list ${target4fetch} COMPILE_OPTIONS) if(options_list) list(APPEND MDBX_BUILD_FLAGS ${options_list}) endif() list(REMOVE_DUPLICATES MDBX_BUILD_FLAGS) string(REPLACE ";" " " MDBX_BUILD_FLAGS "${MDBX_BUILD_FLAGS}") ``` -------------------------------- ### Define C++ API Test Source: https://github.com/mithril-mine/libmdbx/blob/master/ut_and_examples/CMakeLists.txt Adds a test for the C++ API using the modern example executable, if C++ build is enabled. ```cmake if(MDBX_BUILD_CXX) add_test(NAME c++_api COMMAND mdbx_modern_example) endif() ``` -------------------------------- ### Atomic Replace with mdbx_replace Source: https://context7.com/mithril-mine/libmdbx/llms.txt Shows how to atomically replace a key's value while retrieving the old value, or insert if the key does not exist using MDBX_UPSERT. Also demonstrates deleting a key and retrieving its old value. ```c #include #include #include void atomic_replace(MDBX_env *env, MDBX_dbi dbi) { MDBX_txn *txn = NULL; MDBX_val key, new_data, old_data; char old_buffer[1024]; int rc; mdbx_txn_begin(env, NULL, MDBX_TXN_READWRITE, &txn); key.iov_base = "counter"; key.iov_len = strlen("counter"); new_data.iov_base = "42"; new_data.iov_len = 2; // Prepare buffer for old value old_data.iov_base = old_buffer; old_data.iov_len = sizeof(old_buffer); rc = mdbx_replace(txn, dbi, &key, &new_data, &old_data, MDBX_UPSERT); if (rc == MDBX_SUCCESS) { if (old_data.iov_len > 0) { printf("Replaced '%.*s' with '%.*s'\n", (int)old_data.iov_len, (char*)old_data.iov_base, (int)new_data.iov_len, (char*)new_data.iov_base); } else { printf("Inserted new value '%.*s'\n", (int)new_data.iov_len, (char*)new_data.iov_base); } } else if (rc == MDBX_RESULT_TRUE) { printf("Buffer too small, need %zu bytes\n", old_data.iov_len); } // Delete and retrieve old value key.iov_base = "to_delete"; key.iov_len = strlen("to_delete"); old_data.iov_base = old_buffer; old_data.iov_len = sizeof(old_buffer); rc = mdbx_replace(txn, dbi, &key, NULL, &old_data, 0); // NULL new_data = delete if (rc == MDBX_SUCCESS) { printf("Deleted and retrieved: '%.*s'\n", (int)old_data.iov_len, (char*)old_data.iov_base); } mdbx_txn_commit(txn); } ``` -------------------------------- ### Create MDBX Environment Source: https://context7.com/mithril-mine/libmdbx/llms.txt Creates an MDBX environment handle. Configure environment settings like max databases and geometry before opening. Ensure to close the environment with mdbx_env_close(). ```c #include #include #include int main() { MDBX_env *env = NULL; int rc; // Create the environment handle rc = mdbx_env_create(&env); if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_create failed: %s\n", mdbx_strerror(rc)); return EXIT_FAILURE; } // Configure environment before opening rc = mdbx_env_set_maxdbs(env, 10); // Allow up to 10 named databases if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_set_maxdbs failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } // Set database geometry (size limits) rc = mdbx_env_set_geometry(env, 1024 * 1024, // size_lower: 1MB minimum -1, // size_now: use default 1024 * 1024 * 100, // size_upper: 100MB maximum 1024 * 1024, // growth_step: 1MB increments 1024 * 1024 * 2, // shrink_threshold: 2MB -1); // pagesize: use default if (rc != MDBX_SUCCESS) { fprintf(stderr, "mdbx_env_set_geometry failed: %s\n", mdbx_strerror(rc)); mdbx_env_close(env); return EXIT_FAILURE; } printf("Environment created successfully\n"); mdbx_env_close(env); return EXIT_SUCCESS; } ``` -------------------------------- ### Add Test Subdirectory Source: https://github.com/mithril-mine/libmdbx/blob/master/CMakeLists.txt Conditionally adds the 'ut_and_examples' subdirectory if MDBX_ENABLE_TESTS is defined. ```cmake if(MDBX_ENABLE_TESTS) add_subdirectory(ut_and_examples) endif() ``` -------------------------------- ### mdbx_cursor_del - Delete Current Key/Data Pair Source: https://context7.com/mithril-mine/libmdbx/llms.txt Demonstrates how to delete the current key/data pair pointed to by a cursor, including examples for deleting records with a specific prefix and all duplicates for a given key in DUPSORT tables. ```APIDOC ## mdbx_cursor_del ### Description Deletes the current key/data pair pointed to by the cursor. ### Method (Implicitly part of MDBX API, not a direct HTTP method) ### Endpoint (N/A - C function) ### Parameters #### Path Parameters (N/A) #### Query Parameters (N/A) #### Request Body (N/A - Operates on cursor state) ### Request Example ```c // Example usage within a transaction rc = mdbx_cursor_del(cursor, MDBX_CURRENT); rc = mdbx_cursor_del(cursor, MDBX_ALLDUPS); ``` ### Response #### Success Response (0) Indicates the operation was successful. #### Response Example (N/A - Returns an integer status code) ### Error Handling Returns an integer status code indicating success or failure (e.g., MDBX_SUCCESS, MDBX_NOTFOUND). ```