diff --git a/src/avalanche/peermanager.h b/src/avalanche/peermanager.h --- a/src/avalanche/peermanager.h +++ b/src/avalanche/peermanager.h @@ -123,6 +123,8 @@ bool addNodeToPeer(PeerId peerid, NodeId nodeid, CPubKey pubkey); bool removeNode(NodeId nodeid); + bool updateNextRequestTime(NodeId nodeid, TimePoint timeout); + NodeId getSuitableNodeToQuery(); /** diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp --- a/src/avalanche/peermanager.cpp +++ b/src/avalanche/peermanager.cpp @@ -112,6 +112,15 @@ return nodes.erase(nodeid) > 0; } +bool PeerManager::updateNextRequestTime(NodeId nodeid, TimePoint timeout) { + auto it = nodes.find(nodeid); + if (it == nodes.end()) { + return false; + } + + return nodes.modify(it, [&](Node &n) { n.nextRequestTime = timeout; }); +} + NodeId PeerManager::getSuitableNodeToQuery() { for (int retry = 0; retry < SELECT_NODE_MAX_RETRY; retry++) { const PeerId p = selectPeer(); diff --git a/src/avalanche/test/peermanager_tests.cpp b/src/avalanche/test/peermanager_tests.cpp --- a/src/avalanche/test/peermanager_tests.cpp +++ b/src/avalanche/test/peermanager_tests.cpp @@ -365,6 +365,8 @@ for (int i = 0; i < 100; i++) { NodeId n = pm.getSuitableNodeToQuery(); BOOST_CHECK(n >= 0 && n < 4); + BOOST_CHECK( + pm.updateNextRequestTime(n, std::chrono::steady_clock::now())); } // Remove a node, check that it doesn't show up. @@ -373,6 +375,42 @@ for (int i = 0; i < 100; i++) { NodeId n = pm.getSuitableNodeToQuery(); BOOST_CHECK(n == 0 || n == 1 || n == 3); + BOOST_CHECK( + pm.updateNextRequestTime(n, std::chrono::steady_clock::now())); + } + + // Push a node's timeout in the future, so that it doesn't show up. + BOOST_CHECK(pm.updateNextRequestTime(1, std::chrono::steady_clock::now() + + std::chrono::hours(24))); + + for (int i = 0; i < 100; i++) { + NodeId n = pm.getSuitableNodeToQuery(); + BOOST_CHECK(n == 0 || n == 3); + BOOST_CHECK( + pm.updateNextRequestTime(n, std::chrono::steady_clock::now())); + } + + // Move a node from a peer to another. + PeerId altpeer = pm.addPeer(0); + BOOST_CHECK(pm.addNodeToPeer(altpeer, 3, CPubKey())); + + for (int i = 0; i < 100; i++) { + NodeId n = pm.getSuitableNodeToQuery(); + BOOST_CHECK(n == 0); + BOOST_CHECK( + pm.updateNextRequestTime(n, std::chrono::steady_clock::now())); + } + + // Rescore peers and cheks node selection is affected as expected. + BOOST_CHECK(pm.rescorePeer(peerid, 0)); + BOOST_CHECK(pm.rescorePeer(altpeer, 100)); + BOOST_CHECK_EQUAL(pm.compact(), 100); + + for (int i = 0; i < 100; i++) { + NodeId n = pm.getSuitableNodeToQuery(); + BOOST_CHECK(n == 3); + BOOST_CHECK( + pm.updateNextRequestTime(n, std::chrono::steady_clock::now())); } }