From 66b02c93e69cfeaec6e7fa19a03bfb2649025a56 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Sep 2012 14:33:52 +0200 Subject: [PATCH] Move external block import to separate thread --- src/init.cpp | 22 +++------------- src/main.cpp | 60 ++++++++++++++++++++++++++++++++++++++---- src/main.h | 3 ++- src/net.h | 1 + src/qt/bitcoingui.cpp | 4 +-- src/qt/clientmodel.cpp | 5 ++++ src/qt/clientmodel.h | 2 ++ 7 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 8a928218b..92c752a8f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -776,29 +776,13 @@ bool AppInit2() // ********************************************************* Step 9: import blocks + std::vector *vPath = new std::vector(); if (mapArgs.count("-loadblock")) { - uiInterface.InitMessage(_("Importing blockchain data file.")); - BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) - { - FILE *file = fopen(strFile.c_str(), "rb"); - if (file) - LoadExternalBlockFile(file); - } - } - - filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (filesystem::exists(pathBootstrap)) { - uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); - - FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); - if (file) { - filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; - LoadExternalBlockFile(file); - RenameOver(pathBootstrap, pathBootstrapOld); - } + vPath->push_back(strFile); } + NewThread(ThreadImport, vPath); // ********************************************************* Step 10: load peers diff --git a/src/main.cpp b/src/main.cpp index 28bf01a8c..a5179b652 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,6 +38,7 @@ CBigNum bnBestInvalidWork = 0; uint256 hashBestChain = 0; CBlockIndex* pindexBest = NULL; int64 nTimeBestReceived = 0; +bool fImporting = false; CMedianFilter cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have @@ -2251,7 +2252,6 @@ bool LoadExternalBlockFile(FILE* fileIn) int nLoaded = 0; { - LOCK(cs_main); try { CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION); unsigned int nPos = 0; @@ -2288,6 +2288,7 @@ bool LoadExternalBlockFile(FILE* fileIn) { CBlock block; blkdat >> block; + LOCK(cs_main); if (ProcessBlock(NULL,&block)) { nLoaded++; @@ -2305,6 +2306,54 @@ bool LoadExternalBlockFile(FILE* fileIn) return nLoaded > 0; } +struct CImportingNow +{ + CImportingNow() { + assert(fImporting == false); + fImporting = true; + } + + ~CImportingNow() { + assert(fImporting == true); + fImporting = false; + } +}; + +void ThreadImport(void *data) { + std::vector *vFiles = reinterpret_cast*>(data); + + RenameThread("bitcoin-loadblk"); + + CImportingNow imp; + vnThreadsRunning[THREAD_IMPORT]++; + + // -loadblock= + uiInterface.InitMessage(_("Starting block import...")); + BOOST_FOREACH(boost::filesystem::path &path, *vFiles) { + FILE *file = fopen(path.string().c_str(), "rb"); + if (file) + LoadExternalBlockFile(file); + } + + // hardcoded $DATADIR/bootstrap.dat + filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (filesystem::exists(pathBootstrap)) { + uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); + + FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); + if (file) { + filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + LoadExternalBlockFile(file); + RenameOver(pathBootstrap, pathBootstrapOld); + } + } + + delete vFiles; + + vnThreadsRunning[THREAD_IMPORT]--; +} + + @@ -2512,7 +2561,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) // Ask the first connected node for block updates static int nAskedForBlocks = 0; - if (!pfrom->fClient && !pfrom->fOneShot && + if (!pfrom->fClient && !pfrom->fOneShot && !fImporting && (pfrom->nStartingHeight > (nBestHeight - 144)) && (pfrom->nVersion < NOBLKS_VERSION_START || pfrom->nVersion >= NOBLKS_VERSION_END) && @@ -2649,9 +2698,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (fDebug) printf(" got inventory: %s %s\n", inv.ToString().c_str(), fAlreadyHave ? "have" : "new"); - if (!fAlreadyHave) - pfrom->AskFor(inv); - else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) { + if (!fAlreadyHave) { + if (!fImporting) + pfrom->AskFor(inv); + } else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) { pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); } else if (nInv == nLastBlock) { // In case we are on a very long side-chain, it is possible that we already have diff --git a/src/main.h b/src/main.h index 68302b85a..ea71baf90 100644 --- a/src/main.h +++ b/src/main.h @@ -68,6 +68,7 @@ extern int64 nTimeBestReceived; extern CCriticalSection cs_setpwalletRegistered; extern std::set setpwalletRegistered; extern unsigned char pchMessageStart[4]; +extern bool fImporting; // Settings extern int64 nTransactionFee; @@ -92,7 +93,7 @@ void PrintBlockTree(); CBlockIndex* FindBlockByHeight(int nHeight); bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, bool fSendTrickle); -bool LoadExternalBlockFile(FILE* fileIn); +void ThreadImport(void *parg); void GenerateBitcoins(bool fGenerate, CWallet* pwallet); CBlock* CreateNewBlock(CReserveKey& reservekey); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); diff --git a/src/net.h b/src/net.h index 3717c4e63..5e1564f9c 100644 --- a/src/net.h +++ b/src/net.h @@ -106,6 +106,7 @@ enum threadId THREAD_ADDEDCONNECTIONS, THREAD_DUMPADDRESS, THREAD_RPCHANDLER, + THREAD_IMPORT, THREAD_MAX }; diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 19a6a65a1..0d269ea21 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -473,7 +473,7 @@ void BitcoinGUI::setNumConnections(int count) void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) { // don't show / hide progress bar and its label if we have no connection to the network - if (!clientModel || clientModel->getNumConnections() == 0) + if (!clientModel || (clientModel->getNumConnections() == 0 && !clientModel->isImporting())) { progressBarLabel->setVisible(false); progressBar->setVisible(false); @@ -491,7 +491,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) if (strStatusBarWarnings.isEmpty()) { - progressBarLabel->setText(tr("Synchronizing with network...")); + progressBarLabel->setText(tr(clientModel->isImporting() ? "Importing blocks..." : "Synchronizing with network...")); progressBarLabel->setVisible(true); progressBar->setFormat(tr("~%n block(s) remaining", "", nRemainingBlocks)); progressBar->setMaximum(nTotalBlocks); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index b820d16ab..990b364a9 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -103,6 +103,11 @@ bool ClientModel::inInitialBlockDownload() const return IsInitialBlockDownload(); } +bool ClientModel::isImporting() const +{ + return fImporting; +} + int ClientModel::getNumBlocksOfPeers() const { return GetNumBlocksOfPeers(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 70d816ba9..926390a07 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -33,6 +33,8 @@ public: bool isTestNet() const; //! Return true if core is doing initial block download bool inInitialBlockDownload() const; + //! Return true if core is importing blocks + bool isImporting() const; //! Return conservative estimate of total number of blocks, or 0 if unknown int getNumBlocksOfPeers() const; //! Return warnings to be displayed in status bar