diff --git a/nano/node/bootstrap/bootstrap.cpp b/nano/node/bootstrap/bootstrap.cpp index 433241bd0c..95263a66ce 100644 --- a/nano/node/bootstrap/bootstrap.cpp +++ b/nano/node/bootstrap/bootstrap.cpp @@ -8,6 +8,7 @@ #include #include +#include nano::bootstrap_initiator::bootstrap_initiator (nano::node & node_a) : node (node_a) @@ -233,16 +234,16 @@ std::shared_ptr nano::bootstrap_initiator::current_atte return find_attempt (nano::bootstrap_mode::legacy); } -std::shared_ptr nano::bootstrap_initiator::current_lazy_attempt () +std::shared_ptr nano::bootstrap_initiator::current_lazy_attempt () { nano::lock_guard lock (mutex); - return find_attempt (nano::bootstrap_mode::lazy); + return std::dynamic_pointer_cast (find_attempt (nano::bootstrap_mode::lazy)); } -std::shared_ptr nano::bootstrap_initiator::current_wallet_attempt () +std::shared_ptr nano::bootstrap_initiator::current_wallet_attempt () { nano::lock_guard lock (mutex); - return find_attempt (nano::bootstrap_mode::wallet_lazy); + return std::dynamic_pointer_cast (find_attempt (nano::bootstrap_mode::wallet_lazy)); } void nano::bootstrap_initiator::stop_attempts () diff --git a/nano/node/bootstrap/bootstrap.hpp b/nano/node/bootstrap/bootstrap.hpp index e5ff75db7b..ae1c3359ef 100644 --- a/nano/node/bootstrap/bootstrap.hpp +++ b/nano/node/bootstrap/bootstrap.hpp @@ -80,6 +80,8 @@ class bootstrap_attempts final std::map> 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 @@ class bootstrap_initiator final bool has_new_attempts (); void remove_attempt (std::shared_ptr); std::shared_ptr current_attempt (); - std::shared_ptr current_lazy_attempt (); - std::shared_ptr current_wallet_attempt (); + std::shared_ptr current_lazy_attempt (); + std::shared_ptr current_wallet_attempt (); nano::pulls_cache cache; nano::bootstrap_attempts attempts; void stop (); diff --git a/nano/node/bootstrap/bootstrap_attempt.cpp b/nano/node/bootstrap/bootstrap_attempt.cpp index ed192a4b02..b14dd723cf 100644 --- a/nano/node/bootstrap/bootstrap_attempt.cpp +++ b/nano/node/bootstrap/bootstrap_attempt.cpp @@ -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 &) -{ - 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 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 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 &) -{ - 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; -} diff --git a/nano/node/bootstrap/bootstrap_attempt.hpp b/nano/node/bootstrap/bootstrap_attempt.hpp index 55c56781c2..6cb62c17ee 100644 --- a/nano/node/bootstrap/bootstrap_attempt.hpp +++ b/nano/node/bootstrap/bootstrap_attempt.hpp @@ -27,20 +27,7 @@ class bootstrap_attempt : public std::enable_shared_from_this 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 &); - 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 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 &); - 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 () }; diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.cpp b/nano/node/bootstrap/bootstrap_bulk_pull.cpp index dee6a7675f..751ab60e1e 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.cpp @@ -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 const & connection_a, std::shared_ptr const & attempt_a, nano::account const & account_a) : +nano::bulk_pull_account_client::bulk_pull_account_client (std::shared_ptr const & connection_a, std::shared_ptr const & attempt_a, nano::account const & account_a) : connection (connection_a), attempt (attempt_a), account (account_a), diff --git a/nano/node/bootstrap/bootstrap_bulk_pull.hpp b/nano/node/bootstrap/bootstrap_bulk_pull.hpp index 673db280bf..762dc38c4e 100644 --- a/nano/node/bootstrap/bootstrap_bulk_pull.hpp +++ b/nano/node/bootstrap/bootstrap_bulk_pull.hpp @@ -49,15 +49,16 @@ class bulk_pull_client final : public std::enable_shared_from_this { public: - bulk_pull_account_client (std::shared_ptr const &, std::shared_ptr const &, nano::account const &); + bulk_pull_account_client (std::shared_ptr const &, std::shared_ptr const &, nano::account const &); ~bulk_pull_account_client (); void request (); void receive_pending (); std::shared_ptr connection; - std::shared_ptr attempt; + std::shared_ptr attempt; nano::account account; uint64_t pull_blocks; }; diff --git a/nano/node/bootstrap/bootstrap_bulk_push.cpp b/nano/node/bootstrap/bootstrap_bulk_push.cpp index 2e15af324d..e14b3f2920 100644 --- a/nano/node/bootstrap/bootstrap_bulk_push.cpp +++ b/nano/node/bootstrap/bootstrap_bulk_push.cpp @@ -1,11 +1,12 @@ #include #include +#include #include #include #include -nano::bulk_push_client::bulk_push_client (std::shared_ptr const & connection_a, std::shared_ptr const & attempt_a) : +nano::bulk_push_client::bulk_push_client (std::shared_ptr const & connection_a, std::shared_ptr const & attempt_a) : connection (connection_a), attempt (attempt_a) { diff --git a/nano/node/bootstrap/bootstrap_bulk_push.hpp b/nano/node/bootstrap/bootstrap_bulk_push.hpp index c9f19d5cec..f43aba14df 100644 --- a/nano/node/bootstrap/bootstrap_bulk_push.hpp +++ b/nano/node/bootstrap/bootstrap_bulk_push.hpp @@ -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 { public: - explicit bulk_push_client (std::shared_ptr const &, std::shared_ptr const &); + explicit bulk_push_client (std::shared_ptr const &, std::shared_ptr const &); ~bulk_push_client (); void start (); void push (); void push_block (nano::block const &); void send_finished (); std::shared_ptr connection; - std::shared_ptr attempt; + std::shared_ptr attempt; std::promise promise; std::pair current_target; }; diff --git a/nano/node/bootstrap/bootstrap_connections.cpp b/nano/node/bootstrap/bootstrap_connections.cpp index 12f2e7f2ad..63f924cc2a 100644 --- a/nano/node/bootstrap/bootstrap_connections.cpp +++ b/nano/node/bootstrap/bootstrap_connections.cpp @@ -1,12 +1,15 @@ #include #include #include +#include #include #include #include #include +#include + 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 & 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 (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 (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 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) { diff --git a/nano/node/bootstrap/bootstrap_frontier.cpp b/nano/node/bootstrap/bootstrap_frontier.cpp index 219a4e24bd..ebce00ff4a 100644 --- a/nano/node/bootstrap/bootstrap_frontier.cpp +++ b/nano/node/bootstrap/bootstrap_frontier.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -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 const & connection_a, std::shared_ptr const & attempt_a) : +nano::frontier_req_client::frontier_req_client (std::shared_ptr const & connection_a, std::shared_ptr const & attempt_a) : connection (connection_a), attempt (attempt_a), count (0), diff --git a/nano/node/bootstrap/bootstrap_frontier.hpp b/nano/node/bootstrap/bootstrap_frontier.hpp index bab0c2386a..c85a484baf 100644 --- a/nano/node/bootstrap/bootstrap_frontier.hpp +++ b/nano/node/bootstrap/bootstrap_frontier.hpp @@ -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 { public: - explicit frontier_req_client (std::shared_ptr const &, std::shared_ptr const &); + explicit frontier_req_client (std::shared_ptr const &, std::shared_ptr 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 @@ class frontier_req_client final : public std::enable_shared_from_this connection; - std::shared_ptr attempt; + std::shared_ptr attempt; nano::account current; nano::block_hash frontier; unsigned count; diff --git a/nano/node/bootstrap/bootstrap_lazy.cpp b/nano/node/bootstrap/bootstrap_lazy.cpp index dd88088404..6ade6e99f3 100644 --- a/nano/node/bootstrap/bootstrap_lazy.cpp +++ b/nano/node/bootstrap/bootstrap_lazy.cpp @@ -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 (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] () { diff --git a/nano/node/bootstrap/bootstrap_lazy.hpp b/nano/node/bootstrap/bootstrap_lazy.hpp index bc34ce3f57..d2ab6678f7 100644 --- a/nano/node/bootstrap/bootstrap_lazy.hpp +++ b/nano/node/bootstrap/bootstrap_lazy.hpp @@ -35,13 +35,13 @@ class bootstrap_attempt_lazy final : public bootstrap_attempt ~bootstrap_attempt_lazy (); bool process_block (std::shared_ptr 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 & lock_a); bool process_block_lazy (std::shared_ptr const &, nano::account const &, uint64_t, nano::bulk_pull::count_t, unsigned); void lazy_block_state (std::shared_ptr const &, unsigned); @@ -50,7 +50,7 @@ class bootstrap_attempt_lazy final : public bootstrap_attempt 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 lazy_blocks; @@ -75,11 +75,11 @@ class bootstrap_attempt_wallet final : public bootstrap_attempt explicit bootstrap_attempt_wallet (std::shared_ptr const & node_a, uint64_t incremental_id_a, std::string id_a = ""); ~bootstrap_attempt_wallet (); void request_pending (nano::unique_lock &); - void requeue_pending (nano::account const &) override; + void requeue_pending (nano::account const &); void run () override; - void wallet_start (std::deque &) override; + void wallet_start (std::deque &); bool wallet_finished (); - std::size_t wallet_size () override; + std::size_t wallet_size (); void get_information (boost::property_tree::ptree &) override; std::deque wallet_accounts; }; diff --git a/nano/node/bootstrap/bootstrap_legacy.cpp b/nano/node/bootstrap/bootstrap_legacy.cpp index 1d61bb5d55..1904092e6b 100644 --- a/nano/node/bootstrap/bootstrap_legacy.cpp +++ b/nano/node/bootstrap/bootstrap_legacy.cpp @@ -68,8 +68,8 @@ void nano::bootstrap_attempt_legacy::request_push (nano::unique_lock future; { - auto this_l (shared_from_this ()); - auto client (std::make_shared (connection_l, this_l)); + auto this_l = std::dynamic_pointer_cast (shared_from_this ()); + auto client = std::make_shared (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_lockchannel->get_tcp_endpoint (); std::future future; { - auto this_l (shared_from_this ()); - auto client (std::make_shared (connection_l, this_l)); + auto this_l = std::dynamic_pointer_cast (shared_from_this ()); + auto client = std::make_shared (connection_l, this_l); client->run (start_account, frontiers_age, node->config.bootstrap_frontier_request_count); frontiers = client; future = client->promise.get_future (); diff --git a/nano/node/bootstrap/bootstrap_legacy.hpp b/nano/node/bootstrap/bootstrap_legacy.hpp index ae51c73d88..51423d778a 100644 --- a/nano/node/bootstrap/bootstrap_legacy.hpp +++ b/nano/node/bootstrap/bootstrap_legacy.hpp @@ -25,10 +25,10 @@ class bootstrap_attempt_legacy : public bootstrap_attempt void stop () override; bool request_frontier (nano::unique_lock &, bool = false); void request_push (nano::unique_lock &); - 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 &) 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 &); + void set_start_account (nano::account const &); void run_start (nano::unique_lock &); void get_information (boost::property_tree::ptree &) override; nano::tcp_endpoint endpoint_frontier_request;