Skip to content

Commit cce9618

Browse files
committed
Convert mapBlocksInFlight to a multimap
1 parent a905954 commit cce9618

File tree

1 file changed

+71
-37
lines changed

1 file changed

+71
-37
lines changed

src/net_processing.cpp

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,8 @@ class PeerManagerImpl final : public PeerManager
898898
*/
899899
void FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
900900

901-
typedef std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
901+
/* Multimap used to preserve insertion order */
902+
typedef std::multimap<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator>> BlockDownloadMap;
902903
BlockDownloadMap mapBlocksInFlight GUARDED_BY(cs_main);
903904

904905
/** When our tip was last updated. */
@@ -1122,34 +1123,40 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
11221123

11231124
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
11241125
{
1125-
auto it = mapBlocksInFlight.find(hash);
1126-
if (it == mapBlocksInFlight.end()) {
1127-
// Block was not requested
1126+
auto range = mapBlocksInFlight.equal_range(hash);
1127+
if (range.first == range.second) {
1128+
// Block was not requested from any peer
11281129
return;
11291130
}
11301131

1131-
auto [node_id, list_it] = it->second;
1132+
// Currently we don't request more than one peer for same block
1133+
Assume(mapBlocksInFlight.count(hash) == 1);
11321134

1133-
if (from_peer && node_id != *from_peer) {
1134-
// Block was requested by another peer
1135-
return;
1136-
}
1135+
while (range.first != range.second) {
1136+
auto [node_id, list_it] = range.first->second;
11371137

1138-
CNodeState *state = State(node_id);
1139-
assert(state != nullptr);
1138+
if (from_peer && *from_peer != node_id) {
1139+
range.first++;
1140+
continue;
1141+
}
11401142

1141-
if (state->vBlocksInFlight.begin() == list_it) {
1142-
// First block on the queue was received, update the start download time for the next one
1143-
state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
1144-
}
1145-
state->vBlocksInFlight.erase(list_it);
1143+
CNodeState *state = State(node_id);
1144+
assert(state != nullptr);
11461145

1147-
if (state->vBlocksInFlight.empty()) {
1148-
// Last validated block on the queue was received.
1149-
m_peers_downloading_from--;
1146+
if (state->vBlocksInFlight.begin() == list_it) {
1147+
// First block on the queue was received, update the start download time for the next one
1148+
state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
1149+
}
1150+
state->vBlocksInFlight.erase(list_it);
1151+
1152+
if (state->vBlocksInFlight.empty()) {
1153+
// Last validated block on the queue for this peer was received.
1154+
m_peers_downloading_from--;
1155+
}
1156+
state->m_stalling_since = 0us;
1157+
1158+
range.first = mapBlocksInFlight.erase(range.first);
11501159
}
1151-
state->m_stalling_since = 0us;
1152-
mapBlocksInFlight.erase(it);
11531160
}
11541161

11551162
bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
@@ -1160,12 +1167,13 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
11601167
assert(state != nullptr);
11611168

11621169
// Short-circuit most stuff in case it is from the same node
1163-
BlockDownloadMap::iterator itInFlight = mapBlocksInFlight.find(hash);
1164-
if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) {
1165-
if (pit) {
1166-
*pit = &itInFlight->second.second;
1170+
for (auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1171+
if (range.first->second.first == nodeid) {
1172+
if (pit) {
1173+
*pit = &range.first->second.second;
1174+
}
1175+
return false;
11671176
}
1168-
return false;
11691177
}
11701178

11711179
// Make sure it's not listed somewhere already.
@@ -1178,7 +1186,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
11781186
state->m_downloading_since = GetTime<std::chrono::microseconds>();
11791187
m_peers_downloading_from++;
11801188
}
1181-
itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it))).first;
1189+
auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
11821190
if (pit) {
11831191
*pit = &itInFlight->second.second;
11841192
}
@@ -1381,7 +1389,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int co
13811389
}
13821390
} else if (waitingfor == -1) {
13831391
// This is the first already-in-flight block.
1384-
waitingfor = mapBlocksInFlight[pindex->GetBlockHash()].first;
1392+
waitingfor = mapBlocksInFlight.lower_bound(pindex->GetBlockHash())->second.first;
13851393
}
13861394
}
13871395
}
@@ -1511,7 +1519,15 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
15111519
nSyncStarted--;
15121520

15131521
for (const QueuedBlock& entry : state->vBlocksInFlight) {
1514-
mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
1522+
auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1523+
while (range.first != range.second) {
1524+
auto [node_id, list_it] = range.first->second;
1525+
if (node_id != nodeid) {
1526+
range.first++;
1527+
} else {
1528+
range.first = mapBlocksInFlight.erase(range.first);
1529+
}
1530+
}
15151531
}
15161532
m_orphanage.EraseForPeer(nodeid);
15171533
m_txrequest.DisconnectedPeer(nodeid);
@@ -4272,12 +4288,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
42724288
nodestate->m_last_block_announcement = GetTime();
42734289
}
42744290

4275-
BlockDownloadMap::iterator blockInFlightIt = mapBlocksInFlight.find(pindex->GetBlockHash());
4276-
bool fAlreadyInFlight = blockInFlightIt != mapBlocksInFlight.end();
4277-
42784291
if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here
42794292
return;
42804293

4294+
auto range_flight = mapBlocksInFlight.equal_range(pindex->GetBlockHash());
4295+
bool fAlreadyInFlight = range_flight.first != range_flight.second;
4296+
bool in_flight_same_peer{false};
4297+
4298+
while (range_flight.first != range_flight.second) {
4299+
if (range_flight.first->second.first == pfrom.GetId()) {
4300+
in_flight_same_peer = true;
4301+
break;
4302+
}
4303+
range_flight.first++;
4304+
}
4305+
42814306
if (pindex->nChainWork <= m_chainman.ActiveChain().Tip()->nChainWork || // We know something better
42824307
pindex->nTx != 0) { // We had this block at some point, but pruned it
42834308
if (fAlreadyInFlight) {
@@ -4299,7 +4324,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
42994324
// possibilities in compact block processing...
43004325
if (pindex->nHeight <= m_chainman.ActiveChain().Height() + 2) {
43014326
if ((!fAlreadyInFlight && nodestate->vBlocksInFlight.size() < MAX_BLOCKS_IN_TRANSIT_PER_PEER) ||
4302-
(fAlreadyInFlight && blockInFlightIt->second.first == pfrom.GetId())) {
4327+
in_flight_same_peer) {
43034328
std::list<QueuedBlock>::iterator* queuedBlockIt = nullptr;
43044329
if (!BlockRequested(pfrom.GetId(), *pindex, &queuedBlockIt)) {
43054330
if (!(*queuedBlockIt)->partialBlock)
@@ -4431,14 +4456,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
44314456
{
44324457
LOCK(cs_main);
44334458

4434-
BlockDownloadMap::iterator it = mapBlocksInFlight.find(resp.blockhash);
4435-
if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
4436-
it->second.first != pfrom.GetId()) {
4459+
bool expected_blocktxn = false;
4460+
auto range_flight = mapBlocksInFlight.equal_range(resp.blockhash);
4461+
while (range_flight.first != range_flight.second) {
4462+
auto [node_id, block_it] = range_flight.first->second;
4463+
if (node_id == pfrom.GetId() && block_it->partialBlock) {
4464+
expected_blocktxn = true;
4465+
break;
4466+
}
4467+
range_flight.first++;
4468+
}
4469+
4470+
if (!expected_blocktxn) {
44374471
LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom.GetId());
44384472
return;
44394473
}
44404474

4441-
PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
4475+
PartiallyDownloadedBlock& partialBlock = *range_flight.first->second.second->partialBlock;
44424476
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
44434477
if (status == READ_STATUS_INVALID) {
44444478
RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect

0 commit comments

Comments
 (0)