### CMake: Install ChainBase Library and Headers Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt Configures the installation process for the ChainBase library and its header files. It installs headers to the appropriate include directory and the library/archive files to the library directory. Installation can be controlled by a component variable `CHAINBASE_INSTALL_COMPONENT`. ```cmake if(CHAINBASE_INSTALL_COMPONENT) set(INSTALL_COMPONENT_ARGS COMPONENT ${CHAINBASE_INSTALL_COMPONENT} EXCLUDE_FROM_ALL) endif() install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/chainbase DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} ${INSTALL_COMPONENT_ARGS}) install(TARGETS chainbase LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS} ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR} ${INSTALL_COMPONENT_ARGS}) ``` -------------------------------- ### ChainBase Database Operations Example (C++) Source: https://github.com/antelopeio/chainbase/blob/main/README.md This C++ code demonstrates how to use ChainBase to create, modify, and query a database. It defines a 'book' object, sets up a multi-index container for efficient querying, and performs operations like adding, modifying, and removing books. It also shows how to query books based on their pages. ```c++ enum tables { book_table }; /** * Defines a "table" for storing books. This table is assigned a * globally unique ID (book_table) and must inherit from chainbase::object<> which * decorates the book type by defining "id_type" and "type_id" */ struct book : public chainbase::object { /** defines a default constructor for types that don't have * members requiring dynamic memory allocation. */ CHAINBASE_DEFAULT_CONSTRUCTOR( book ) id_type id; ///< this manditory member is a primary key int pages = 0; int publish_date = 0; }; struct by_id; struct by_pages; struct by_date; /** * This is a relatively standard boost multi_index_container definition that has three * requirements to be used withn a chainbase database: * - it must use chainbase::allocator * - the first index must be on the primary key (id) and must be unique (hashed or ordered) */ typedef multi_index_container< book, indexed_by< ordered_unique< tag, member >, ///< required ordered_non_unique< tag, BOOST_MULTI_INDEX_MEMBER(book,int,pages) >, ordered_non_unique< tag, BOOST_MULTI_INDEX_MEMBER(book,int,publish_date) > >, chainbase::allocator ///< required for use with chainbase::database > book_index; /** This simple program will open database_dir and add two new books every time it is run and then print out all of the books in the database. */ int main( int argc, char** argv ) { chainbase::database db; db.open( "database_dir", database::read_write, 1024*1024*8 ); /// open or create a database with 8MB capacity db.add_index< book_index >(); /// open or create the book_index const auto& book_idx = db.get_index().indices(); /** Returns a const reference to the book, this pointer will remain valid until the book is removed from the database. */ const auto& new_book300 = db.create( [&]( book& b ) { b.pages = 300+book_idx.size(); } ); const auto& new_book400 = db.create( [&]( book& b ) { b.pages = 300+book_idx.size(); } ); /** You modify a book by passing in a lambda that receives a non-const reference to the book you wish to modify. */ db.modify( new_book300, [&]( book& b ) { b.pages++; }); for( const auto& b : book_idx ) { std::cout << b.pages << "\n"; } auto itr = book_idx.get().lower_bound( 100 ); if( itr != book_idx.get().end() ) { std::cout << itr->pages; } db.remove( new_book400 ); return 0; } ``` -------------------------------- ### ChainBase C++ Database Operations Example Source: https://context7.com/antelopeio/chainbase/llms.txt Demonstrates core ChainBase functionalities including database opening, index management, object creation, modification, querying, and removal. It utilizes Boost.MultiIndex for efficient data indexing and management. This example is suitable for understanding basic state persistence and transactional operations within ChainBase. ```cpp #include #include #include #include #include using namespace chainbase; using namespace boost::multi_index; enum tables { book_table }; struct book : public chainbase::object { CHAINBASE_DEFAULT_CONSTRUCTOR(book) id_type id; int pages = 0; int publish_date = 0; }; struct by_id; struct by_pages; struct by_date; typedef multi_index_container< book, indexed_by< ordered_unique, member>, ordered_non_unique, BOOST_MULTI_INDEX_MEMBER(book, int, pages)>, ordered_non_unique, BOOST_MULTI_INDEX_MEMBER(book, int, publish_date)> >, chainbase::node_allocator > book_index; CHAINBASE_SET_INDEX_TYPE(book, book_index) int main(int argc, char** argv) { // Open database database db; db.open("database_dir", database::read_write, 1024*1024*8); db.add_index(); const auto& book_idx = db.get_index().indices(); // Create books const auto& book300 = db.create([&](book& b) { b.pages = 300 + book_idx.size(); b.publish_date = 2024; }); const auto& book400 = db.create([&](book& b) { b.pages = 400 + book_idx.size(); b.publish_date = 2025; }); // Modify book db.modify(book300, [&](book& b) { b.pages++; }); // Query by index auto itr = book_idx.get().lower_bound(100); if (itr != book_idx.get().end()) { std::cout << "First book with 100+ pages: " << itr->pages << "\n"; } // Print all books for (const auto& b : book_idx) { std::cout << "Book pages: " << b.pages << ", date: " << b.publish_date << "\n"; } // Transaction with undo { auto session = db.start_undo_session(true); db.modify(book300, [&](book& b) { b.pages = 1000; }); std::cout << "Modified pages: " << book300.pages << "\n"; // Automatically undone on scope exit } std::cout << "Pages after undo: " << book300.pages << "\n"; // Remove book db.remove(book400); // Flush to disk db.flush(); return 0; } ``` -------------------------------- ### Monitor and Manage Database Memory in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Provides C++ code examples for monitoring and managing database memory usage with `chainbase`. This includes checking free and reclaimable memory, retrieving row counts per index, accessing the segment manager, triggering memory flushes, and inspecting the memory usage of specific indexes. ```cpp #include #include #include using namespace chainbase; // Assume database db and book_index are defined and initialized as in previous examples // For demonstration purposes, let's re-declare them: database db("db_dir", database::read_write, 1024*1024*8); db.add_index(); // Check available memory size_t free_memory = db.get_free_memory(); std::cout << "Free memory: " << free_memory << " bytes\n"; // Get reclaimable memory from freelists size_t reclaimable = db.get_reclaimable_memory(); std::cout << "Reclaimable: " << reclaimable << " bytes\n"; // Get row count per index auto row_counts = db.row_count_per_index(); for (const auto& [count, type_name] : row_counts) { std::cout << type_name << ": " << count << " rows\n"; } // Get segment manager for advanced operations segment_manager* seg_mgr = db.get_segment_manager(); // Check memory and flush if needed (automatic threshold-based) size_t flushed = db.check_memory_and_flush_if_needed(); if (flushed > 0) { std::cout << "Flushed " << flushed << " bytes to disk\n"; } // Get memory usage for specific index const auto& book_idx_abstract = db.get_index(); size_t freelist_mem = book_idx_abstract.freelist_memory_usage(); std::cout << "Freelist memory: " << freelist_mem << " bytes\n"; ``` -------------------------------- ### Transaction Sessions and Undo Management in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Illustrates nested transaction management using undo sessions in C++. This includes starting sessions, making changes (create, modify), committing changes via `push()`, rolling back via `undo()`, and merging changes via `squash()`. It also shows manual control over the undo stack with `commit()` and `undo_all()`. ```cpp // Start undo session (changes automatically rolled back on scope exit) { auto session = db.start_undo_session(true); db.create([&](book& b) { b.pages = 400; b.publish_date = 2026; }); db.modify(existing_book, [&](book& b) { b.pages = 500; }); // Changes rolled back automatically when session destructs } // Push session changes to parent undo level { auto session = db.start_undo_session(true); db.create([&](book& b) { b.pages = 600; }); session.push(); // Commit to parent undo level } // Now can undo the pushed changes db.undo(); // Squash session (merge with parent, no undo boundary) { auto session = db.start_undo_session(true); db.modify(book_ref, [&](book& b) { b.pages = 700; }); session.squash(); // Merge into parent level } // Nested sessions auto outer_session = db.start_undo_session(true); db.create([&](book& b) { b.pages = 100; }); { auto inner_session = db.start_undo_session(true); db.create([&](book& b) { b.pages = 200; }); inner_session.push(); // Commit inner to outer } outer_session.push(); // Commit outer to undo stack // Manual undo operations db.undo(); // Undo last committed session db.squash(); // Squash top two undo levels db.commit(10); // Commit all changes up to revision 10 db.undo_all(); // Undo everything to initial state ``` -------------------------------- ### ChainBase Object Creation, Modification, and Removal (C++) Source: https://context7.com/antelopeio/chainbase/llms.txt Covers the fundamental CRUD (Create, Read, Update, Delete) operations for objects within a ChainBase database. Demonstrates creating new objects via lambda constructors, modifying existing ones, removing objects, and accessing them by primary key using find() and get(). ```cpp // Create new object with lambda constructor const auto& new_book = db.create([&](book& b) { b.pages = 300; b.publish_date = 2024; b.title = shared_string("My Book"); }); // Modify existing object db.modify(new_book, [&](book& b) { b.pages = 350; b.publish_date = 2025; }); // Remove object db.remove(new_book); // Access by primary key const auto* book_ptr = db.find(book::id_type(0)); if (book_ptr) { std::cout << "Pages: " << book_ptr->pages << "\n"; } // Get by primary key (throws if not found) try { const auto& book_ref = db.get(book::id_type(0)); std::cout << "Pages: " << book_ref.pages << "\n"; } catch (const std::out_of_range& e) { std::cerr << "Book not found: " << e.what() << "\n"; } ``` -------------------------------- ### ChainBase Database Initialization and Lifecycle (C++) Source: https://context7.com/antelopeio/chainbase/llms.txt Demonstrates how to open, create, and manage a ChainBase database. Includes operations for read-write and read-only access, checking database state, and flushing changes to disk. Dependencies include the chainbase library. ```cpp #include using namespace chainbase; // Open or create database with 8MB capacity database db; db.open("database_dir", database::read_write, 1024*1024*8); // Open existing database in read-only mode (for concurrent readers) database db_reader; db_reader.open("database_dir", database::read_only, 0, true); // Check database state bool is_readonly = db.is_read_only(); int64_t current_rev = db.revision(); size_t free_mem = db.get_free_memory(); // Flush changes to disk db.flush(); ``` -------------------------------- ### ChainBase Object Definition and Index Registration (C++) Source: https://context7.com/antelopeio/chainbase/llms.txt Illustrates how to define custom objects for ChainBase and register them with multi-index containers. This enables efficient querying and management of data based on various indices. Dependencies include chainbase and boost.multi_index libraries. ```cpp #include #include #include #include using namespace chainbase; using namespace boost::multi_index; // Table ID enumeration enum tables { book_table = 0 }; // Define object inheriting from chainbase::object struct book : public chainbase::object { CHAINBASE_DEFAULT_CONSTRUCTOR(book) id_type id; // Primary key (mandatory) int pages = 0; int publish_date = 0; shared_string title; }; // Index tag definitions struct by_id; struct by_pages; struct by_date; // Define multi_index_container with chainbase::node_allocator typedef multi_index_container< book, indexed_by< ordered_unique, member>, ordered_non_unique, BOOST_MULTI_INDEX_MEMBER(book, int, pages)>, ordered_non_unique, BOOST_MULTI_INDEX_MEMBER(book, int, publish_date)> >, chainbase::node_allocator > book_index; // Register the index type for the object CHAINBASE_SET_INDEX_TYPE(book, book_index) // Add index to database db.add_index(); ``` -------------------------------- ### Create and Use Shared Copy-on-Write Vectors in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Demonstrates the creation, manipulation, and usage of shared copy-on-write vectors in C++. This includes initialization from various sources, copy and move semantics, element access, iteration, and comparison operators. It leverages the `chainbase::shared_cow_vector` class. ```cpp #include #include #include #include // Create from iterators std::vector source = {1, 2, 3, 4, 5}; shared_vector vec1(source.begin(), source.end()); // Create from pointer and size int arr[] = {10, 20, 30}; shared_vector vec2(arr, 3); // Create from initializer list shared_vector vec3 = {100, 200, 300}; // Copy constructor (shares data) shared_vector vec4 = vec1; assert(vec1.data() == vec4.data()); // Same buffer // Assignment from std::vector std::vector std_vec = {7, 8, 9}; vec1 = shared_vector(std_vec); // Access elements (const only, copy-on-write) std::cout << "Size: " << vec1.size() << "\n"; std::cout << "Element 0: " << vec1[0] << "\n"; std::cout << "Empty: " << vec1.empty() << "\n"; // Iterate for (const auto& val : vec1) { std::cout << val << " "; } std::cout << "\n"; // Move semantics shared_vector vec5 = std::move(vec1); assert(vec1.data() == nullptr); assert(vec1.empty()); // Comparison operators bool equal = (vec3 == vec4); ``` -------------------------------- ### CMake: Build and Link ChainBase Library Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt Defines the ChainBase library target, compiling source files and headers. It links against Boost system libraries and optionally other Boost components (Boost::asio, Boost::interprocess, etc.) and platform-specific libraries like `ws2_32` on Windows or `stdc++fs` for specific GCC versions. ```cmake file(GLOB HEADERS "include/chainbase/*.hpp") add_library( chainbase src/chainbase.cpp src/pinnable_mapped_file.cpp ${HEADERS} ) target_link_libraries( chainbase PUBLIC ${PLATFORM_LIBRARIES} Boost::system ) if(TARGET Boost::asio) target_link_libraries( chainbase PUBLIC Boost::headers Boost::interprocess Boost::chrono Boost::multi_index Boost::lexical_cast Boost::asio ) endif() target_include_directories( chainbase PUBLIC "$" "$" ) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9) target_link_libraries( chainbase PUBLIC stdc++fs ) endif() endif() if(WIN32) target_link_libraries( chainbase PUBLIC ws2_32 mswsock ) endif() ``` -------------------------------- ### Querying with Secondary Indices in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Demonstrates how to access and query objects within a database using secondary indices in C++. It covers iterating through all elements, querying ranges, finding specific elements, and using template-based index access. Assumes a pre-existing database object `db` and index configurations `book_index`, `by_id`, `by_pages`, `by_date`. ```cpp // Get index reference const auto& book_idx = db.get_index().indices(); // Iterate all books by primary key for (const auto& b : book_idx.get()) { std::cout << "Book ID: " << b.id._id << ", Pages: " << b.pages << "\n"; } // Query by secondary index auto& pages_idx = book_idx.get(); auto itr = pages_idx.lower_bound(100); if (itr != pages_idx.end()) { std::cout << "First book with 100+ pages: " << itr->pages << "\n"; } // Find by secondary key auto itr_exact = pages_idx.find(300); if (itr_exact != pages_idx.end()) { std::cout << "Found book with exactly 300 pages\n"; } // Use template-based index access auto date_itr = db.get_index().lower_bound(2020); while (date_itr != db.get_index().end()) { std::cout << "Published: " << date_itr->publish_date << "\n"; ++date_itr; } // Find object by secondary index with convenience method const auto* book_by_pages = db.find(250); if (book_by_pages) { std::cout << "Found book: " << book_by_pages->title << "\n"; } ``` -------------------------------- ### CMake: Platform-Specific Compiler Flags Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt Applies platform-specific compiler flags. For Apple systems, it enables `-Wall` and `-Wno-conversion`. For Linux, it enables `-Wall`. Additionally, for Linux with `FULL_STATIC_BUILD` enabled, it adds flags for static linking of the C++ standard library. ```cmake if( APPLE ) # Apple Specific Options Here message( STATUS "Configuring ChainBase on OS X" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-conversion" ) else( APPLE ) # Linux Specific Options Here message( STATUS "Configuring ChainBase on Linux" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) if ( FULL_STATIC_BUILD ) set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc") endif ( FULL_STATIC_BUILD ) LIST( APPEND PLATFORM_LIBRARIES pthread ) endif( APPLE ) ``` -------------------------------- ### Shared Copy-on-Write String in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Demonstrates the usage of `shared_string`, a memory-efficient string type with reference counting in C++. It covers creation from various sources (C-string, string_view, pointer/size), copy construction, assignment, accessing data, checking emptiness, move semantics, and comparison operators. Requires including ``. ```cpp #include // Create from C string shared_string str1("hello"); // Create from string_view shared_string str2(std::string_view("world")); // Create from pointer and size const char* data = "test"; shared_string str3(data, 4); // Copy constructor (shares data, no allocation) shared_string str4 = str1; assert(str1.data() == str4.data()); // Same underlying buffer // Assign triggers copy (if needed) str4.assign("different", 9); assert(str1.data() != str4.data()); // Now different buffers // Access data std::cout << "String: " << std::string_view(str1.data(), str1.size()) << "\n"; std::cout << "Length: " << str1.size() << "\n"; std::cout << "Empty: " << str1.empty() << "\n"; // Move semantics shared_string str5 = std::move(str1); assert(str1.data() == nullptr); assert(str1.empty()); // Comparison operators shared_string a("abc"), b("def"); bool less = (a < b); bool equal = (a == b); ``` -------------------------------- ### Revision Management in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Explains how to track and manage database revision history in C++. This includes retrieving the current revision number, explicitly setting the revision (typically during initialization), checking the revision range of the undo stack for an index, and performing undo operations to revert to previous revisions. ```cpp // Get current revision int64_t rev = db.revision(); std::cout << "Current revision: " << rev << "\n"; // Set revision explicitly (typically used during initialization) if (!db.is_read_only()) { db.set_revision(100); } // Check undo stack revision range for an index const auto& idx = db.get_index(); auto [min_rev, max_rev] = idx.undo_stack_revision_range(); std::cout << "Undo stack spans revisions " << min_rev << " to " << max_rev << "\n"; // Work with sessions at specific revisions auto session1 = db.start_undo_session(true); // ... make changes ... session1.push(); // Creates new revision auto session2 = db.start_undo_session(true); // ... make more changes ... session2.push(); // Another revision // Undo back to previous revision db.undo(); ``` -------------------------------- ### CMake: Set C++ Standard to C++20 Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt Ensures the project uses C++20 or newer. If the C++ standard is not explicitly set, it defaults to C++20 and requires it to be on. If C++98 is detected, it throws a fatal error. ```cmake if(CMAKE_CXX_STANDARD EQUAL 98) message(FATAL_ERROR "chainbase requires c++20 or newer") elseif(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() ``` -------------------------------- ### CMake: Enable Coverage Testing Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt Conditionally enables code coverage testing by adding the `--coverage` flag to CMAKE_CXX_FLAGS if the `ENABLE_COVERAGE_TESTING` variable is set to TRUE. This is typically used for debugging and performance analysis. ```cmake set(ENABLE_COVERAGE_TESTING FALSE CACHE BOOL "Build ChainBase for code coverage analysis") if(ENABLE_COVERAGE_TESTING) SET(CMAKE_CXX_FLAGS "--coverage ${CMAKE_CXX_FLAGS}") endif() ``` -------------------------------- ### CMake: BSD Specific Emulation Source: https://github.com/antelopeio/chainbase/blob/main/CMakeLists.txt For FreeBSD systems, this directive prevents the use of pthreads by defining `BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION`. This is necessary because Boost.Interprocess may attempt to use pthreads on BSD, which can lead to issues. ```cmake if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") target_compile_definitions(chainbase PUBLIC BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) endif() ``` -------------------------------- ### Toggle Read-Only Mode for Database in C++ Source: https://context7.com/antelopeio/chainbase/llms.txt Illustrates how to dynamically enable and disable read-only mode for a `chainbase::database` object in C++. This prevents accidental modifications during query-only operations and ensures data integrity. It shows how operations fail in read-only mode and resume once switched back to read-write. ```cpp #include #include #include using namespace chainbase; // Assume book and book_index are defined elsewhere struct book { int pages; }; struct book_index {}; database db("db_dir", database::read_write, 1024*1024*8); db.add_index(); // Switch to read-only mode (prevents accidental modifications) db.set_read_only_mode(); try { // These operations will throw std::logic_error db.create([](book& b) { b.pages = 100; }); } catch (const std::logic_error& e) { std::cerr << "Cannot modify in read-only mode: " << e.what() << "\n"; } // Query operations still work const auto& idx = db.get_index(); std::cout << "Row count: " << idx.row_count() << "\n"; // Switch back to read-write mode (only if opened with read_write flag) db.unset_read_only_mode(); // Now modifications work again db.create([](book& b) { b.pages = 200; }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.