###################################### Tutorial: Your First Key-Value Store ###################################### In this tutorial, you will learn how to initialize an LMDB environment, write a key-value pair to the database, and read it back using the ``lmdbxx`` C++20 module. By the end of this guide, you will have a working executable that persists data to your disk. *************** Prerequisites *************** Before you begin, ensure you have: - A C++20 capable compiler. - The ``lmdbxx`` module and the underlying C ``lmdb`` library linked to your project. - A temporary directory on your system to store the database files (we will use ``./testdb``). **************************** Step 1: Import the Modules **************************** Create a new file named ``main.cpp``. Start by importing the standard library and the ``lmdbxx`` module. .. code:: cpp import std; import lmdbxx; ************************************ Step 2: Initialize the Environment ************************************ LMDB uses an "environment" to manage memory mapping and file locks. We must create it, configure it, and open it targeting a directory on our disk. .. code:: cpp int main() { // Create the directory for our database std::filesystem::create_directory("./testdb"); // Create the LMDB environment wrapper auto env = lmdbxx::env::create(); // Configure the environment to allow at least one named database env.set_max_dbs(1); // Open the environment in our target directory env.open("./testdb"); // ... we will add more code here } **************************************** Step 3: Write Data (Write Transaction) **************************************** All read and write operations in LMDB happen inside a transaction. Let's start a write transaction, open the default database, and store a message. Add the following to your ``main`` function: .. code:: cpp // 1. Begin a read-write transaction auto write_txn = lmdbxx::txn::begin(env); // 2. Open the main database handle using this transaction auto db = lmdbxx::dbi::open(write_txn); // 3. Define our key and value strings std::string_view key = "greeting"; std::string_view value = "Hello, LMDB C++20 Module!"; // 4. Put the data into the database db.put(write_txn, key, value); // 5. Commit the transaction to disk write_txn.commit(); std::println("Data written successfully."); ******************************************* Step 4: Read Data (Read-Only Transaction) ******************************************* Now, let's verify that our data was saved. We will create a new, read-only transaction. Read-only transactions are extremely fast and do not block writers. .. code:: cpp // 1. Begin a read-only transaction auto read_txn = lmdbxx::txn::begin(env, nullptr, lmdbxx::env_flags::rdonly); // 2. Prepare a string_view to receive the data std::string_view retrieved_value; // 3. Search the database for our key if (db.get(read_txn, "greeting", retrieved_value)) { std::println("Retrieved: {}", retrieved_value); } else { std::println("Key not found!"); } // Read transactions should be aborted or let fall out of scope when done read_txn.abort(); return 0; } ********************** Complete Source Code ********************** Here is the complete code for this tutorial. Because ``lmdbxx`` uses RAII wrappers, the database and environment handles will safely close themselves automatically when they fall out of scope at the end of ``main``. .. code:: cpp import std; import lmdbxx; int main() { std::filesystem::create_directory("./testdb"); auto env = lmdbxx::env::create(); env.set_max_dbs(1); env.open("./testdb"); // --- Write Data --- auto write_txn = lmdbxx::txn::begin(env); auto db = lmdbxx::dbi::open(write_txn); db.put(write_txn, "greeting", "Hello, LMDB C++20 Module!"); write_txn.commit(); std::println("Data written successfully."); // --- Read Data --- auto read_txn = lmdbxx::txn::begin(env, nullptr, lmdbxx::env_flags::rdonly); std::string_view retrieved_value; if (db.get(read_txn, "greeting", retrieved_value)) { std::println("Retrieved: {}", retrieved_value); } return 0; }