Connect to a bootstrap peer only once concurrently (#1590)

This commit is contained in:
Sergey Kroshnin 2019-01-23 21:13:35 +03:00 committed by Roy Keene
commit ddcdc2f584
2 changed files with 41 additions and 2 deletions

View file

@ -1148,13 +1148,17 @@ void nano::bootstrap_attempt::populate_connections ()
double rate_sum = 0.0;
size_t num_pulls = 0;
std::priority_queue<std::shared_ptr<nano::bootstrap_client>, std::vector<std::shared_ptr<nano::bootstrap_client>>, block_rate_cmp> sorted_connections;
std::unordered_set<nano::tcp_endpoint> endpoints;
{
std::unique_lock<std::mutex> lock (mutex);
num_pulls = pulls.size ();
std::deque<std::weak_ptr<nano::bootstrap_client>> 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<nano::bootstrap_client> (node, shared_from_this (), nano::tcp_endpoint (peer.address (), peer.port ())));
auto client (std::make_shared<nano::bootstrap_client> (node, shared_from_this (), endpoint));
client->run ();
std::lock_guard<std::mutex> lock (mutex);
clients.push_back (client);

View file

@ -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<uint32_t> (big) ^ static_cast<uint32_t> (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<uint32_t> (big) ^ static_cast<uint32_t> (big >> 32));
return result;
}
};
template <size_t size>
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<sizeof (size_t)> ehash;
return ehash (endpoint_a);
}
};
template <>
struct hash<boost::asio::ip::address>
{
size_t operator() (boost::asio::ip::address const & ip_a) const