Refactor ProcessGetData in anticipation of avoiding cs_main for ABC

This commit is contained in:
Matt Corallo 2017-12-24 11:58:20 -05:00
parent 818075adac
commit 66aa1d58a1

View file

@ -1038,29 +1038,11 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc)); connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
} }
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensusParams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{ {
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
std::vector<CInv> vNotFound;
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
LOCK(cs_main); LOCK(cs_main);
while (it != pfrom->vRecvGetData.end()) {
// Don't bother if send buffer is too full to respond anyway
if (pfrom->fPauseSend)
break;
const CInv &inv = *it;
{
if (interruptMsgProc)
return;
it++;
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK)
{
bool send = false; bool send = false;
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
std::shared_ptr<const CBlock> a_recent_block; std::shared_ptr<const CBlock> a_recent_block;
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block; std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
bool fWitnessesPresentInARecentCompactBlock; bool fWitnessesPresentInARecentCompactBlock;
@ -1070,6 +1052,9 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
a_recent_compact_block = most_recent_compact_block; a_recent_compact_block = most_recent_compact_block;
fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock; fWitnessesPresentInARecentCompactBlock = fWitnessesPresentInMostRecentCompactBlock;
} }
{
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
if (mi != mapBlockIndex.end()) if (mi != mapBlockIndex.end())
{ {
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) && if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
@ -1082,11 +1067,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
CValidationState dummy; CValidationState dummy;
ActivateBestChain(dummy, Params(), a_recent_block); ActivateBestChain(dummy, Params(), a_recent_block);
} }
}
}
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
if (mi != mapBlockIndex.end()) {
send = BlockRequestAllowed(mi->second, consensusParams); send = BlockRequestAllowed(mi->second, consensusParams);
if (!send) { if (!send) {
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId()); LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
} }
} }
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
// disconnect node in case we have reached the outbound limit for serving historical blocks // disconnect node in case we have reached the outbound limit for serving historical blocks
// never disconnect whitelisted nodes // never disconnect whitelisted nodes
if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
@ -1183,9 +1173,26 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
pfrom->hashContinue.SetNull(); pfrom->hashContinue.SetNull();
} }
} }
} }
else if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX)
void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
std::vector<CInv> vNotFound;
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
{ {
LOCK(cs_main);
while (it != pfrom->vRecvGetData.end() && (it->type == MSG_TX || it->type == MSG_WITNESS_TX)) {
if (interruptMsgProc)
return;
// Don't bother if send buffer is too full to respond anyway
if (pfrom->fPauseSend)
break;
const CInv &inv = *it;
it++;
// Send stream from relay memory // Send stream from relay memory
bool push = false; bool push = false;
auto mi = mapRelay.find(inv.hash); auto mi = mapRelay.find(inv.hash);
@ -1205,15 +1212,19 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if (!push) { if (!push) {
vNotFound.push_back(inv); vNotFound.push_back(inv);
} }
}
// Track requests for our stuff. // Track requests for our stuff.
GetMainSignals().Inventory(inv.hash); GetMainSignals().Inventory(inv.hash);
}
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) if (it != pfrom->vRecvGetData.end()) {
break; const CInv &inv = *it;
it++;
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
ProcessGetBlockData(pfrom, consensusParams, inv, connman, interruptMsgProc);
} }
} }
} // release cs_main
pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it); pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);