|
19 | 19 | #ifndef LIBBITCOIN_DATABASE_STORE_IPP |
20 | 20 | #define LIBBITCOIN_DATABASE_STORE_IPP |
21 | 21 |
|
| 22 | +#include <chrono> |
22 | 23 | #include <unordered_map> |
23 | 24 | #include <bitcoin/system.hpp> |
24 | 25 | #include <bitcoin/database/boost.hpp> |
@@ -49,6 +50,7 @@ const std::unordered_map<event_t, std::string> CLASS::events |
49 | 50 |
|
50 | 51 | { event_t::wait_lock, "wait_lock" }, |
51 | 52 | { event_t::flush_body, "flush_body" }, |
| 53 | + { event_t::prune_table, "prune_table" }, |
52 | 54 | { event_t::backup_table, "backup_table" }, |
53 | 55 | { event_t::copy_header, "copy_header" }, |
54 | 56 | { event_t::archive_snapshot, "archive_snapshot" }, |
@@ -416,6 +418,61 @@ code CLASS::open(const event_handler& handler) NOEXCEPT |
416 | 418 | return ec; |
417 | 419 | } |
418 | 420 |
|
| 421 | +TEMPLATE |
| 422 | +code CLASS::prune(const event_handler& handler) NOEXCEPT |
| 423 | +{ |
| 424 | + while (!transactor_mutex_.try_lock_for(std::chrono::seconds(1))) |
| 425 | + { |
| 426 | + handler(event_t::wait_lock, table_t::store); |
| 427 | + } |
| 428 | + |
| 429 | + code ec{ error::success }; |
| 430 | + const auto prune = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT |
| 431 | + { |
| 432 | + if (!ec) |
| 433 | + { |
| 434 | + handler(event_t::prune_table, table); |
| 435 | + if (!storage.reset()) |
| 436 | + ec = error::prune_table; |
| 437 | + } |
| 438 | + }; |
| 439 | + |
| 440 | + const auto unload = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT |
| 441 | + { |
| 442 | + if (!ec) |
| 443 | + { |
| 444 | + handler(event_t::unload_file, table); |
| 445 | + ec = storage.unload(); |
| 446 | + } |
| 447 | + }; |
| 448 | + |
| 449 | + const auto load = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT |
| 450 | + { |
| 451 | + if (!ec) |
| 452 | + { |
| 453 | + handler(event_t::load_file, table); |
| 454 | + ec = storage.load(); |
| 455 | + } |
| 456 | + }; |
| 457 | + |
| 458 | + // Prevouts resettable if all candidates confirmed (fork is candidate top). |
| 459 | + const query<CLASS> query_{ *this }; |
| 460 | + if (query_.get_fork() == query_.get_top_candidate()) |
| 461 | + { |
| 462 | + // zeroize table head, set body logical size to zero. |
| 463 | + prune(ec, prevout, table_t::prevout_table); |
| 464 | + |
| 465 | + // unmap body, setting mapped size to logical size (zero). |
| 466 | + unload(ec, prevout_body_, table_t::prevout_body); |
| 467 | + |
| 468 | + // map body, making table usable again. |
| 469 | + load(ec, prevout_body_, table_t::prevout_body); |
| 470 | + } |
| 471 | + |
| 472 | + transactor_mutex_.unlock(); |
| 473 | + return ec; |
| 474 | +} |
| 475 | + |
419 | 476 | TEMPLATE |
420 | 477 | code CLASS::snapshot(const event_handler& handler) NOEXCEPT |
421 | 478 | { |
|
0 commit comments