diff --git a/include/bitcoin/database/error.hpp b/include/bitcoin/database/error.hpp index e6cc4876..01428c0c 100644 --- a/include/bitcoin/database/error.hpp +++ b/include/bitcoin/database/error.hpp @@ -91,6 +91,7 @@ enum error_t : uint8_t /// tables create_table, close_table, + prune_table, backup_table, restore_table, verify_table, diff --git a/include/bitcoin/database/impl/store.ipp b/include/bitcoin/database/impl/store.ipp index ab404c27..70c70435 100644 --- a/include/bitcoin/database/impl/store.ipp +++ b/include/bitcoin/database/impl/store.ipp @@ -19,6 +19,7 @@ #ifndef LIBBITCOIN_DATABASE_STORE_IPP #define LIBBITCOIN_DATABASE_STORE_IPP +#include #include #include #include @@ -49,6 +50,7 @@ const std::unordered_map CLASS::events { event_t::wait_lock, "wait_lock" }, { event_t::flush_body, "flush_body" }, + { event_t::prune_table, "prune_table" }, { event_t::backup_table, "backup_table" }, { event_t::copy_header, "copy_header" }, { event_t::archive_snapshot, "archive_snapshot" }, @@ -416,6 +418,61 @@ code CLASS::open(const event_handler& handler) NOEXCEPT return ec; } +TEMPLATE +code CLASS::prune(const event_handler& handler) NOEXCEPT +{ + while (!transactor_mutex_.try_lock_for(std::chrono::seconds(1))) + { + handler(event_t::wait_lock, table_t::store); + } + + code ec{ error::success }; + const auto prune = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT + { + if (!ec) + { + handler(event_t::prune_table, table); + if (!storage.reset()) + ec = error::prune_table; + } + }; + + const auto unload = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT + { + if (!ec) + { + handler(event_t::unload_file, table); + ec = storage.unload(); + } + }; + + const auto load = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT + { + if (!ec) + { + handler(event_t::load_file, table); + ec = storage.load(); + } + }; + + // Prevouts resettable if all candidates confirmed (fork is candidate top). + const query query_{ *this }; + if (query_.get_fork() == query_.get_top_candidate()) + { + // zeroize table head, set body logical size to zero. + prune(ec, prevout, table_t::prevout_table); + + // unmap body, setting mapped size to logical size (zero). + unload(ec, prevout_body_, table_t::prevout_body); + + // map body, making table usable again. + load(ec, prevout_body_, table_t::prevout_body); + } + + transactor_mutex_.unlock(); + return ec; +} + TEMPLATE code CLASS::snapshot(const event_handler& handler) NOEXCEPT { diff --git a/include/bitcoin/database/primitives/arraymap.hpp b/include/bitcoin/database/primitives/arraymap.hpp index 386fa431..76d7f80a 100644 --- a/include/bitcoin/database/primitives/arraymap.hpp +++ b/include/bitcoin/database/primitives/arraymap.hpp @@ -76,7 +76,7 @@ class arraymap /// Capacity of body in bytes. size_t capacity() const NOEXCEPT; - /// Increase count as neccesary to specified. + /// Increase count as necessary to specified. bool expand(const Link& count) NOEXCEPT; /// Errors. diff --git a/include/bitcoin/database/primitives/hashmap.hpp b/include/bitcoin/database/primitives/hashmap.hpp index ebb82392..7ed33102 100644 --- a/include/bitcoin/database/primitives/hashmap.hpp +++ b/include/bitcoin/database/primitives/hashmap.hpp @@ -79,7 +79,7 @@ class hashmap /// Capacity of body in bytes. size_t capacity() const NOEXCEPT; - /// Increase count as neccesary to specified. + /// Increase count as necessary to specified. bool expand(const Link& count) NOEXCEPT; /// Diagnostic counters. diff --git a/include/bitcoin/database/primitives/nomap.hpp b/include/bitcoin/database/primitives/nomap.hpp index 91b70440..09bea2ef 100644 --- a/include/bitcoin/database/primitives/nomap.hpp +++ b/include/bitcoin/database/primitives/nomap.hpp @@ -71,7 +71,7 @@ class nomap /// Reduce count as specified. bool truncate(const Link& count) NOEXCEPT; - /// Increase count as neccesary to specified. + /// Increase count as necessary to specified. bool expand(const Link& count) NOEXCEPT; /// Errors. diff --git a/include/bitcoin/database/store.hpp b/include/bitcoin/database/store.hpp index bd9b290d..7dde890e 100644 --- a/include/bitcoin/database/store.hpp +++ b/include/bitcoin/database/store.hpp @@ -63,6 +63,9 @@ class store /// Open and load the set of tables, set locks. code open(const event_handler& handler) NOEXCEPT; + /// Prune prunable tables (from loaded, leaves loaded). + code prune(const event_handler& handler) NOEXCEPT; + /// Snapshot the set of tables (from loaded, leaves loaded). code snapshot(const event_handler& handler) NOEXCEPT; diff --git a/include/bitcoin/database/tables/event.hpp b/include/bitcoin/database/tables/event.hpp index 5fe56278..654fbd97 100644 --- a/include/bitcoin/database/tables/event.hpp +++ b/include/bitcoin/database/tables/event.hpp @@ -36,6 +36,7 @@ enum class event_t wait_lock, flush_body, + prune_table, backup_table, copy_header, archive_snapshot, diff --git a/src/error.cpp b/src/error.cpp index d7bce30b..37166d67 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -83,6 +83,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) // tables { create_table, "failed to create table" }, { close_table, "failed to close table" }, + { prune_table, "failed to prune table" }, { backup_table, "failed to backup table" }, { restore_table, "failed to restore table" }, { verify_table, "failed to verify table" }, diff --git a/test/error.cpp b/test/error.cpp index 4e6164ff..de705091 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -329,6 +329,15 @@ BOOST_AUTO_TEST_CASE(error_t__code__close_table__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "failed to close table"); } +BOOST_AUTO_TEST_CASE(error_t__code__prune_table__true_exected_message) +{ + constexpr auto value = error::prune_table; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "failed to prune table"); +} + BOOST_AUTO_TEST_CASE(error_t__code__backup_table__true_exected_message) { constexpr auto value = error::backup_table; diff --git a/test/query/archive_read.cpp b/test/query/archive_read.cpp index e3369ec5..cb46e8de 100644 --- a/test/query/archive_read.cpp +++ b/test/query/archive_read.cpp @@ -40,8 +40,7 @@ struct query_archive_read_setup_fixture BOOST_FIXTURE_TEST_SUITE(query_archive_read_tests, query_archive_read_setup_fixture) -const auto events_handler = [](auto, auto) {}; - +////const auto events_handler = [](auto, auto) {}; BOOST_AUTO_TEST_CASE(query_archive_read_test) { diff --git a/test/query/consensus.cpp b/test/query/consensus.cpp index 7c9a0a2f..67647720 100644 --- a/test/query/consensus.cpp +++ b/test/query/consensus.cpp @@ -40,8 +40,7 @@ struct query_consensus_setup_fixture BOOST_FIXTURE_TEST_SUITE(query_consensus_tests, query_consensus_setup_fixture) -const auto events_handler = [](auto, auto) {}; - +////const auto events_handler = [](auto, auto) {}; BOOST_AUTO_TEST_CASE(query_consensus_test) { diff --git a/test/query/height.cpp b/test/query/height.cpp index c3ecfbbc..3b0352bf 100644 --- a/test/query/height.cpp +++ b/test/query/height.cpp @@ -40,8 +40,7 @@ struct query_height_setup_fixture BOOST_FIXTURE_TEST_SUITE(query_height_tests, query_height_setup_fixture) -const auto events_handler = [](auto, auto) {}; - +////const auto events_handler = [](auto, auto) {}; BOOST_AUTO_TEST_CASE(query_height_test) { diff --git a/test/query/network.cpp b/test/query/network.cpp index 51d9012b..99026d28 100644 --- a/test/query/network.cpp +++ b/test/query/network.cpp @@ -40,8 +40,7 @@ struct query_network_setup_fixture BOOST_FIXTURE_TEST_SUITE(query_network_tests, query_network_setup_fixture) -const auto events_handler = [](auto, auto) {}; - +////const auto events_handler = [](auto, auto) {}; BOOST_AUTO_TEST_CASE(query_network_test) { diff --git a/test/query/objects.cpp b/test/query/objects.cpp index 4ec1ac52..c98dd1a4 100644 --- a/test/query/objects.cpp +++ b/test/query/objects.cpp @@ -40,8 +40,7 @@ struct query_objects_setup_fixture BOOST_FIXTURE_TEST_SUITE(query_objects_tests, query_objects_setup_fixture) -const auto events_handler = [](auto, auto) {}; - +////const auto events_handler = [](auto, auto) {}; BOOST_AUTO_TEST_CASE(query_objects_test) { diff --git a/test/store.cpp b/test/store.cpp index ed660bba..4522f138 100644 --- a/test/store.cpp +++ b/test/store.cpp @@ -17,6 +17,7 @@ * along with this program. If not, see . */ #include "test.hpp" +#include "mocks/blocks.hpp" #include "mocks/map_store.hpp" // these are the slow tests (mmap) @@ -274,6 +275,22 @@ BOOST_AUTO_TEST_CASE(store__open__created__success) BOOST_REQUIRE(!instance.close(events)); } +// prune +// ---------------------------------------------------------------------------- +// Empty store asserts so create and initialize. + +BOOST_AUTO_TEST_CASE(store__prune__initialized__success) +{ + settings configuration{}; + configuration.path = TEST_DIRECTORY; + store instance{ configuration }; + query> query_{ instance }; + BOOST_REQUIRE(!instance.create(events)); + BOOST_REQUIRE(query_.initialize(test::genesis)); + BOOST_REQUIRE(!instance.prune(events)); + BOOST_REQUIRE(!instance.close(events)); +} + // snapshot // ---------------------------------------------------------------------------- diff --git a/test/tables/caches/prevout.cpp b/test/tables/caches/prevout.cpp index 145419f4..d3d19846 100644 --- a/test/tables/caches/prevout.cpp +++ b/test/tables/caches/prevout.cpp @@ -25,7 +25,6 @@ BOOST_AUTO_TEST_SUITE(prevout_tests) using namespace system; using namespace system::chain; using tx = schema::transaction::link; -constexpr auto terminal = schema::transaction::link::terminal; const std::vector conflicts1{ 0x01020304 }; const std::vector conflicts2{ 0xbaadf00d, 0x01020304 }; diff --git a/test/tables/caches/validated_bk.cpp b/test/tables/caches/validated_bk.cpp index 40e84b67..5c462d8a 100644 --- a/test/tables/caches/validated_bk.cpp +++ b/test/tables/caches/validated_bk.cpp @@ -64,11 +64,8 @@ BOOST_AUTO_TEST_CASE(validated_bk__put__two__expected) table::validated_bk instance{ head_store, body_store, 8 }; BOOST_REQUIRE(instance.create()); - table::validated_bk::link link1{}; BOOST_REQUIRE(instance.put(0, slab1)); BOOST_REQUIRE_EQUAL(instance.at(0), 0u); - - table::validated_bk::link link2{}; BOOST_REQUIRE(instance.put(1, slab2)); BOOST_REQUIRE_EQUAL(instance.at(1), 10u);