Skip to content

Commit a88b6cb

Browse files
authored
Merge pull request #663 from evoskuil/master
Refactor prune() to be backup/restore safe.
2 parents dbe9b74 + 32fa5f8 commit a88b6cb

File tree

9 files changed

+67
-62
lines changed

9 files changed

+67
-62
lines changed

include/bitcoin/database/impl/primitives/arraymap.ipp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,21 @@ bool CLASS::close() NOEXCEPT
5050
}
5151

5252
TEMPLATE
53-
bool CLASS::reset() NOEXCEPT
53+
bool CLASS::clear() NOEXCEPT
5454
{
55-
Link count{};
56-
return head_.clear() && head_.get_body_count(count) &&
57-
body_.truncate(count);
55+
// Head is nullified and its body reference is zeroized. Body memory
56+
// recovery requires truncate/unload/load, which should be preceded by a
57+
// snapshot as all existing snapshots will be invalidated by the truncate.
58+
// An intervening snapshot will capture the zero count body reference (and
59+
// null head links) and will therefore be recoverable whether or not the
60+
// truncation succeeds.
61+
return head_.clear();
5862
}
5963

6064
TEMPLATE
61-
bool CLASS::backup() NOEXCEPT
65+
bool CLASS::backup(bool prune) NOEXCEPT
6266
{
63-
return head_.set_body_count(body_.count());
67+
return head_.set_body_count(prune ? Link{ 0 } : body_.count());
6468
}
6569

6670
TEMPLATE

include/bitcoin/database/impl/primitives/hashmap.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ bool CLASS::close() NOEXCEPT
5151
}
5252

5353
TEMPLATE
54-
bool CLASS::backup() NOEXCEPT
54+
bool CLASS::backup(bool) NOEXCEPT
5555
{
5656
return head_.set_body_count(body_.count());
5757
}

include/bitcoin/database/impl/primitives/nomap.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ bool CLASS::close() NOEXCEPT
4949
}
5050

5151
TEMPLATE
52-
bool CLASS::backup() NOEXCEPT
52+
bool CLASS::backup(bool) NOEXCEPT
5353
{
5454
return head_.set_body_count(manager_.count());
5555
}

include/bitcoin/database/impl/store.ipp

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -429,59 +429,59 @@ code CLASS::prune(const event_handler& handler) NOEXCEPT
429429
}
430430

431431
code ec{ error::success };
432-
const auto prune = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT
433-
{
434-
if (!ec)
435-
{
436-
handler(event_t::prune_table, table);
437-
if (!storage.reset())
438-
ec = error::prune_table;
439-
}
440-
};
441-
442-
const auto unload = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT
443-
{
444-
if (!ec)
445-
{
446-
handler(event_t::unload_file, table);
447-
ec = storage.unload();
448-
}
449-
};
450-
451-
const auto load = [&handler](code& ec, auto& storage, table_t table) NOEXCEPT
452-
{
453-
if (!ec)
454-
{
455-
handler(event_t::load_file, table);
456-
ec = storage.load();
457-
}
458-
};
459432

460433
// Prevouts resettable if all candidates confirmed (fork is candidate top).
461-
if (query<CLASS>{ *this }.is_coalesced())
434+
if (!query<CLASS>{ *this }.is_coalesced())
462435
{
463-
// zeroize table head, set body logical size to zero.
464-
prune(ec, prevout, table_t::prevout_table);
465-
466-
// unmap body, setting mapped size to logical size (zero).
467-
unload(ec, prevout_body_, table_t::prevout_body);
468-
469-
// map body, making table usable again.
470-
load(ec, prevout_body_, table_t::prevout_body);
436+
ec = error::not_coalesced;
471437
}
472438
else
473439
{
474-
ec = error::not_coalesced;
440+
// nullify table head, set reference body count to zero.
441+
handler(event_t::prune_table, table_t::prevout_head);
442+
if (!prevout.clear())
443+
{
444+
ec = error::prune_table;
445+
}
446+
else
447+
{
448+
// Snapshot with nullified head and zero body count.
449+
// The 'prune' parameter signals to not reset body count.
450+
ec = snapshot(handler, true);
451+
452+
if (!ec)
453+
{
454+
// zeroize table body, set logical body count to zero.
455+
handler(event_t::prune_table, table_t::prevout_body);
456+
if (!prevout_body_.truncate(zero))
457+
{
458+
ec = error::prune_table;
459+
}
460+
else
461+
{
462+
// unmap body, setting mapped size to logical size (zero).
463+
handler(event_t::unload_file, table_t::prevout_body);
464+
ec = prevout_body_.unload();
465+
466+
if (!ec)
467+
{
468+
// map body, making table usable again.
469+
handler(event_t::load_file, table_t::prevout_body);
470+
ec = prevout_body_.load();
471+
}
472+
}
473+
}
474+
}
475475
}
476476

477477
transactor_mutex_.unlock();
478478
return ec;
479479
}
480480

481481
TEMPLATE
482-
code CLASS::snapshot(const event_handler& handler) NOEXCEPT
482+
code CLASS::snapshot(const event_handler& handler, bool prune) NOEXCEPT
483483
{
484-
while (!transactor_mutex_.try_lock_for(std::chrono::seconds(1)))
484+
while (!prune && !transactor_mutex_.try_lock_for(std::chrono::seconds(1)))
485485
{
486486
handler(event_t::wait_lock, table_t::store);
487487
}
@@ -511,16 +511,16 @@ code CLASS::snapshot(const event_handler& handler) NOEXCEPT
511511
flush(ec, strong_tx_body_, table_t::strong_tx_body);
512512

513513
flush(ec, duplicate_body_, table_t::duplicate_body);
514-
flush(ec, prevout_body_, table_t::prevout_body);
514+
if (!prune) flush(ec, prevout_body_, table_t::prevout_body);
515515
flush(ec, validated_bk_body_, table_t::validated_bk_body);
516516
flush(ec, validated_tx_body_, table_t::validated_tx_body);
517517

518518
flush(ec, address_body_, table_t::address_body);
519519
flush(ec, filter_bk_body_, table_t::filter_bk_body);
520520
flush(ec, filter_tx_body_, table_t::filter_tx_body);
521521

522-
if (!ec) ec = backup(handler);
523-
transactor_mutex_.unlock();
522+
if (!ec) ec = backup(handler, prune);
523+
if (!prune) transactor_mutex_.unlock();
524524
return ec;
525525
}
526526

@@ -863,16 +863,16 @@ code CLASS::unload_close(const event_handler& handler) NOEXCEPT
863863
}
864864

865865
TEMPLATE
866-
code CLASS::backup(const event_handler& handler) NOEXCEPT
866+
code CLASS::backup(const event_handler& handler, bool prune) NOEXCEPT
867867
{
868868
code ec{ error::success };
869869
const auto backup = [&handler](code& ec, auto& storage,
870-
table_t table) NOEXCEPT
870+
table_t table, bool prune=false) NOEXCEPT
871871
{
872872
if (!ec)
873873
{
874874
handler(event_t::backup_table, table);
875-
if (!storage.backup())
875+
if (!storage.backup(prune))
876876
ec = error::backup_table;
877877
}
878878
};
@@ -891,7 +891,7 @@ code CLASS::backup(const event_handler& handler) NOEXCEPT
891891
backup(ec, strong_tx, table_t::strong_tx_table);
892892

893893
backup(ec, duplicate, table_t::duplicate_table);
894-
backup(ec, prevout, table_t::prevout_table);
894+
backup(ec, prevout, table_t::prevout_table, prune);
895895
backup(ec, validated_bk, table_t::validated_bk_table);
896896
backup(ec, validated_tx, table_t::validated_tx_table);
897897

include/bitcoin/database/primitives/arraymap.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ class arraymap
5050

5151
bool create() NOEXCEPT;
5252
bool close() NOEXCEPT;
53-
bool reset() NOEXCEPT;
54-
bool backup() NOEXCEPT;
53+
bool clear() NOEXCEPT;
54+
bool backup(bool prune=false) NOEXCEPT;
5555
bool restore() NOEXCEPT;
5656
bool verify() const NOEXCEPT;
5757

include/bitcoin/database/primitives/hashmap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class hashmap
5454

5555
bool create() NOEXCEPT;
5656
bool close() NOEXCEPT;
57-
bool backup() NOEXCEPT;
57+
bool backup(bool=false) NOEXCEPT;
5858
bool restore() NOEXCEPT;
5959
bool verify() const NOEXCEPT;
6060

include/bitcoin/database/primitives/nomap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class nomap
4646

4747
bool create() NOEXCEPT;
4848
bool close() NOEXCEPT;
49-
bool backup() NOEXCEPT;
49+
bool backup(bool=false) NOEXCEPT;
5050
bool restore() NOEXCEPT;
5151
bool verify() const NOEXCEPT;
5252

include/bitcoin/database/store.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class store
6767
code prune(const event_handler& handler) NOEXCEPT;
6868

6969
/// Snapshot the set of tables (from loaded, leaves loaded).
70-
code snapshot(const event_handler& handler) NOEXCEPT;
70+
code snapshot(const event_handler& handler, bool prune=false) NOEXCEPT;
7171

7272
/// Restore the most recent snapshot (from closed, leaves loaded).
7373
code restore(const event_handler& handler) NOEXCEPT;
@@ -125,7 +125,7 @@ class store
125125
protected:
126126
code open_load(const event_handler& handler) NOEXCEPT;
127127
code unload_close(const event_handler& handler) NOEXCEPT;
128-
code backup(const event_handler& handler) NOEXCEPT;
128+
code backup(const event_handler& handler, bool prune=false) NOEXCEPT;
129129
code dump(const std::filesystem::path& folder,
130130
const event_handler& handler) NOEXCEPT;
131131

test/primitives/arraymap.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -834,16 +834,17 @@ BOOST_AUTO_TEST_CASE(arraymap__record_body_count__nine_close__nine)
834834
BOOST_REQUIRE(!instance.get_fault());
835835
}
836836

837+
// Close resets the cleared body count.
837838
BOOST_AUTO_TEST_CASE(arraymap__reset__nine_close__zero)
838839
{
839840
data_chunk head(initial_head_size, 0xff);
840841
auto body = base16_chunk("112233441122334411223344112233441122334411223344112233441122334411223344");
841842
test::chunk_storage head_store{ head };
842843
test::chunk_storage body_store{ body };
843844
record_table instance{ head_store, body_store, initial_buckets };
844-
BOOST_REQUIRE(instance.reset());
845+
BOOST_REQUIRE(instance.clear());
845846
BOOST_REQUIRE(instance.close());
846-
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
847+
BOOST_REQUIRE_EQUAL(head_store.buffer(), base16_chunk("090000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
847848
BOOST_REQUIRE(!instance.get_fault());
848849
}
849850

0 commit comments

Comments
 (0)