135template <
typename T,
typename Comparator>
137 std::vector<T> &
elements, Comparator comparator,
size_t k,
141 size_t eraseSize = std::min(k,
elements.size());
148 std::vector<NodeEvictionCandidate> &eviction_candidates) {
149 eviction_candidates.erase(
151 eviction_candidates.begin(), eviction_candidates.end(),
153 eviction_candidates.end());
157 std::vector<NodeEvictionCandidate> &eviction_candidates) {
158 eviction_candidates.erase(
159 std::remove_if(eviction_candidates.begin(), eviction_candidates.end(),
161 return n.m_conn_type != ConnectionType::INBOUND;
163 eviction_candidates.end());
167 std::vector<NodeEvictionCandidate> &eviction_candidates) {
176 const size_t initial_size = eviction_candidates.size();
177 const size_t total_protect_size{initial_size / 2};
187 std::array<Net, 3> networks{{{
false,
NET_I2P, 0},
192 for (Net &n : networks) {
193 n.count = std::count_if(
194 eviction_candidates.cbegin(), eviction_candidates.cend(),
196 return n.is_local ? c.m_is_local : c.m_network == n.id;
202 std::stable_sort(networks.begin(), networks.end(),
203 [](Net a, Net b) { return a.count < b.count; });
206 const size_t max_protect_by_network{total_protect_size / 2};
207 size_t num_protected{0};
209 while (num_protected < max_protect_by_network) {
212 auto num_networks = std::count_if(networks.begin(), networks.end(),
213 [](
const Net &n) { return n.count; });
214 if (num_networks == 0) {
217 const size_t disadvantaged_to_protect{max_protect_by_network -
219 const size_t protect_per_network{std::max(
220 disadvantaged_to_protect / num_networks,
static_cast<size_t>(1))};
224 bool protected_at_least_one{
false};
226 for (Net &n : networks) {
230 const size_t before = eviction_candidates.size();
234 return n.is_local ? c.m_is_local : c.m_network == n.id;
236 const size_t after = eviction_candidates.size();
237 if (before > after) {
238 protected_at_least_one =
true;
239 const size_t delta{before - after};
240 num_protected += delta;
241 if (num_protected >= max_protect_by_network) {
247 if (!protected_at_least_one) {
254 assert(num_protected == initial_size - eviction_candidates.size());
255 const size_t remaining_to_protect{total_protect_size - num_protected};
257 remaining_to_protect);
260[[nodiscard]] std::optional<NodeId>
306 if (vEvictionCandidates.empty()) {
315 vEvictionCandidates.begin(), vEvictionCandidates.end(),
317 vEvictionCandidates.erase(
319 vEvictionCandidates.begin(), vEvictionCandidates.end(),
321 vEvictionCandidates.end());
326 uint64_t naMostConnections;
327 unsigned int nMostConnections = 0;
328 std::chrono::seconds nMostConnectionsTime{0};
329 std::map<uint64_t, std::vector<NodeEvictionCandidate>> mapNetGroupNodes;
331 std::vector<NodeEvictionCandidate> &group =
332 mapNetGroupNodes[
node.nKeyedNetGroup];
333 group.push_back(
node);
334 const auto grouptime{group[0].m_connected};
335 size_t group_size = group.size();
336 if (group_size > nMostConnections ||
337 (group_size == nMostConnections &&
338 grouptime > nMostConnectionsTime)) {
339 nMostConnections = group_size;
340 nMostConnectionsTime = grouptime;
341 naMostConnections =
node.nKeyedNetGroup;
346 vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
349 return vEvictionCandidates.front().id;
static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static void EraseLastKElements(std::vector< T > &elements, Comparator comparator, size_t k, std::function< bool(const NodeEvictionCandidate &)> predicate=[](const NodeEvictionCandidate &n) { return true;})
Sort an array by the specified comparator, then erase the last K elements where predicate is true.
static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
void ProtectNoBanConnections(std::vector< NodeEvictionCandidate > &eviction_candidates)
static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static bool CompareNodeAvailabilityScore(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
void ProtectEvictionCandidatesByRatio(std::vector< NodeEvictionCandidate > &eviction_candidates)
Protect desirable or disadvantaged inbound peers from eviction by ratio.
std::optional< NodeId > SelectNodeToEvict(std::vector< NodeEvictionCandidate > &&vEvictionCandidates)
Select an inbound peer to evict after filtering out (protecting) peers having distinct,...
static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static bool CompareNodeProofTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
void ProtectOutboundConnections(std::vector< NodeEvictionCandidate > &eviction_candidates)
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
static unsigned char elements[DATACOUNT][DATALEN]
@ NET_MAX
Dummy value to indicate the number of NET_* constants.
@ NET_ONION
TOR (v2 or v3)
Sort eviction candidates by network/localhost and connection uptime.
CompareNodeNetworkTime(bool is_local, Network network)
bool operator()(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) const
std::chrono::seconds m_last_tx_time
std::chrono::seconds m_connected
std::chrono::seconds m_last_block_time
std::chrono::microseconds m_min_ping_time
std::chrono::seconds m_last_proof_time