dncurrency/nano/node/peer_exclusion.cpp
Wesley Shillingford 0a64feb49e
Various consistency changes (#3058)
* Various consistency changes

* Colin comments
2021-02-17 15:36:27 +00:00

95 lines
3.3 KiB
C++

#include <nano/node/peer_exclusion.hpp>
constexpr std::chrono::hours nano::peer_exclusion::exclude_time_hours;
constexpr std::chrono::hours nano::peer_exclusion::exclude_remove_hours;
constexpr size_t nano::peer_exclusion::size_max;
constexpr double nano::peer_exclusion::peers_percentage_limit;
uint64_t nano::peer_exclusion::add (nano::tcp_endpoint const & endpoint_a, size_t const network_peers_count_a)
{
uint64_t result (0);
nano::lock_guard<std::mutex> guard (mutex);
// Clean old excluded peers
auto limited = limited_size (network_peers_count_a);
while (peers.size () > 1 && peers.size () > limited)
{
peers.get<tag_exclusion> ().erase (peers.get<tag_exclusion> ().begin ());
}
debug_assert (peers.size () <= size_max);
auto & peers_by_endpoint (peers.get<tag_endpoint> ());
auto address = endpoint_a.address ();
auto existing (peers_by_endpoint.find (address));
if (existing == peers_by_endpoint.end ())
{
// Insert new endpoint
auto inserted (peers.emplace (peer_exclusion::item{ std::chrono::steady_clock::steady_clock::now () + exclude_time_hours, address, 1 }));
(void)inserted;
debug_assert (inserted.second);
result = 1;
}
else
{
// Update existing endpoint
peers_by_endpoint.modify (existing, [&result](peer_exclusion::item & item_a) {
++item_a.score;
result = item_a.score;
if (item_a.score == peer_exclusion::score_limit)
{
item_a.exclude_until = std::chrono::steady_clock::now () + peer_exclusion::exclude_time_hours;
}
else if (item_a.score > peer_exclusion::score_limit)
{
item_a.exclude_until = std::chrono::steady_clock::now () + peer_exclusion::exclude_time_hours * item_a.score * 2;
}
});
}
return result;
}
bool nano::peer_exclusion::check (nano::tcp_endpoint const & endpoint_a)
{
bool excluded (false);
nano::lock_guard<std::mutex> guard (mutex);
auto & peers_by_endpoint (peers.get<tag_endpoint> ());
auto existing (peers_by_endpoint.find (endpoint_a.address ()));
if (existing != peers_by_endpoint.end () && existing->score >= score_limit)
{
if (existing->exclude_until > std::chrono::steady_clock::now ())
{
excluded = true;
}
else if (existing->exclude_until + exclude_remove_hours * existing->score < std::chrono::steady_clock::now ())
{
peers_by_endpoint.erase (existing);
}
}
return excluded;
}
void nano::peer_exclusion::remove (nano::tcp_endpoint const & endpoint_a)
{
nano::lock_guard<std::mutex> guard (mutex);
peers.get<tag_endpoint> ().erase (endpoint_a.address ());
}
size_t nano::peer_exclusion::limited_size (size_t const network_peers_count_a) const
{
return std::min (size_max, static_cast<size_t> (network_peers_count_a * peers_percentage_limit));
}
size_t nano::peer_exclusion::size () const
{
nano::lock_guard<std::mutex> guard (mutex);
return peers.size ();
}
std::unique_ptr<nano::container_info_component> nano::collect_container_info (nano::peer_exclusion const & excluded_peers, std::string const & name)
{
auto composite = std::make_unique<container_info_composite> (name);
size_t excluded_peers_count = excluded_peers.size ();
auto sizeof_excluded_peers_element = sizeof (nano::peer_exclusion::ordered_endpoints::value_type);
composite->add_component (std::make_unique<container_info_leaf> (container_info{ "peers", excluded_peers_count, sizeof_excluded_peers_element }));
return composite;
}