Faster block existence check when the block type is known (#1484)

This commit is contained in:
cryptocode 2018-12-19 19:25:06 +01:00 committed by Roy Keene
commit dc11556491
6 changed files with 71 additions and 33 deletions

View file

@ -1369,46 +1369,74 @@ void rai::mdb_store::block_del (rai::transaction const & transaction_a, rai::blo
}
}
bool rai::mdb_store::block_exists (rai::transaction const & transaction_a, rai::block_hash const & hash_a)
bool rai::mdb_store::block_exists (rai::transaction const & transaction_a, rai::block_type type, rai::block_hash const & hash_a)
{
auto exists (true);
auto exists (false);
rai::mdb_val junk;
auto status (mdb_get (env.tx (transaction_a), send_blocks, rai::mdb_val (hash_a), junk));
assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
if (!exists)
switch (type)
{
auto status (mdb_get (env.tx (transaction_a), receive_blocks, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
if (!exists)
case rai::block_type::send:
{
auto status (mdb_get (env.tx (transaction_a), send_blocks, rai::mdb_val (hash_a), junk));
assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
break;
}
case rai::block_type::receive:
{
auto status (mdb_get (env.tx (transaction_a), receive_blocks, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
break;
}
case rai::block_type::open:
{
auto status (mdb_get (env.tx (transaction_a), open_blocks, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
break;
}
case rai::block_type::change:
{
auto status (mdb_get (env.tx (transaction_a), change_blocks, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
break;
}
case rai::block_type::state:
{
auto status (mdb_get (env.tx (transaction_a), state_blocks_v0, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
if (!exists)
{
auto status (mdb_get (env.tx (transaction_a), change_blocks, rai::mdb_val (hash_a), junk));
auto status (mdb_get (env.tx (transaction_a), state_blocks_v1, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
if (!exists)
{
auto status (mdb_get (env.tx (transaction_a), state_blocks_v0, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
if (!exists)
{
auto status (mdb_get (env.tx (transaction_a), state_blocks_v1, rai::mdb_val (hash_a), junk));
release_assert (status == 0 || status == MDB_NOTFOUND);
exists = status == 0;
}
}
}
break;
}
case rai::block_type::invalid:
case rai::block_type::not_a_block:
break;
}
return exists;
}
bool rai::mdb_store::block_exists (rai::transaction const & tx_a, rai::block_hash const & hash_a)
{
// clang-format off
return
block_exists (tx_a, rai::block_type::send, hash_a) ||
block_exists (tx_a, rai::block_type::receive, hash_a) ||
block_exists (tx_a, rai::block_type::open, hash_a) ||
block_exists (tx_a, rai::block_type::change, hash_a) ||
block_exists (tx_a, rai::block_type::state, hash_a);
// clang-format on
}
rai::block_counts rai::mdb_store::block_count (rai::transaction const & transaction_a)
{
rai::block_counts result;

View file

@ -159,6 +159,7 @@ public:
std::shared_ptr<rai::block> block_random (rai::transaction const &) override;
void block_del (rai::transaction const &, rai::block_hash const &) override;
bool block_exists (rai::transaction const &, rai::block_hash const &) override;
bool block_exists (rai::transaction const &, rai::block_type, rai::block_hash const &) override;
rai::block_counts block_count (rai::transaction const &) override;
bool root_exists (rai::transaction const &, rai::uint256_union const &) override;

View file

@ -1866,7 +1866,7 @@ void rai::node::send_keepalive (rai::endpoint const & endpoint_a)
void rai::node::process_fork (rai::transaction const & transaction_a, std::shared_ptr<rai::block> block_a)
{
auto root (block_a->root ());
if (!store.block_exists (transaction_a, block_a->hash ()) && store.root_exists (transaction_a, block_a->root ()))
if (!store.block_exists (transaction_a, block_a->type (), block_a->hash ()) && store.root_exists (transaction_a, block_a->root ()))
{
std::shared_ptr<rai::block> ledger_block (ledger.forked_block (transaction_a, *block_a));
if (ledger_block)
@ -2645,13 +2645,13 @@ public:
void rai::node::process_confirmed (std::shared_ptr<rai::block> block_a)
{
auto hash (block_a->hash ());
bool exists (ledger.block_exists (hash));
bool exists (ledger.block_exists (block_a->type (), hash));
// Attempt to process confirmed block if it's not in ledger yet
if (!exists)
{
auto transaction (store.tx_begin_write ());
block_processor.process_receive_one (transaction, block_a);
exists = store.block_exists (transaction, hash);
exists = store.block_exists (transaction, block_a->type (), hash);
}
if (exists)
{

View file

@ -200,6 +200,7 @@ public:
virtual std::shared_ptr<rai::block> block_random (rai::transaction const &) = 0;
virtual void block_del (rai::transaction const &, rai::block_hash const &) = 0;
virtual bool block_exists (rai::transaction const &, rai::block_hash const &) = 0;
virtual bool block_exists (rai::transaction const &, rai::block_type, rai::block_hash const &) = 0;
virtual rai::block_counts block_count (rai::transaction const &) = 0;
virtual bool root_exists (rai::transaction const &, rai::uint256_union const &) = 0;

View file

@ -217,7 +217,7 @@ void ledger_processor::state_block (rai::state_block const & block_a)
void ledger_processor::state_block_impl (rai::state_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block before? (Unambiguous)
if (result.code == rai::process_result::progress)
{
@ -328,7 +328,7 @@ void ledger_processor::state_block_impl (rai::state_block const & block_a)
void ledger_processor::epoch_block_impl (rai::state_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block before? (Unambiguous)
if (result.code == rai::process_result::progress)
{
@ -391,7 +391,7 @@ void ledger_processor::epoch_block_impl (rai::state_block const & block_a)
void ledger_processor::change_block (rai::change_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block before? (Harmless)
if (result.code == rai::process_result::progress)
{
@ -433,7 +433,7 @@ void ledger_processor::change_block (rai::change_block const & block_a)
void ledger_processor::send_block (rai::send_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block before? (Harmless)
if (result.code == rai::process_result::progress)
{
@ -480,7 +480,7 @@ void ledger_processor::send_block (rai::send_block const & block_a)
void ledger_processor::receive_block (rai::receive_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block already? (Harmless)
if (result.code == rai::process_result::progress)
{
@ -545,7 +545,7 @@ void ledger_processor::receive_block (rai::receive_block const & block_a)
void ledger_processor::open_block (rai::open_block const & block_a)
{
auto hash (block_a.hash ());
auto existing (ledger.store.block_exists (transaction, hash));
auto existing (ledger.store.block_exists (transaction, block_a.type (), hash));
result.code = existing ? rai::process_result::old : rai::process_result::progress; // Have we seen this block already? (Harmless)
if (result.code == rai::process_result::progress)
{
@ -685,6 +685,13 @@ bool rai::ledger::block_exists (rai::block_hash const & hash_a)
return result;
}
bool rai::ledger::block_exists (rai::block_type type, rai::block_hash const & hash_a)
{
auto transaction (store.tx_begin_read ());
auto result (store.block_exists (transaction, type, hash_a));
return result;
}
std::string rai::ledger::block_text (char const * hash_a)
{
return block_text (rai::block_hash (hash_a));
@ -1005,7 +1012,7 @@ std::shared_ptr<rai::block> rai::ledger::successor (rai::transaction const & tra
std::shared_ptr<rai::block> rai::ledger::forked_block (rai::transaction const & transaction_a, rai::block const & block_a)
{
assert (!store.block_exists (transaction_a, block_a.hash ()));
assert (!store.block_exists (transaction_a, block_a.type (), block_a.hash ()));
auto root (block_a.root ());
assert (store.block_exists (transaction_a, root) || store.account_exists (transaction_a, root));
auto result (store.block_get (transaction_a, store.block_successor (transaction_a, root)));

View file

@ -31,6 +31,7 @@ public:
rai::block_hash representative (rai::transaction const &, rai::block_hash const &);
rai::block_hash representative_calculated (rai::transaction const &, rai::block_hash const &);
bool block_exists (rai::block_hash const &);
bool block_exists (rai::block_type, rai::block_hash const &);
std::string block_text (char const *);
std::string block_text (rai::block_hash const &);
bool is_send (rai::transaction const &, rai::state_block const &);