-
Notifications
You must be signed in to change notification settings - Fork 36.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net processing: Move peer_map to PeerManager #19910
Conversation
Requested by @MarcoFalke @sdaftuar and @theuni . Review very much appreciated 🙏 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
src/rpc/net.cpp
Outdated
@@ -156,7 +156,10 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) | |||
for (const CNodeStats& stats : vstats) { | |||
UniValue obj(UniValue::VOBJ); | |||
CNodeStateStats statestats; | |||
bool fStateStats = GetNodeStateStats(stats.nodeid, statestats); | |||
bool fStateStats{false}; | |||
if (node.peerman) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is currently not possible to not have node.peerman
. I think an Ensure..()
like EnsureMempool
would be good. It doesn't really make sense to call getpeerinfo
without a peerman anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done something slightly different and checked existence at the top of this function. Let me know what you think.
e4488c3
to
322e87b
Compare
Concept ACK. |
Concept ACK: decoupling is good! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 322e87b, I have reviewed the code and it looks OK.
322e87b
to
d350feb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK d350feb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
Concept ACK. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
b28f866
to
658ca70
Compare
658ca70
to
1b25b5c
Compare
1b25b5c
to
2ce2ec1
Compare
3bf5917
to
aedd418
Compare
rebased |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/net_processing.cpp
Outdated
PeerRef ret; | ||
LOCK(m_peer_mutex); | ||
auto it = m_peer_map.find(id); | ||
return it != m_peer_map.end() ? it->second : nullptr; | ||
if (it != m_peer_map.end()) ret = it->second; | ||
return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these changes required? What are benefits to return an empty shared pointer instead nullptr
-constructed one? Btw, in all caller places the return value is checked for nullptr
, not being empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes is clear that NRVO can be used, since there's only one return statement. I'm not sure if the previous version would have used copy elision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for considering this!
I'd be curious to know if compilers are allowed to rearrange the code before deciding how many return statements there are. I could see this going either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering the before-change code, to be precise, in C++17 in a return statement, when the operand is a prvalue (the result of the ternary conditional expression), elision of copy/move operations is mandatory.
OTOH, NRVO is non-mandatory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @hebasto! Yes, I think you're right. If I'm reading it correctly, the result of the conditional operator is a prvalue (item 5 in https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator since 4 doesn't apply), and copy elision is mandatory for returning a prvalue.
I've reverted this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and copy elision is mandatory for returning a prvalue.
Good to have C++17 :)
Code Review ACK aedd418 Private members >> Anon-namespaced statics/functions Especially when the functionality is strongly intertwined with the class of which it's being made a member. |
aedd418
to
5a1f08c
Compare
Rebased and addressed outstanding review comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows us to avoid repeated locking in FinalizeNode()
4fe77ae
to
3025ca9
Compare
PeerRef PeerManager::RemovePeer(NodeId id) | ||
{ | ||
PeerRef ret; | ||
LOCK(m_peer_mutex); | ||
auto it = m_peer_map.find(id); | ||
if (it != m_peer_map.end()) { | ||
ret = std::move(it->second); | ||
m_peer_map.erase(it); | ||
} | ||
return ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3025ca9
I'm curios is it possible to force the mandatory copy/move elision for the return value here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-ACK 3025ca9. |
Re-ACK 3025ca9
|
@@ -842,11 +790,9 @@ void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) { | |||
LOCK(cs_main); | |||
int misbehavior{0}; | |||
{ | |||
PeerRef peer = GetPeerRef(nodeid); | |||
PeerRef peer = RemovePeer(nodeid); | |||
assert(peer != nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting bitcoind crashing due to this assert. It appears that sometimes FinalizeNode gets called twice (from DeleteNode()). Perhaps nRefCount is being increased between the two occurances. This only seems to happen though when there's a delay between them due to UpdateTip(). It's probably a bug I've introduced somewhere, but just leaving this comment as a "heads up".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I expect if the bug was present in master we'd have seen it in CI or from a user report.
This moves
g_peer_map
from a global in net_processing.cpp's unnamed namespace to being a memberm_peer_map
ofPeerManager
.