From: CryptoManiac Date: Mon, 28 Jul 2014 18:57:22 +0000 (+0400) Subject: Make sure we always have a node to do IBD from X-Git-Tag: v0.4.4.6-nvc-update7~5^2~1 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=28f9882707d389250e307ebf58dcf981340f1381 Make sure we always have a node to do IBD from This introduces the concept of the 'sync node', which is the one we asked for missing blocks. In case the sync node goes away, a new one will be selected. --- diff --git a/src/main.cpp b/src/main.cpp index fa8f993..9a521fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3985,6 +3985,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->PushMessage("ping"); } + // Start block sync + if (pto->fStartSync) { + pto->fStartSync = false; + pto->PushGetBlocks(pindexBest, uint256(0)); + } + // Resend wallet transactions that haven't gotten in a block yet ResendWalletTransactions(); diff --git a/src/net.cpp b/src/net.cpp index 16439a7..cd826d6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -55,6 +55,7 @@ static map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; +static CNode* pnodeSync = NULL; CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices); uint64 nLocalHostNonce = 0; array vnThreadsRunning; @@ -539,6 +540,15 @@ void CNode::CloseSocketDisconnect() hSocket = INVALID_SOCKET; vRecv.clear(); } + + // in case this fails, we'll empty the recv buffer when the CNode is deleted + TRY_LOCK(cs_vRecv, lockRecv); + if (lockRecv) + vRecv.clear(); + + // if this was the sync node, we'll need a new one + if (this == pnodeSync) + pnodeSync = NULL; } void CNode::Cleanup() @@ -1572,12 +1582,37 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu return true; } +// for now, use a very simple selection metric: the node from which we received +// most recently +double static NodeSyncScore(const CNode *pnode) { + return -pnode->nLastRecv; +} - - - - - +void static StartSync(const vector &vNodes) { + CNode *pnodeNewSync = NULL; + double dBestScore = 0; + + // Iterate over all nodes + BOOST_FOREACH(CNode* pnode, vNodes) { + // check preconditions for allowing a sync + if (!pnode->fClient && !pnode->fOneShot && + !pnode->fDisconnect && pnode->fSuccessfullyConnected && + (pnode->nStartingHeight > (nBestHeight - 144)) && + (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) { + // if ok, compare node's score with the best so far + double dScore = NodeSyncScore(pnode); + if (pnodeNewSync == NULL || dScore > dBestScore) { + pnodeNewSync = pnode; + dBestScore = dScore; + } + } + } + // if a new sync candidate was found, start sync! + if (pnodeNewSync) { + pnodeNewSync->fStartSync = true; + pnodeSync = pnodeNewSync; + } +} void ThreadMessageHandler(void* parg) { @@ -1606,14 +1641,21 @@ void ThreadMessageHandler2(void* parg) SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); while (!fShutdown) { + bool fHaveSyncNode = false; vector vNodesCopy; { LOCK(cs_vNodes); vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + BOOST_FOREACH(CNode* pnode, vNodesCopy) { pnode->AddRef(); + if (pnode == pnodeSync) + fHaveSyncNode = true; + } } + if (!fHaveSyncNode) + StartSync(vNodesCopy); + // Poll the connected nodes for messages CNode* pnodeTrickle = NULL; if (!vNodesCopy.empty()) diff --git a/src/net.h b/src/net.h index 0d51bff..c1d478a 100644 --- a/src/net.h +++ b/src/net.h @@ -197,6 +197,7 @@ public: CBlockIndex* pindexLastGetBlocksBegin; uint256 hashLastGetBlocksEnd; int nStartingHeight; + bool fStartSync; // flood relay std::vector vAddrToSend; @@ -237,6 +238,7 @@ public: pindexLastGetBlocksBegin = 0; hashLastGetBlocksEnd = 0; nStartingHeight = -1; + fStartSync = false; fGetAddr = false; nMisbehavior = 0; hashCheckpointKnown = 0;