Skip to content

Commit cca221f

Browse files
committed
net: Drop CNodeRef for AttemptToEvictConnection
Locking for each operation here is unnecessary, and solves the wrong problem. Additionally, it introduces a problem when cs_vNodes is held in an owning class, to which invididual CNodeRefs won't have access. These should be weak pointers anyway, once vNodes contain shared pointers. Rather than using a refcounting class, use a 3-step process instead. 1. Lock vNodes long enough to snapshot the fields necessary for comparing 2. Unlock and do the comparison 3. Re-lock and mark the resulting node for disconnection if it still exists
1 parent 563f375 commit cca221f

File tree

1 file changed

+31
-53
lines changed

1 file changed

+31
-53
lines changed

src/net.cpp

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -794,51 +794,22 @@ void SocketSendData(CNode *pnode)
794794

795795
static std::list<CNode*> vNodesDisconnected;
796796

797-
class CNodeRef {
798-
public:
799-
CNodeRef(CNode *pnode) : _pnode(pnode) {
800-
LOCK(cs_vNodes);
801-
_pnode->AddRef();
802-
}
803-
804-
~CNodeRef() {
805-
LOCK(cs_vNodes);
806-
_pnode->Release();
807-
}
808-
809-
CNode& operator *() const {return *_pnode;};
810-
CNode* operator ->() const {return _pnode;};
811-
812-
CNodeRef& operator =(const CNodeRef& other)
813-
{
814-
if (this != &other) {
815-
LOCK(cs_vNodes);
816-
817-
_pnode->Release();
818-
_pnode = other._pnode;
819-
_pnode->AddRef();
820-
}
821-
return *this;
822-
}
823-
824-
CNodeRef(const CNodeRef& other):
825-
_pnode(other._pnode)
826-
{
827-
LOCK(cs_vNodes);
828-
_pnode->AddRef();
829-
}
830-
private:
831-
CNode *_pnode;
797+
struct NodeEvictionCandidate
798+
{
799+
NodeId id;
800+
int64_t nTimeConnected;
801+
int64_t nMinPingUsecTime;
802+
CAddress addr;
832803
};
833804

834-
static bool ReverseCompareNodeMinPingTime(const CNodeRef &a, const CNodeRef &b)
805+
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
835806
{
836-
return a->nMinPingUsecTime > b->nMinPingUsecTime;
807+
return a.nMinPingUsecTime > b.nMinPingUsecTime;
837808
}
838809

839-
static bool ReverseCompareNodeTimeConnected(const CNodeRef &a, const CNodeRef &b)
810+
static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
840811
{
841-
return a->nTimeConnected > b->nTimeConnected;
812+
return a.nTimeConnected > b.nTimeConnected;
842813
}
843814

844815
class CompareNetGroupKeyed
@@ -851,14 +822,14 @@ class CompareNetGroupKeyed
851822
GetRandBytes(vchSecretKey.data(), vchSecretKey.size());
852823
}
853824

854-
bool operator()(const CNodeRef &a, const CNodeRef &b)
825+
bool operator()(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
855826
{
856827
std::vector<unsigned char> vchGroupA, vchGroupB;
857828
CSHA256 hashA, hashB;
858829
std::vector<unsigned char> vchA(32), vchB(32);
859830

860-
vchGroupA = a->addr.GetGroup();
861-
vchGroupB = b->addr.GetGroup();
831+
vchGroupA = a.addr.GetGroup();
832+
vchGroupB = b.addr.GetGroup();
862833

863834
hashA.Write(begin_ptr(vchGroupA), vchGroupA.size());
864835
hashB.Write(begin_ptr(vchGroupB), vchGroupB.size());
@@ -882,7 +853,7 @@ class CompareNetGroupKeyed
882853
* simultaneously better at all of them than honest peers.
883854
*/
884855
static bool AttemptToEvictConnection(bool fPreferNewConnection) {
885-
std::vector<CNodeRef> vEvictionCandidates;
856+
std::vector<NodeEvictionCandidate> vEvictionCandidates;
886857
{
887858
LOCK(cs_vNodes);
888859

@@ -893,7 +864,8 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
893864
continue;
894865
if (node->fDisconnect)
895866
continue;
896-
vEvictionCandidates.push_back(CNodeRef(node));
867+
NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, node->addr};
868+
vEvictionCandidates.push_back(candidate);
897869
}
898870
}
899871

@@ -928,16 +900,16 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
928900
std::vector<unsigned char> naMostConnections;
929901
unsigned int nMostConnections = 0;
930902
int64_t nMostConnectionsTime = 0;
931-
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
932-
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
933-
mapAddrCounts[node->addr.GetGroup()].push_back(node);
934-
int64_t grouptime = mapAddrCounts[node->addr.GetGroup()][0]->nTimeConnected;
935-
size_t groupsize = mapAddrCounts[node->addr.GetGroup()].size();
903+
std::map<std::vector<unsigned char>, std::vector<NodeEvictionCandidate> > mapAddrCounts;
904+
BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) {
905+
mapAddrCounts[node.addr.GetGroup()].push_back(node);
906+
int64_t grouptime = mapAddrCounts[node.addr.GetGroup()][0].nTimeConnected;
907+
size_t groupsize = mapAddrCounts[node.addr.GetGroup()].size();
936908

937909
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
938910
nMostConnections = groupsize;
939911
nMostConnectionsTime = grouptime;
940-
naMostConnections = node->addr.GetGroup();
912+
naMostConnections = node.addr.GetGroup();
941913
}
942914
}
943915

@@ -952,9 +924,15 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
952924
return false;
953925

954926
// Disconnect from the network group with the most connections
955-
vEvictionCandidates[0]->fDisconnect = true;
956-
957-
return true;
927+
NodeId evicted = vEvictionCandidates.front().id;
928+
LOCK(cs_vNodes);
929+
for(std::vector<CNode*>::const_iterator it(vNodes.begin()); it != vNodes.end(); ++it) {
930+
if ((*it)->GetId() == evicted) {
931+
(*it)->fDisconnect = true;
932+
return true;
933+
}
934+
}
935+
return false;
958936
}
959937

960938
static void AcceptConnection(const ListenSocket& hListenSocket) {

0 commit comments

Comments
 (0)