@@ -471,6 +471,43 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
471
471
return &it->second ;
472
472
}
473
473
474
+ /* *
475
+ * Data structure for an individual peer. This struct is not protected by
476
+ * cs_main since it does not contain validation-critical data.
477
+ *
478
+ * Memory is owned by shared pointers and this object is destructed when
479
+ * the refcount drops to zero.
480
+ *
481
+ * TODO: move most members from CNodeState to this structure.
482
+ * TODO: move remaining application-layer data members from CNode to this structure.
483
+ */
484
+ struct Peer {
485
+ /* * Same id as the CNode object for this peer */
486
+ const NodeId m_id{0 };
487
+
488
+ Peer (NodeId id) : m_id(id) {}
489
+ };
490
+
491
+ using PeerRef = std::shared_ptr<Peer>;
492
+
493
+ /* *
494
+ * Map of all Peer objects, keyed by peer id. This map is protected
495
+ * by the global g_peer_mutex. Once a shared pointer reference is
496
+ * taken, the lock may be released. Individual fields are protected by
497
+ * their own locks.
498
+ */
499
+ Mutex g_peer_mutex;
500
+ static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY (g_peer_mutex);
501
+
502
+ /* * Get a shared pointer to the Peer object.
503
+ * May return nullptr if the Peer object can't be found. */
504
+ static PeerRef GetPeerRef (NodeId id)
505
+ {
506
+ LOCK (g_peer_mutex);
507
+ auto it = g_peer_map.find (id);
508
+ return it != g_peer_map.end () ? it->second : nullptr ;
509
+ }
510
+
474
511
static void UpdatePreferredDownload (const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
475
512
{
476
513
nPreferredDownload -= state->fPreferredDownload ;
@@ -838,6 +875,11 @@ void PeerLogicValidation::InitializeNode(CNode *pnode) {
838
875
LOCK (cs_main);
839
876
mapNodeState.emplace_hint (mapNodeState.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (addr, pnode->IsInboundConn (), pnode->IsManualConn ()));
840
877
}
878
+ {
879
+ PeerRef peer = std::make_shared<Peer>(nodeid);
880
+ LOCK (g_peer_mutex);
881
+ g_peer_map.emplace_hint (g_peer_map.end (), nodeid, std::move (peer));
882
+ }
841
883
if (!pnode->IsInboundConn ())
842
884
PushNodeVersion (*pnode, *connman, GetTime ());
843
885
}
@@ -865,6 +907,10 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const
865
907
void PeerLogicValidation::FinalizeNode (NodeId nodeid, bool & fUpdateConnectionTime ) {
866
908
fUpdateConnectionTime = false ;
867
909
LOCK (cs_main);
910
+ {
911
+ LOCK (g_peer_mutex);
912
+ g_peer_map.erase (nodeid);
913
+ }
868
914
CNodeState *state = State (nodeid);
869
915
assert (state != nullptr );
870
916
0 commit comments