Merge pull request #3809 from clemahieu/bootstrap_cleanup

Bootstrap cleanup
This commit is contained in:
clemahieu 2022-05-05 19:59:58 +01:00 committed by GitHub
commit 837259c0dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 58 additions and 130 deletions

View file

@ -8,6 +8,7 @@
#include <boost/format.hpp>
#include <algorithm>
#include <memory>
nano::bootstrap_initiator::bootstrap_initiator (nano::node & node_a) :
node (node_a)
@ -233,16 +234,16 @@ std::shared_ptr<nano::bootstrap_attempt> nano::bootstrap_initiator::current_atte
return find_attempt (nano::bootstrap_mode::legacy);
}
std::shared_ptr<nano::bootstrap_attempt> nano::bootstrap_initiator::current_lazy_attempt ()
std::shared_ptr<nano::bootstrap_attempt_lazy> nano::bootstrap_initiator::current_lazy_attempt ()
{
nano::lock_guard<nano::mutex> lock (mutex);
return find_attempt (nano::bootstrap_mode::lazy);
return std::dynamic_pointer_cast<nano::bootstrap_attempt_lazy> (find_attempt (nano::bootstrap_mode::lazy));
}
std::shared_ptr<nano::bootstrap_attempt> nano::bootstrap_initiator::current_wallet_attempt ()
std::shared_ptr<nano::bootstrap_attempt_wallet> nano::bootstrap_initiator::current_wallet_attempt ()
{
nano::lock_guard<nano::mutex> lock (mutex);
return find_attempt (nano::bootstrap_mode::wallet_lazy);
return std::dynamic_pointer_cast<nano::bootstrap_attempt_wallet> (find_attempt (nano::bootstrap_mode::wallet_lazy));
}
void nano::bootstrap_initiator::stop_attempts ()

View file

@ -80,6 +80,8 @@ public:
std::map<uint64_t, std::shared_ptr<nano::bootstrap_attempt>> attempts;
};
class bootstrap_attempt_lazy;
class bootstrap_attempt_wallet;
/**
* Client side portion to initiate bootstrap sessions. Prevents multiple legacy-type bootstrap sessions from being started at the same time. Does permit
* lazy/wallet bootstrap sessions to overlap with legacy sessions.
@ -103,8 +105,8 @@ public:
bool has_new_attempts ();
void remove_attempt (std::shared_ptr<nano::bootstrap_attempt>);
std::shared_ptr<nano::bootstrap_attempt> current_attempt ();
std::shared_ptr<nano::bootstrap_attempt> current_lazy_attempt ();
std::shared_ptr<nano::bootstrap_attempt> current_wallet_attempt ();
std::shared_ptr<nano::bootstrap_attempt_lazy> current_lazy_attempt ();
std::shared_ptr<nano::bootstrap_attempt_wallet> current_wallet_attempt ();
nano::pulls_cache cache;
nano::bootstrap_attempts attempts;
void stop ();

View file

@ -113,27 +113,6 @@ std::string nano::bootstrap_attempt::mode_text ()
return mode_text;
}
void nano::bootstrap_attempt::add_frontier (nano::pull_info const &)
{
debug_assert (mode == nano::bootstrap_mode::legacy);
}
void nano::bootstrap_attempt::add_bulk_push_target (nano::block_hash const &, nano::block_hash const &)
{
debug_assert (mode == nano::bootstrap_mode::legacy);
}
bool nano::bootstrap_attempt::request_bulk_push_target (std::pair<nano::block_hash, nano::block_hash> &)
{
debug_assert (mode == nano::bootstrap_mode::legacy);
return true;
}
void nano::bootstrap_attempt::set_start_account (nano::account const &)
{
debug_assert (mode == nano::bootstrap_mode::legacy);
}
bool nano::bootstrap_attempt::process_block (std::shared_ptr<nano::block> const & block_a, nano::account const & known_account_a, uint64_t pull_blocks_processed, nano::bulk_pull::count_t max_blocks, bool block_expected, unsigned retry_limit)
{
bool stop_pull (false);
@ -149,53 +128,3 @@ bool nano::bootstrap_attempt::process_block (std::shared_ptr<nano::block> const
}
return stop_pull;
}
bool nano::bootstrap_attempt::lazy_start (nano::hash_or_account const &, bool)
{
debug_assert (mode == nano::bootstrap_mode::lazy);
return false;
}
void nano::bootstrap_attempt::lazy_add (nano::pull_info const &)
{
debug_assert (mode == nano::bootstrap_mode::lazy);
}
void nano::bootstrap_attempt::lazy_requeue (nano::block_hash const &, nano::block_hash const &)
{
debug_assert (mode == nano::bootstrap_mode::lazy);
}
uint32_t nano::bootstrap_attempt::lazy_batch_size ()
{
debug_assert (mode == nano::bootstrap_mode::lazy);
return node->network_params.bootstrap.lazy_min_pull_blocks;
}
bool nano::bootstrap_attempt::lazy_processed_or_exists (nano::block_hash const &)
{
debug_assert (mode == nano::bootstrap_mode::lazy);
return false;
}
bool nano::bootstrap_attempt::lazy_has_expired () const
{
debug_assert (mode == nano::bootstrap_mode::lazy);
return true;
}
void nano::bootstrap_attempt::requeue_pending (nano::account const &)
{
debug_assert (mode == nano::bootstrap_mode::wallet_lazy);
}
void nano::bootstrap_attempt::wallet_start (std::deque<nano::account> &)
{
debug_assert (mode == nano::bootstrap_mode::wallet_lazy);
}
std::size_t nano::bootstrap_attempt::wallet_size ()
{
debug_assert (mode == nano::bootstrap_mode::wallet_lazy);
return 0;
}

View file

@ -27,20 +27,7 @@ public:
void pull_finished ();
bool should_log ();
std::string mode_text ();
virtual void add_frontier (nano::pull_info const &);
virtual void add_bulk_push_target (nano::block_hash const &, nano::block_hash const &);
virtual bool request_bulk_push_target (std::pair<nano::block_hash, nano::block_hash> &);
virtual void set_start_account (nano::account const &);
virtual bool lazy_start (nano::hash_or_account const &, bool confirmed = true);
virtual void lazy_add (nano::pull_info const &);
virtual void lazy_requeue (nano::block_hash const &, nano::block_hash const &);
virtual uint32_t lazy_batch_size ();
virtual bool lazy_has_expired () const;
virtual bool lazy_processed_or_exists (nano::block_hash const &);
virtual bool process_block (std::shared_ptr<nano::block> const &, nano::account const &, uint64_t, nano::bulk_pull::count_t, bool, unsigned);
virtual void requeue_pending (nano::account const &);
virtual void wallet_start (std::deque<nano::account> &);
virtual std::size_t wallet_size ();
virtual void get_information (boost::property_tree::ptree &) = 0;
nano::mutex next_log_mutex;
std::chrono::steady_clock::time_point next_log{ std::chrono::steady_clock::now () };

View file

@ -284,7 +284,7 @@ void nano::bulk_pull_client::received_block (boost::system::error_code const & e
}
}
nano::bulk_pull_account_client::bulk_pull_account_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt> const & attempt_a, nano::account const & account_a) :
nano::bulk_pull_account_client::bulk_pull_account_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt_wallet> const & attempt_a, nano::account const & account_a) :
connection (connection_a),
attempt (attempt_a),
account (account_a),

View file

@ -49,15 +49,16 @@ public:
uint64_t unexpected_count;
bool network_error{ false };
};
class bootstrap_attempt_wallet;
class bulk_pull_account_client final : public std::enable_shared_from_this<nano::bulk_pull_account_client>
{
public:
bulk_pull_account_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt> const &, nano::account const &);
bulk_pull_account_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt_wallet> const &, nano::account const &);
~bulk_pull_account_client ();
void request ();
void receive_pending ();
std::shared_ptr<nano::bootstrap_client> connection;
std::shared_ptr<nano::bootstrap_attempt> attempt;
std::shared_ptr<nano::bootstrap_attempt_wallet> attempt;
nano::account account;
uint64_t pull_blocks;
};

View file

@ -1,11 +1,12 @@
#include <nano/node/bootstrap/bootstrap_attempt.hpp>
#include <nano/node/bootstrap/bootstrap_bulk_push.hpp>
#include <nano/node/bootstrap/bootstrap_legacy.hpp>
#include <nano/node/node.hpp>
#include <nano/node/transport/tcp.hpp>
#include <boost/format.hpp>
nano::bulk_push_client::bulk_push_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt> const & attempt_a) :
nano::bulk_push_client::bulk_push_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt_legacy> const & attempt_a) :
connection (connection_a),
attempt (attempt_a)
{

View file

@ -6,7 +6,7 @@
namespace nano
{
class bootstrap_attempt;
class bootstrap_attempt_legacy;
class bootstrap_client;
/**
@ -15,14 +15,14 @@ class bootstrap_client;
class bulk_push_client final : public std::enable_shared_from_this<nano::bulk_push_client>
{
public:
explicit bulk_push_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt> const &);
explicit bulk_push_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt_legacy> const &);
~bulk_push_client ();
void start ();
void push ();
void push_block (nano::block const &);
void send_finished ();
std::shared_ptr<nano::bootstrap_client> connection;
std::shared_ptr<nano::bootstrap_attempt> attempt;
std::shared_ptr<nano::bootstrap_attempt_legacy> attempt;
std::promise<bool> promise;
std::pair<nano::block_hash, nano::block_hash> current_target;
};

View file

@ -1,12 +1,15 @@
#include <nano/node/bootstrap/bootstrap.hpp>
#include <nano/node/bootstrap/bootstrap_attempt.hpp>
#include <nano/node/bootstrap/bootstrap_connections.hpp>
#include <nano/node/bootstrap/bootstrap_lazy.hpp>
#include <nano/node/common.hpp>
#include <nano/node/node.hpp>
#include <nano/node/transport/tcp.hpp>
#include <boost/format.hpp>
#include <memory>
constexpr double nano::bootstrap_limits::bootstrap_connection_scale_target_blocks;
constexpr double nano::bootstrap_limits::bootstrap_minimum_blocks_per_sec;
constexpr double nano::bootstrap_limits::bootstrap_minimum_termination_time_sec;
@ -348,10 +351,13 @@ void nano::bootstrap_connections::request_pull (nano::unique_lock<nano::mutex> &
pulls.pop_front ();
attempt_l = node.bootstrap_initiator.attempts.find (pull.bootstrap_id);
// Check if lazy pull is obsolete (head was processed or head is 0 for destinations requests)
if (attempt_l != nullptr && attempt_l->mode == nano::bootstrap_mode::lazy && !pull.head.is_zero () && attempt_l->lazy_processed_or_exists (pull.head))
if (auto lazy = std::dynamic_pointer_cast<nano::bootstrap_attempt_lazy> (attempt_l))
{
attempt_l->pull_finished ();
attempt_l = nullptr;
if (!pull.head.is_zero () && lazy->lazy_processed_or_exists (pull.head))
{
attempt_l->pull_finished ();
attempt_l = nullptr;
}
}
}
if (attempt_l != nullptr)
@ -383,10 +389,11 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a,
auto attempt_l (node.bootstrap_initiator.attempts.find (pull.bootstrap_id));
if (attempt_l != nullptr)
{
auto lazy = std::dynamic_pointer_cast<nano::bootstrap_attempt_lazy> (attempt_l);
++attempt_l->requeued_pulls;
if (attempt_l->mode == nano::bootstrap_mode::lazy)
if (lazy)
{
pull.count = attempt_l->lazy_batch_size ();
pull.count = lazy->lazy_batch_size ();
}
if (attempt_l->mode == nano::bootstrap_mode::legacy && (pull.attempts < pull.retry_limit + (pull.processed / nano::bootstrap_limits::requeued_pulls_processed_blocks_factor)))
{
@ -397,10 +404,10 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a,
attempt_l->pull_started ();
condition.notify_all ();
}
else if (attempt_l->mode == nano::bootstrap_mode::lazy && (pull.attempts <= pull.retry_limit + (pull.processed / node.network_params.bootstrap.lazy_max_pull_blocks)))
else if (lazy && (pull.attempts <= pull.retry_limit + (pull.processed / node.network_params.bootstrap.lazy_max_pull_blocks)))
{
debug_assert (pull.account_or_head == pull.head);
if (!attempt_l->lazy_processed_or_exists (pull.account_or_head.as_block_hash ()))
if (!lazy->lazy_processed_or_exists (pull.account_or_head.as_block_hash ()))
{
{
nano::lock_guard<nano::mutex> lock (mutex);
@ -418,9 +425,9 @@ void nano::bootstrap_connections::requeue_pull (nano::pull_info const & pull_a,
}
node.stats.inc (nano::stat::type::bootstrap, nano::stat::detail::bulk_pull_failed_account, nano::stat::dir::in);
if (attempt_l->mode == nano::bootstrap_mode::lazy && pull.processed > 0)
if (lazy && pull.processed > 0)
{
attempt_l->lazy_add (pull);
lazy->lazy_add (pull);
}
else if (attempt_l->mode == nano::bootstrap_mode::legacy)
{

View file

@ -1,5 +1,6 @@
#include <nano/node/bootstrap/bootstrap_attempt.hpp>
#include <nano/node/bootstrap/bootstrap_frontier.hpp>
#include <nano/node/bootstrap/bootstrap_legacy.hpp>
#include <nano/node/node.hpp>
#include <nano/node/transport/tcp.hpp>
@ -40,7 +41,7 @@ void nano::frontier_req_client::run (nano::account const & start_account_a, uint
nano::buffer_drop_policy::no_limiter_drop);
}
nano::frontier_req_client::frontier_req_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt> const & attempt_a) :
nano::frontier_req_client::frontier_req_client (std::shared_ptr<nano::bootstrap_client> const & connection_a, std::shared_ptr<nano::bootstrap_attempt_legacy> const & attempt_a) :
connection (connection_a),
attempt (attempt_a),
count (0),

View file

@ -7,7 +7,7 @@
namespace nano
{
class bootstrap_attempt;
class bootstrap_attempt_legacy;
class bootstrap_client;
/**
@ -16,7 +16,7 @@ class bootstrap_client;
class frontier_req_client final : public std::enable_shared_from_this<nano::frontier_req_client>
{
public:
explicit frontier_req_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt> const &);
explicit frontier_req_client (std::shared_ptr<nano::bootstrap_client> const &, std::shared_ptr<nano::bootstrap_attempt_legacy> const &);
void run (nano::account const & start_account_a, uint32_t const frontiers_age_a, uint32_t const count_a);
void receive_frontier ();
void received_frontier (boost::system::error_code const &, std::size_t);
@ -24,7 +24,7 @@ public:
void unsynced (nano::block_hash const &, nano::block_hash const &);
void next ();
std::shared_ptr<nano::bootstrap_client> connection;
std::shared_ptr<nano::bootstrap_attempt> attempt;
std::shared_ptr<nano::bootstrap_attempt_legacy> attempt;
nano::account current;
nano::block_hash frontier;
unsigned count;

View file

@ -188,10 +188,9 @@ void nano::bootstrap_attempt_lazy::run ()
while ((still_pulling () || !lazy_finished ()) && !lazy_has_expired ())
{
unsigned iterations (0);
auto this_l (shared_from_this ());
while (still_pulling () && !lazy_has_expired ())
{
condition.wait (lock, [&stopped = stopped, &pulling = pulling, &lazy_pulls = lazy_pulls, this_l] { return stopped || pulling == 0 || (pulling < nano::bootstrap_limits::bootstrap_connection_scale_target_blocks && !lazy_pulls.empty ()) || this_l->lazy_has_expired (); });
condition.wait (lock, [this, &stopped = stopped, &pulling = pulling, &lazy_pulls = lazy_pulls] { return stopped || pulling == 0 || (pulling < nano::bootstrap_limits::bootstrap_connection_scale_target_blocks && !lazy_pulls.empty ()) || lazy_has_expired (); });
++iterations;
// Flushing lazy pulls
lazy_pull_flush (lock);
@ -489,7 +488,7 @@ void nano::bootstrap_attempt_wallet::request_pending (nano::unique_lock<nano::mu
auto account (wallet_accounts.front ());
wallet_accounts.pop_front ();
++pulling;
auto this_l (shared_from_this ());
auto this_l = std::dynamic_pointer_cast<nano::bootstrap_attempt_wallet> (shared_from_this ());
// The bulk_pull_account_client destructor attempt to requeue_pull which can cause a deadlock if this is the last reference
// Dispatch request in an external thread in case it needs to be destroyed
node->background ([connection_l, this_l, account] () {

View file

@ -35,13 +35,13 @@ public:
~bootstrap_attempt_lazy ();
bool process_block (std::shared_ptr<nano::block> const &, nano::account const &, uint64_t, nano::bulk_pull::count_t, bool, unsigned) override;
void run () override;
bool lazy_start (nano::hash_or_account const &, bool confirmed = true) override;
bool lazy_start (nano::hash_or_account const &, bool confirmed = true);
void lazy_add (nano::hash_or_account const &, unsigned);
void lazy_add (nano::pull_info const &) override;
void lazy_requeue (nano::block_hash const &, nano::block_hash const &) override;
void lazy_add (nano::pull_info const &);
void lazy_requeue (nano::block_hash const &, nano::block_hash const &);
bool lazy_finished ();
bool lazy_has_expired () const override;
uint32_t lazy_batch_size () override;
bool lazy_has_expired () const;
uint32_t lazy_batch_size ();
void lazy_pull_flush (nano::unique_lock<nano::mutex> & lock_a);
bool process_block_lazy (std::shared_ptr<nano::block> const &, nano::account const &, uint64_t, nano::bulk_pull::count_t, unsigned);
void lazy_block_state (std::shared_ptr<nano::block> const &, unsigned);
@ -50,7 +50,7 @@ public:
void lazy_blocks_insert (nano::block_hash const &);
void lazy_blocks_erase (nano::block_hash const &);
bool lazy_blocks_processed (nano::block_hash const &);
bool lazy_processed_or_exists (nano::block_hash const &) override;
bool lazy_processed_or_exists (nano::block_hash const &);
unsigned lazy_retry_limit_confirmed ();
void get_information (boost::property_tree::ptree &) override;
std::unordered_set<std::size_t> lazy_blocks;
@ -75,11 +75,11 @@ public:
explicit bootstrap_attempt_wallet (std::shared_ptr<nano::node> const & node_a, uint64_t incremental_id_a, std::string id_a = "");
~bootstrap_attempt_wallet ();
void request_pending (nano::unique_lock<nano::mutex> &);
void requeue_pending (nano::account const &) override;
void requeue_pending (nano::account const &);
void run () override;
void wallet_start (std::deque<nano::account> &) override;
void wallet_start (std::deque<nano::account> &);
bool wallet_finished ();
std::size_t wallet_size () override;
std::size_t wallet_size ();
void get_information (boost::property_tree::ptree &) override;
std::deque<nano::account> wallet_accounts;
};

View file

@ -68,8 +68,8 @@ void nano::bootstrap_attempt_legacy::request_push (nano::unique_lock<nano::mutex
{
std::future<bool> future;
{
auto this_l (shared_from_this ());
auto client (std::make_shared<nano::bulk_push_client> (connection_l, this_l));
auto this_l = std::dynamic_pointer_cast<nano::bootstrap_attempt_legacy> (shared_from_this ());
auto client = std::make_shared<nano::bulk_push_client> (connection_l, this_l);
client->start ();
push = client;
future = client->promise.get_future ();
@ -134,8 +134,8 @@ bool nano::bootstrap_attempt_legacy::request_frontier (nano::unique_lock<nano::m
endpoint_frontier_request = connection_l->channel->get_tcp_endpoint ();
std::future<bool> future;
{
auto this_l (shared_from_this ());
auto client (std::make_shared<nano::frontier_req_client> (connection_l, this_l));
auto this_l = std::dynamic_pointer_cast<nano::bootstrap_attempt_legacy> (shared_from_this ());
auto client = std::make_shared<nano::frontier_req_client> (connection_l, this_l);
client->run (start_account, frontiers_age, node->config.bootstrap_frontier_request_count);
frontiers = client;
future = client->promise.get_future ();

View file

@ -25,10 +25,10 @@ public:
void stop () override;
bool request_frontier (nano::unique_lock<nano::mutex> &, bool = false);
void request_push (nano::unique_lock<nano::mutex> &);
void add_frontier (nano::pull_info const &) override;
void add_bulk_push_target (nano::block_hash const &, nano::block_hash const &) override;
bool request_bulk_push_target (std::pair<nano::block_hash, nano::block_hash> &) override;
void set_start_account (nano::account const &) override;
void add_frontier (nano::pull_info const &);
void add_bulk_push_target (nano::block_hash const &, nano::block_hash const &);
bool request_bulk_push_target (std::pair<nano::block_hash, nano::block_hash> &);
void set_start_account (nano::account const &);
void run_start (nano::unique_lock<nano::mutex> &);
void get_information (boost::property_tree::ptree &) override;
nano::tcp_endpoint endpoint_frontier_request;