Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract recently_confirmed container out of active_transactions #3887

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4280,7 +4280,7 @@ TEST (rep_crawler, recently_confirmed)
auto & node1 (*system.nodes[0]);
ASSERT_EQ (1, node1.ledger.cache.block_count);
auto const block = nano::dev::genesis;
node1.active.add_recently_confirmed (block->qualified_root (), block->hash ());
node1.active.recently_confirmed.put (block->qualified_root (), block->hash ());
auto & node2 (*system.add_node ());
system.wallet (1)->insert_adhoc (nano::dev::genesis_key.prv);
auto channel = node1.network.find_channel (node2.network.endpoint ());
Expand Down
84 changes: 59 additions & 25 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ nano::active_transactions::active_transactions (nano::node & node_a, nano::confi
node{ node_a },
generator{ node_a.config, node_a.ledger, node_a.wallets, node_a.vote_processor, node_a.history, node_a.network, node_a.stats, false },
final_generator{ node_a.config, node_a.ledger, node_a.wallets, node_a.vote_processor, node_a.history, node_a.network, node_a.stats, true },
recently_confirmed{ 65536 },
election_time_to_live{ node_a.network_params.network.is_dev_network () ? 0s : 2s },
thread ([this] () {
nano::thread_role::set (nano::thread_role::name::request_loop);
Expand Down Expand Up @@ -372,7 +373,7 @@ nano::election_insertion_result nano::active_transactions::insert_impl (nano::un
auto existing (roots.get<tag_root> ().find (root));
if (existing == roots.get<tag_root> ().end ())
{
if (recently_confirmed.get<tag_root> ().find (root) == recently_confirmed.get<tag_root> ().end ())
if (!recently_confirmed.exists (root))
{
result.inserted = true;
auto hash (block_a->hash ());
Expand Down Expand Up @@ -447,13 +448,12 @@ nano::vote_code nano::active_transactions::vote (std::shared_ptr<nano::vote> con
nano::unique_lock<nano::mutex> lock (mutex);
for (auto const & hash : vote_a->hashes)
{
auto & recently_confirmed_by_hash (recently_confirmed.get<tag_hash> ());
auto existing (blocks.find (hash));
if (existing != blocks.end ())
{
process.emplace_back (existing->second, hash);
}
else if (recently_confirmed_by_hash.count (hash) == 0)
else if (!recently_confirmed.exists (hash))
{
add_inactive_votes_cache (lock, hash, vote_a->account, vote_a->timestamp ());
}
Expand Down Expand Up @@ -547,22 +547,6 @@ void nano::active_transactions::add_recently_cemented (nano::election_status con
}
}

void nano::active_transactions::add_recently_confirmed (nano::qualified_root const & root_a, nano::block_hash const & hash_a)
{
nano::lock_guard<nano::mutex> guard (mutex);
recently_confirmed.get<tag_sequence> ().emplace_back (root_a, hash_a);
if (recently_confirmed.size () > recently_confirmed_size)
{
recently_confirmed.get<tag_sequence> ().pop_front ();
}
}

void nano::active_transactions::erase_recently_confirmed (nano::block_hash const & hash_a)
{
nano::lock_guard<nano::mutex> guard (mutex);
recently_confirmed.get<tag_hash> ().erase (hash_a);
}

void nano::active_transactions::erase (nano::block const & block_a)
{
erase (block_a.qualified_root ());
Expand Down Expand Up @@ -869,11 +853,6 @@ std::size_t nano::active_transactions::election_winner_details_size ()
return election_winner_details.size ();
}

nano::cementable_account::cementable_account (nano::account const & account_a, std::size_t blocks_uncemented_a) :
account (account_a), blocks_uncemented (blocks_uncemented_a)
{
}

std::unique_ptr<nano::container_info_component> nano::collect_container_info (active_transactions & active_transactions, std::string const & name)
{
std::size_t roots_count;
Expand All @@ -893,9 +872,64 @@ std::unique_ptr<nano::container_info_component> nano::collect_container_info (ac
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "roots", roots_count, sizeof (decltype (active_transactions.roots)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "blocks", blocks_count, sizeof (decltype (active_transactions.blocks)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "election_winner_details", active_transactions.election_winner_details_size (), sizeof (decltype (active_transactions.election_winner_details)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "recently_confirmed", recently_confirmed_count, sizeof (decltype (active_transactions.recently_confirmed)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "recently_confirmed", recently_confirmed_count, sizeof (decltype (active_transactions.recently_confirmed.confirmed)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "recently_cemented", recently_cemented_count, sizeof (decltype (active_transactions.recently_cemented)::value_type) }));
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "inactive_votes_cache", active_transactions.inactive_votes_cache_size (), sizeof (nano::gap_information) }));
composite->add_component (collect_container_info (active_transactions.generator, "generator"));
return composite;
}

/*
* class recently_confirmed
*/

nano::recently_confirmed_cache::recently_confirmed_cache (std::size_t max_size_a) :
max_size{ max_size_a }
{
}

void nano::recently_confirmed_cache::put (const nano::qualified_root & root, const nano::block_hash & hash)
{
nano::lock_guard<nano::mutex> guard{ mutex };
confirmed.get<tag_sequence> ().emplace_back (root, hash);
if (confirmed.size () > max_size)
{
confirmed.get<tag_sequence> ().pop_front ();
}
}

void nano::recently_confirmed_cache::erase (const nano::block_hash & hash)
{
nano::lock_guard<nano::mutex> guard{ mutex };
confirmed.get<tag_hash> ().erase (hash);
}

void nano::recently_confirmed_cache::clear ()
{
nano::lock_guard<nano::mutex> guard{ mutex };
confirmed.clear ();
}

bool nano::recently_confirmed_cache::exists (const nano::block_hash & hash) const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return confirmed.get<tag_hash> ().find (hash) != confirmed.get<tag_hash> ().end ();
}

bool nano::recently_confirmed_cache::exists (const nano::qualified_root & root) const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return confirmed.get<tag_root> ().find (root) != confirmed.get<tag_root> ().end ();
}

std::size_t nano::recently_confirmed_cache::size () const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return confirmed.size ();
}

nano::recently_confirmed_cache::entry_t nano::recently_confirmed_cache::back () const
{
nano::lock_guard<nano::mutex> guard{ mutex };
return confirmed.back ();
}
58 changes: 39 additions & 19 deletions nano/node/active_transactions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace mi = boost::multi_index;
namespace nano
{
class node;
class active_transactions;
class block;
class block_sideband;
class election;
Expand All @@ -38,12 +39,44 @@ class transaction;
class confirmation_height_processor;
class stat;

class cementable_account final
class recently_confirmed_cache final
{
public:
cementable_account (nano::account const & account_a, std::size_t blocks_uncemented_a);
nano::account account;
uint64_t blocks_uncemented{ 0 };
using entry_t = std::pair<nano::qualified_root, nano::block_hash>;

explicit recently_confirmed_cache (std::size_t max_size);

void put (nano::qualified_root const &, nano::block_hash const &);
void erase (nano::block_hash const &);
void clear ();
std::size_t size () const;

bool exists (nano::qualified_root const &) const;
bool exists (nano::block_hash const &) const;

public: // Tests
entry_t back () const;

private:
// clang-format off
class tag_root {};
class tag_hash {};

using ordered_recent_confirmations = boost::multi_index_container<entry_t,
mi::indexed_by<
mi::sequenced<mi::tag<tag_sequence>>,
mi::hashed_unique<mi::tag<tag_root>,
mi::member<entry_t, nano::qualified_root, &entry_t::first>>,
mi::hashed_unique<mi::tag<tag_hash>,
mi::member<entry_t, nano::block_hash, &entry_t::second>>>>;
// clang-format on
ordered_recent_confirmations confirmed;

std::size_t const max_size;

mutable nano::mutex mutex;

friend std::unique_ptr<container_info_component> collect_container_info (active_transactions &, std::string const &);
};

class election_insertion_result final
Expand Down Expand Up @@ -118,8 +151,6 @@ class active_transactions final
std::deque<nano::election_status> recently_cemented;

void add_recently_cemented (nano::election_status const &);
void add_recently_confirmed (nano::qualified_root const &, nano::block_hash const &);
void erase_recently_confirmed (nano::block_hash const &);
void add_inactive_votes_cache (nano::unique_lock<nano::mutex> &, nano::block_hash const &, nano::account const &, uint64_t const);
// Inserts an election if conditions are met
void trigger_inactive_votes_cache_election (std::shared_ptr<nano::block> const &);
Expand All @@ -137,6 +168,8 @@ class active_transactions final
nano::vote_generator generator;
nano::vote_generator final_generator;

recently_confirmed_cache recently_confirmed;

#ifdef MEMORY_POOL_DISABLED
using allocator = std::allocator<nano::inactive_cache_information>;
#else
Expand Down Expand Up @@ -177,19 +210,6 @@ class active_transactions final
// Maximum time an election can be kept active if it is extending the container
std::chrono::seconds const election_time_to_live;

static std::size_t constexpr recently_confirmed_size{ 65536 };
using recent_confirmation = std::pair<nano::qualified_root, nano::block_hash>;
// clang-format off
boost::multi_index_container<recent_confirmation,
mi::indexed_by<
mi::sequenced<mi::tag<tag_sequence>>,
mi::hashed_unique<mi::tag<tag_root>,
mi::member<recent_confirmation, nano::qualified_root, &recent_confirmation::first>>,
mi::hashed_unique<mi::tag<tag_hash>,
mi::member<recent_confirmation, nano::block_hash, &recent_confirmation::second>>>>
recently_confirmed;
// clang-format on

int active_hinted_elections_count{ 0 };

ordered_cache inactive_votes_cache;
Expand Down
2 changes: 1 addition & 1 deletion nano/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1401,7 +1401,7 @@ void nano::node::process_confirmed (nano::election_status const & status_a, uint
auto const num_iters = (config.block_processor_batch_max_time / network_params.node.process_confirmed_interval) * 4;
if (auto block_l = ledger.store.block.get (ledger.store.tx_begin_read (), hash))
{
active.add_recently_confirmed (block_l->qualified_root (), hash);
active.recently_confirmed.put (block_l->qualified_root (), hash);
confirmation_height_processor.add (block_l);
}
else if (iteration_a < num_iters)
Expand Down
3 changes: 2 additions & 1 deletion nano/node/repcrawler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ void nano::rep_crawler::query (std::vector<std::shared_ptr<nano::transport::chan
}
if (!channels_a.empty ())
{
node.active.erase_recently_confirmed (hash_root.first);
// In case our random block is a recently confirmed one, we remove an entry otherwise votes will be marked as replay and not forwarded to repcrawler
node.active.recently_confirmed.erase (hash_root.first);
}
for (auto i (channels_a.begin ()), n (channels_a.end ()); i != n; ++i)
{
Expand Down