Browse Source

Merge pull request #5976

8ba7f84 Reduce download timeouts as blocks arrive (Suhas Daftuar)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
9f7809f6c3
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 32
      src/main.cpp

32
src/main.cpp

@ -154,8 +154,8 @@ namespace {
uint256 hash; uint256 hash;
CBlockIndex *pindex; //! Optional. CBlockIndex *pindex; //! Optional.
int64_t nTime; //! Time of "getdata" request in microseconds. int64_t nTime; //! Time of "getdata" request in microseconds.
int nValidatedQueuedBefore; //! Number of blocks queued with validated headers (globally) at the time this one is requested.
bool fValidatedHeaders; //! Whether this block has validated headers at the time of request. bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
}; };
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
@ -216,6 +216,7 @@ struct CNodeState {
int64_t nStallingSince; int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight; list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight; int nBlocksInFlight;
int nBlocksInFlightValidHeaders;
//! Whether we consider this a preferred download peer. //! Whether we consider this a preferred download peer.
bool fPreferredDownload; bool fPreferredDownload;
@ -229,6 +230,7 @@ struct CNodeState {
fSyncStarted = false; fSyncStarted = false;
nStallingSince = 0; nStallingSince = 0;
nBlocksInFlight = 0; nBlocksInFlight = 0;
nBlocksInFlightValidHeaders = 0;
fPreferredDownload = false; fPreferredDownload = false;
} }
}; };
@ -260,6 +262,12 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload; nPreferredDownload += state->fPreferredDownload;
} }
// Returns time at which to timeout block request (nTime in microseconds)
int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore)
{
return nTime + 500000 * Params().GetConsensus().nPowTargetSpacing * (4 + nValidatedQueuedBefore);
}
void InitializeNode(NodeId nodeid, const CNode *pnode) { void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main); LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second; CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
@ -292,6 +300,7 @@ void MarkBlockAsReceived(const uint256& hash) {
if (itInFlight != mapBlocksInFlight.end()) { if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first); CNodeState *state = State(itInFlight->second.first);
nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders; nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
state->vBlocksInFlight.erase(itInFlight->second.second); state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--; state->nBlocksInFlight--;
state->nStallingSince = 0; state->nStallingSince = 0;
@ -307,10 +316,12 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, CBlockIndex *pindex
// Make sure it's not listed somewhere already. // Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash); MarkBlockAsReceived(hash);
QueuedBlock newentry = {hash, pindex, GetTimeMicros(), nQueuedValidatedHeaders, pindex != NULL}; int64_t nNow = GetTimeMicros();
QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders)};
nQueuedValidatedHeaders += newentry.fValidatedHeaders; nQueuedValidatedHeaders += newentry.fValidatedHeaders;
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry); list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++; state->nBlocksInFlight++;
state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders;
mapBlocksInFlight[hash] = std::make_pair(nodeid, it); mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
} }
@ -5015,10 +5026,23 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes // being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
// to unreasonably increase our timeout. // to unreasonably increase our timeout.
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * consensusParams.nPowTargetSpacing * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) { // We also compare the block download timeout originally calculated against the time at which we'd disconnect
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id); // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're
// only looking at this peer's oldest request). This way a large queue in the past doesn't result in a
// permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing
// more quickly than once every 5 minutes, then we'll shorten the download window for this block).
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders);
if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
}
if (queuedBlock.nTimeDisconnect < nNow) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
pto->fDisconnect = true; pto->fDisconnect = true;
} }
}
// //
// Message: getdata (blocks) // Message: getdata (blocks)

Loading…
Cancel
Save