Skip to content

Commit 795afe6

Browse files
committed
Merge #19910: net processing: Move peer_map to PeerManager
3025ca9 [net processing] Add RemovePeer() (John Newbery) a20ab22 [net processing] Make GetPeerRef const (John Newbery) ed7e469 [net_processing] Move peer_map to PeerManager (John Newbery) a529fd3 [net processing] Move GetNodeStateStats into PeerManager (John Newbery) Pull request description: This moves `g_peer_map` from a global in net_processing.cpp's unnamed namespace to being a member `m_peer_map` of `PeerManager`. ACKs for top commit: theuni: Re-ACK 3025ca9. dongcarl: Re-ACK 3025ca9 hebasto: re-ACK 3025ca9, since my [previous](bitcoin/bitcoin#19910 (review)) review only reverted the change that introduced NRVO in `PeerManager::GetPeerRef`, and comments are fixed in the proper commits. Tree-SHA512: 6369eb3c688ac5b84f89f7674115f78ff02edbed76063ac2ebb1759894c9e973883e10821a35dab92bd3d738280acc095bd5368f552a060b83cd309330387d47
2 parents a3586d5 + 3025ca9 commit 795afe6

File tree

4 files changed

+94
-74
lines changed

4 files changed

+94
-74
lines changed

src/net_processing.cpp

Lines changed: 23 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -422,58 +422,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
422422
return &it->second;
423423
}
424424

425-
/**
426-
* Data structure for an individual peer. This struct is not protected by
427-
* cs_main since it does not contain validation-critical data.
428-
*
429-
* Memory is owned by shared pointers and this object is destructed when
430-
* the refcount drops to zero.
431-
*
432-
* TODO: move most members from CNodeState to this structure.
433-
* TODO: move remaining application-layer data members from CNode to this structure.
434-
*/
435-
struct Peer {
436-
/** Same id as the CNode object for this peer */
437-
const NodeId m_id{0};
438-
439-
/** Protects misbehavior data members */
440-
Mutex m_misbehavior_mutex;
441-
/** Accumulated misbehavior score for this peer */
442-
int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
443-
/** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
444-
bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
445-
446-
/** Set of txids to reconsider once their parent transactions have been accepted **/
447-
std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
448-
449-
/** Protects m_getdata_requests **/
450-
Mutex m_getdata_requests_mutex;
451-
/** Work queue of items requested by this peer **/
452-
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
453-
454-
explicit Peer(NodeId id) : m_id(id) {}
455-
};
456-
457-
using PeerRef = std::shared_ptr<Peer>;
458-
459-
/**
460-
* Map of all Peer objects, keyed by peer id. This map is protected
461-
* by the global g_peer_mutex. Once a shared pointer reference is
462-
* taken, the lock may be released. Individual fields are protected by
463-
* their own locks.
464-
*/
465-
Mutex g_peer_mutex;
466-
static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY(g_peer_mutex);
467-
468-
/** Get a shared pointer to the Peer object.
469-
* May return nullptr if the Peer object can't be found. */
470-
static PeerRef GetPeerRef(NodeId id)
471-
{
472-
LOCK(g_peer_mutex);
473-
auto it = g_peer_map.find(id);
474-
return it != g_peer_map.end() ? it->second : nullptr;
475-
}
476-
477425
static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
478426
{
479427
nPreferredDownload -= state->fPreferredDownload;
@@ -807,8 +755,8 @@ void PeerManager::InitializeNode(CNode *pnode) {
807755
}
808756
{
809757
PeerRef peer = std::make_shared<Peer>(nodeid);
810-
LOCK(g_peer_mutex);
811-
g_peer_map.emplace_hint(g_peer_map.end(), nodeid, std::move(peer));
758+
LOCK(m_peer_mutex);
759+
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
812760
}
813761
if (!pnode->IsInboundConn()) {
814762
PushNodeVersion(*pnode, m_connman, GetTime());
@@ -842,11 +790,9 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) {
842790
LOCK(cs_main);
843791
int misbehavior{0};
844792
{
845-
PeerRef peer = GetPeerRef(nodeid);
793+
PeerRef peer = RemovePeer(nodeid);
846794
assert(peer != nullptr);
847795
misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score);
848-
LOCK(g_peer_mutex);
849-
g_peer_map.erase(nodeid);
850796
}
851797
CNodeState *state = State(nodeid);
852798
assert(state != nullptr);
@@ -887,7 +833,26 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) {
887833
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
888834
}
889835

890-
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
836+
PeerRef PeerManager::GetPeerRef(NodeId id) const
837+
{
838+
LOCK(m_peer_mutex);
839+
auto it = m_peer_map.find(id);
840+
return it != m_peer_map.end() ? it->second : nullptr;
841+
}
842+
843+
PeerRef PeerManager::RemovePeer(NodeId id)
844+
{
845+
PeerRef ret;
846+
LOCK(m_peer_mutex);
847+
auto it = m_peer_map.find(id);
848+
if (it != m_peer_map.end()) {
849+
ret = std::move(it->second);
850+
m_peer_map.erase(it);
851+
}
852+
return ret;
853+
}
854+
855+
bool PeerManager::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
891856
{
892857
LOCK(cs_main);
893858
CNodeState* state = State(nodeid);

src/net_processing.h

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,47 @@ static const bool DEFAULT_PEERBLOCKFILTERS = false;
3232
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
3333
static const int DISCOURAGEMENT_THRESHOLD{100};
3434

35+
struct CNodeStateStats {
36+
int m_misbehavior_score = 0;
37+
int nSyncHeight = -1;
38+
int nCommonHeight = -1;
39+
std::vector<int> vHeightInFlight;
40+
};
41+
42+
/**
43+
* Data structure for an individual peer. This struct is not protected by
44+
* cs_main since it does not contain validation-critical data.
45+
*
46+
* Memory is owned by shared pointers and this object is destructed when
47+
* the refcount drops to zero.
48+
*
49+
* TODO: move most members from CNodeState to this structure.
50+
* TODO: move remaining application-layer data members from CNode to this structure.
51+
*/
52+
struct Peer {
53+
/** Same id as the CNode object for this peer */
54+
const NodeId m_id{0};
55+
56+
/** Protects misbehavior data members */
57+
Mutex m_misbehavior_mutex;
58+
/** Accumulated misbehavior score for this peer */
59+
int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
60+
/** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
61+
bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
62+
63+
/** Set of txids to reconsider once their parent transactions have been accepted **/
64+
std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
65+
66+
/** Protects m_getdata_requests **/
67+
Mutex m_getdata_requests_mutex;
68+
/** Work queue of items requested by this peer **/
69+
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
70+
71+
explicit Peer(NodeId id) : m_id(id) {}
72+
};
73+
74+
using PeerRef = std::shared_ptr<Peer>;
75+
3576
class PeerManager final : public CValidationInterface, public NetEventsInterface {
3677
public:
3778
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
@@ -94,7 +135,18 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface
94135
*/
95136
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);
96137

138+
/** Get statistics from node state */
139+
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats);
140+
97141
private:
142+
/** Get a shared pointer to the Peer object.
143+
* May return an empty shared_ptr if the Peer object can't be found. */
144+
PeerRef GetPeerRef(NodeId id) const;
145+
146+
/** Get a shared pointer to the Peer object and remove it from m_peer_map.
147+
* May return an empty shared_ptr if the Peer object can't be found. */
148+
PeerRef RemovePeer(NodeId id);
149+
98150
/**
99151
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
100152
*
@@ -143,18 +195,18 @@ class PeerManager final : public CValidationInterface, public NetEventsInterface
143195
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
144196

145197
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
146-
};
147198

148-
struct CNodeStateStats {
149-
int m_misbehavior_score = 0;
150-
int nSyncHeight = -1;
151-
int nCommonHeight = -1;
152-
std::vector<int> vHeightInFlight;
199+
/** Protects m_peer_map */
200+
mutable Mutex m_peer_mutex;
201+
/**
202+
* Map of all Peer objects, keyed by peer id. This map is protected
203+
* by the m_peer_mutex. Once a shared pointer reference is
204+
* taken, the lock may be released. Individual fields are protected by
205+
* their own locks.
206+
*/
207+
std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
153208
};
154209

155-
/** Get statistics from node state */
156-
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
157-
158210
/** Relay transaction to every node */
159211
void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
160212

src/node/interfaces.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,13 @@ class NodeImpl : public Node
121121
}
122122

123123
// Try to retrieve the CNodeStateStats for each node.
124-
TRY_LOCK(::cs_main, lockMain);
125-
if (lockMain) {
126-
for (auto& node_stats : stats) {
127-
std::get<1>(node_stats) =
128-
GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
124+
if (m_context->peerman) {
125+
TRY_LOCK(::cs_main, lockMain);
126+
if (lockMain) {
127+
for (auto& node_stats : stats) {
128+
std::get<1>(node_stats) =
129+
m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
130+
}
129131
}
130132
}
131133
return true;

src/rpc/net.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ static RPCHelpMan getpeerinfo()
165165
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
166166
{
167167
NodeContext& node = EnsureNodeContext(request.context);
168-
if(!node.connman)
168+
if(!node.connman || !node.peerman) {
169169
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
170+
}
170171

171172
std::vector<CNodeStats> vstats;
172173
node.connman->GetNodeStats(vstats);
@@ -176,7 +177,7 @@ static RPCHelpMan getpeerinfo()
176177
for (const CNodeStats& stats : vstats) {
177178
UniValue obj(UniValue::VOBJ);
178179
CNodeStateStats statestats;
179-
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
180+
bool fStateStats = node.peerman->GetNodeStateStats(stats.nodeid, statestats);
180181
obj.pushKV("id", stats.nodeid);
181182
obj.pushKV("addr", stats.addrName);
182183
if (stats.addrBind.IsValid()) {

0 commit comments

Comments
 (0)