aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2013-04-05 00:43:04 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2013-04-07 19:19:13 +0200
commit6ed71b5e4faa2ea6d739eefa9c3dcc15db80439c (patch)
tree4ae32dd9b5153c1fd1cad299518ede52a9f1bf69 /src/net.cpp
parent31dead887d7658660e89d14c22d494baeca874e9 (diff)
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. For now, the heuristic is very simple, but it can easily be extended later to add better policies.
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp59
1 files changed, 52 insertions, 7 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 0defa96e40..4727f1e2e6 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -44,6 +44,7 @@ static map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
+static CNode* pnodeSync = NULL;
uint64 nLocalHostNonce = 0;
static std::vector<SOCKET> vhListenSocket;
CAddrMan addrman;
@@ -521,12 +522,16 @@ void CNode::CloseSocketDisconnect()
printf("disconnecting node %s\n", addrName.c_str());
closesocket(hSocket);
hSocket = INVALID_SOCKET;
-
- // in case this fails, we'll empty the recv buffer when the CNode is deleted
- TRY_LOCK(cs_vRecvMsg, lockRecv);
- if (lockRecv)
- vRecvMsg.clear();
}
+
+ // in case this fails, we'll empty the recv buffer when the CNode is deleted
+ TRY_LOCK(cs_vRecvMsg, lockRecv);
+ if (lockRecv)
+ vRecvMsg.clear();
+
+ // if this was the sync node, we'll need a new one
+ if (this == pnodeSync)
+ pnodeSync = NULL;
}
void CNode::Cleanup()
@@ -1546,24 +1551,64 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
}
+// 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<CNode*> &vNodes) {
+ CNode *pnodeNewSync = NULL;
+ double dBestScore = 0;
+ // fImporting and fReindex are accessed out of cs_main here, but only
+ // as an optimization - they are checked again in SendMessages.
+ if (fImporting || fReindex)
+ return;
-
+ // 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()
{
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
while (true)
{
+ bool fHaveSyncNode = false;
+
vector<CNode*> 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())