From ddcdc2f58450cb972666aa4ae57e01e003746e3d Mon Sep 17 00:00:00 2001 From: Sergey Kroshnin Date: Wed, 23 Jan 2019 21:13:35 +0300 Subject: [PATCH] Connect to a bootstrap peer only once concurrently (#1590) --- nano/node/bootstrap.cpp | 11 +++++++++-- nano/node/common.hpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/nano/node/bootstrap.cpp b/nano/node/bootstrap.cpp index cc8f4c51..12fbfc40 100644 --- a/nano/node/bootstrap.cpp +++ b/nano/node/bootstrap.cpp @@ -1148,13 +1148,17 @@ void nano::bootstrap_attempt::populate_connections () double rate_sum = 0.0; size_t num_pulls = 0; std::priority_queue, std::vector>, block_rate_cmp> sorted_connections; + std::unordered_set endpoints; { std::unique_lock lock (mutex); num_pulls = pulls.size (); + std::deque> new_clients; for (auto & c : clients) { if (auto client = c.lock ()) { + new_clients.push_back (client); + endpoints.insert (client->endpoint); double elapsed_sec = client->elapsed_seconds (); auto blocks_per_sec = client->block_rate (); rate_sum += blocks_per_sec; @@ -1175,6 +1179,8 @@ void nano::bootstrap_attempt::populate_connections () } } } + // Cleanup expired clients + clients.swap (new_clients); } auto target = target_connections (num_pulls); @@ -1219,9 +1225,10 @@ void nano::bootstrap_attempt::populate_connections () for (int i = 0; i < delta; i++) { auto peer (node->peers.bootstrap_peer ()); - if (peer != nano::endpoint (boost::asio::ip::address_v6::any (), 0)) + auto endpoint (nano::tcp_endpoint (peer.address (), peer.port ())); + if (peer != nano::endpoint (boost::asio::ip::address_v6::any (), 0) && endpoints.find (endpoint) == endpoints.end ()) { - auto client (std::make_shared (node, shared_from_this (), nano::tcp_endpoint (peer.address (), peer.port ()))); + auto client (std::make_shared (node, shared_from_this (), endpoint)); client->run (); std::lock_guard lock (mutex); clients.push_back (client); diff --git a/nano/node/common.hpp b/nano/node/common.hpp index 42ca6178..e425edc3 100644 --- a/nano/node/common.hpp +++ b/nano/node/common.hpp @@ -35,6 +35,19 @@ uint64_t endpoint_hash_raw (nano::endpoint const & endpoint_a) auto result (XXH64_digest (&hash)); return result; } +uint64_t endpoint_hash_raw (nano::tcp_endpoint const & endpoint_a) +{ + assert (endpoint_a.address ().is_v6 ()); + nano::uint128_union address; + address.bytes = endpoint_a.address ().to_v6 ().to_bytes (); + XXH64_state_t hash; + XXH64_reset (&hash, 0); + XXH64_update (&hash, address.bytes.data (), address.bytes.size ()); + auto port (endpoint_a.port ()); + XXH64_update (&hash, &port, sizeof (port)); + auto result (XXH64_digest (&hash)); + return result; +} uint64_t ip_address_hash_raw (boost::asio::ip::address const & ip_a) { assert (ip_a.is_v6 ()); @@ -58,6 +71,10 @@ struct endpoint_hash<8> { return endpoint_hash_raw (endpoint_a); } + size_t operator() (nano::tcp_endpoint const & endpoint_a) const + { + return endpoint_hash_raw (endpoint_a); + } }; template <> struct endpoint_hash<4> @@ -68,6 +85,12 @@ struct endpoint_hash<4> uint32_t result (static_cast (big) ^ static_cast (big >> 32)); return result; } + size_t operator() (nano::tcp_endpoint const & endpoint_a) const + { + uint64_t big (endpoint_hash_raw (endpoint_a)); + uint32_t result (static_cast (big) ^ static_cast (big >> 32)); + return result; + } }; template struct ip_address_hash @@ -105,6 +128,15 @@ struct hash<::nano::endpoint> } }; template <> +struct hash<::nano::tcp_endpoint> +{ + size_t operator() (::nano::tcp_endpoint const & endpoint_a) const + { + endpoint_hash ehash; + return ehash (endpoint_a); + } +}; +template <> struct hash { size_t operator() (boost::asio::ip::address const & ip_a) const