Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/peermanager.cpp
// Copyright (c) 2020 The Bitcoin developers | // Copyright (c) 2020 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <avalanche/peermanager.h> | #include <avalanche/peermanager.h> | ||||
#include <random.h> | #include <random.h> | ||||
#include <cassert> | #include <cassert> | ||||
namespace avalanche { | namespace avalanche { | ||||
PeerId PeerManager::addPeer(PeerId p, uint32_t score) { | PeerId PeerManager::addPeer(PeerId p, uint32_t score) { | ||||
auto inserted = peers.emplace(p, Peer(score, uint32_t(slots.size()))); | auto inserted = | ||||
peers.emplace(p, score, uint32_t(slots.size()), ProofId(GetRandHash())); | |||||
assert(inserted.second); | assert(inserted.second); | ||||
const uint64_t start = slotCount; | const uint64_t start = slotCount; | ||||
slots.emplace_back(start, score, p); | slots.emplace_back(start, score, p); | ||||
slotCount = start + score; | slotCount = start + score; | ||||
return p; | return p; | ||||
} | } | ||||
bool PeerManager::removePeer(PeerId p) { | bool PeerManager::removePeer(const PeerId peerid) { | ||||
auto it = peers.find(p); | auto it = peers.find(peerid); | ||||
if (it == peers.end()) { | if (it == peers.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
size_t i = it->second.index; | size_t i = it->index; | ||||
assert(i < slots.size()); | assert(i < slots.size()); | ||||
if (i + 1 == slots.size()) { | if (i + 1 == slots.size()) { | ||||
slots.pop_back(); | slots.pop_back(); | ||||
slotCount = slots.empty() ? 0 : slots.back().getStop(); | slotCount = slots.empty() ? 0 : slots.back().getStop(); | ||||
} else { | } else { | ||||
fragmentation += slots[i].getScore(); | fragmentation += slots[i].getScore(); | ||||
slots[i] = slots[i].withPeerId(NO_PEER); | slots[i] = slots[i].withPeerId(NO_PEER); | ||||
} | } | ||||
// Remove nodes associated with this peer, unless their timeout is still | // Remove nodes associated with this peer, unless their timeout is still | ||||
// active. This ensure that we don't overquery them in case their are | // active. This ensure that we don't overquery them in case their are | ||||
// subsequently added to another peer. | // subsequently added to another peer. | ||||
auto &nview = nodes.get<next_request_time>(); | auto &nview = nodes.get<next_request_time>(); | ||||
nview.erase(nview.lower_bound(boost::make_tuple(p, TimePoint())), | nview.erase(nview.lower_bound(boost::make_tuple(peerid, TimePoint())), | ||||
nview.upper_bound( | nview.upper_bound(boost::make_tuple( | ||||
boost::make_tuple(p, std::chrono::steady_clock::now()))); | peerid, std::chrono::steady_clock::now()))); | ||||
peers.erase(it); | peers.erase(it); | ||||
return true; | return true; | ||||
} | } | ||||
bool PeerManager::rescorePeer(PeerId p, uint32_t score) { | bool PeerManager::rescorePeer(const PeerId peerid, uint32_t score) { | ||||
auto it = peers.find(p); | auto it = peers.find(peerid); | ||||
if (it == peers.end()) { | if (it == peers.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
size_t i = it->second.index; | |||||
assert(i < slots.size()); | |||||
// Update the peer's score. | // Update the peer's score. | ||||
it->second.score = score; | peers.modify(it, [&](Peer &p) { p.score = score; }); | ||||
const size_t i = it->index; | |||||
assert(i < slots.size()); | |||||
// Update the slot allocation to reflect the new score. | // Update the slot allocation to reflect the new score. | ||||
const uint64_t start = slots[i].getStart(); | const uint64_t start = slots[i].getStart(); | ||||
// If this is the last element, we can extend/shrink easily. | // If this is the last element, we can extend/shrink easily. | ||||
if (i + 1 == slots.size()) { | if (i + 1 == slots.size()) { | ||||
slots[i] = slots[i].withScore(score); | slots[i] = slots[i].withScore(score); | ||||
slotCount = slots[i].getStop(); | slotCount = slots[i].getStop(); | ||||
return true; | return true; | ||||
} | } | ||||
const uint64_t stop = start + score; | const uint64_t stop = start + score; | ||||
const uint64_t nextStart = slots[i + 1].getStart(); | const uint64_t nextStart = slots[i + 1].getStart(); | ||||
// We can extend in place. | // We can extend in place. | ||||
if (stop <= nextStart) { | if (stop <= nextStart) { | ||||
fragmentation += (slots[i].getStop() - stop); | fragmentation += (slots[i].getStop() - stop); | ||||
slots[i] = slots[i].withScore(score); | slots[i] = slots[i].withScore(score); | ||||
return true; | return true; | ||||
} | } | ||||
// So we need to insert a new entry. | // So we need to insert a new entry. | ||||
fragmentation += slots[i].getScore(); | fragmentation += slots[i].getScore(); | ||||
slots[i] = slots[i].withPeerId(NO_PEER); | slots[i] = slots[i].withPeerId(NO_PEER); | ||||
it->second.index = uint32_t(slots.size()); | peers.modify(it, [this](Peer &p) { p.index = uint32_t(slots.size()); }); | ||||
const uint64_t newStart = slotCount; | const uint64_t newStart = slotCount; | ||||
slots.emplace_back(newStart, score, p); | slots.emplace_back(newStart, score, peerid); | ||||
slotCount = newStart + score; | slotCount = newStart + score; | ||||
return true; | return true; | ||||
} | } | ||||
bool PeerManager::addNodeToPeer(PeerId peerid, NodeId nodeid, CPubKey pubkey) { | bool PeerManager::addNodeToPeer(PeerId peerid, NodeId nodeid, CPubKey pubkey) { | ||||
auto pit = peers.find(peerid); | auto pit = peers.find(peerid); | ||||
if (pit == peers.end()) { | if (pit == peers.end()) { | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | uint64_t PeerManager::compact() { | ||||
// Shrink the vector to the expected size. | // Shrink the vector to the expected size. | ||||
while (slots.size() > peers.size()) { | while (slots.size() > peers.size()) { | ||||
slots.pop_back(); | slots.pop_back(); | ||||
} | } | ||||
uint64_t prevStop = 0; | uint64_t prevStop = 0; | ||||
uint32_t i = 0; | uint32_t i = 0; | ||||
for (auto &pair : peers) { | for (auto it = peers.begin(); it != peers.end(); it++) { | ||||
PeerId pid = pair.first; | slots[i] = Slot(prevStop, it->score, it->peerid); | ||||
Peer &p = pair.second; | |||||
slots[i] = Slot(prevStop, p.score, pid); | |||||
prevStop = slots[i].getStop(); | prevStop = slots[i].getStop(); | ||||
p.index = i++; | peers.modify(it, [&](Peer &p) { p.index = i++; }); | ||||
} | } | ||||
const uint64_t saved = slotCount - prevStop; | const uint64_t saved = slotCount - prevStop; | ||||
slotCount = prevStop; | slotCount = prevStop; | ||||
fragmentation = 0; | fragmentation = 0; | ||||
return saved; | return saved; | ||||
} | } | ||||
Show All 12 Lines | for (size_t i = 0; i < slots.size(); i++) { | ||||
// If this is a dead slot, then nothing more needs to be checked. | // If this is a dead slot, then nothing more needs to be checked. | ||||
if (s.getPeerId() == NO_PEER) { | if (s.getPeerId() == NO_PEER) { | ||||
continue; | continue; | ||||
} | } | ||||
// We have a live slot, verify index. | // We have a live slot, verify index. | ||||
auto it = peers.find(s.getPeerId()); | auto it = peers.find(s.getPeerId()); | ||||
if (it == peers.end() || it->second.index != i) { | if (it == peers.end() || it->index != i) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
for (const auto &pair : peers) { | for (const auto &p : peers) { | ||||
auto p = pair.first; | |||||
auto i = pair.second.index; | |||||
auto s = pair.second.score; | |||||
// The index must point to a slot refering to this peer. | // The index must point to a slot refering to this peer. | ||||
if (i >= slots.size() || slots[i].getPeerId() != p) { | if (p.index >= slots.size() || slots[p.index].getPeerId() != p.peerid) { | ||||
return false; | return false; | ||||
} | } | ||||
// If the score do not match, same thing. | // If the score do not match, same thing. | ||||
if (slots[i].getScore() != s) { | if (slots[p.index].getScore() != p.score) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
PeerId selectPeerImpl(const std::vector<Slot> &slots, const uint64_t slot, | PeerId selectPeerImpl(const std::vector<Slot> &slots, const uint64_t slot, | ||||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |