changeset 3631:627fdda97160 draft

Move external block import to separate thread
author Pieter Wuille <pieter.wuille@gmail.com>
date Thu, 13 Sep 2012 14:33:52 +0200
parents badd5a8dd294
children 94f6e3e0c600
files src/init.cpp src/main.cpp src/main.h src/net.h src/qt/bitcoingui.cpp src/qt/clientmodel.cpp src/qt/clientmodel.h
diffstat 7 files changed, 70 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -776,29 +776,13 @@
 
     // ********************************************************* Step 9: import blocks
 
+    std::vector<boost::filesystem::path> *vPath = new std::vector<boost::filesystem::path>();
     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);
-        }
+            vPath->push_back(strFile);
     }
-
-    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);
-        }
-    }
+    NewThread(ThreadImport, vPath);
 
     // ********************************************************* Step 10: load peers
 
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,6 +38,7 @@
 uint256 hashBestChain = 0;
 CBlockIndex* pindexBest = NULL;
 int64 nTimeBestReceived = 0;
+bool fImporting = false;
 
 CMedianFilter<int> cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have
 
@@ -2251,7 +2252,6 @@
 
     int nLoaded = 0;
     {
-        LOCK(cs_main);
         try {
             CAutoFile blkdat(fileIn, SER_DISK, CLIENT_VERSION);
             unsigned int nPos = 0;
@@ -2288,6 +2288,7 @@
                 {
                     CBlock block;
                     blkdat >> block;
+                    LOCK(cs_main);
                     if (ProcessBlock(NULL,&block))
                     {
                         nLoaded++;
@@ -2305,6 +2306,54 @@
     return nLoaded > 0;
 }
 
+struct CImportingNow
+{
+    CImportingNow() {
+        assert(fImporting == false);
+        fImporting = true;
+    }
+
+    ~CImportingNow() {
+        assert(fImporting == true);
+        fImporting = false;
+    }
+};
+
+void ThreadImport(void *data) {
+    std::vector<boost::filesystem::path> *vFiles = reinterpret_cast<std::vector<boost::filesystem::path>*>(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 @@
 
         // 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 @@
             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
--- a/src/main.h
+++ b/src/main.h
@@ -68,6 +68,7 @@
 extern CCriticalSection cs_setpwalletRegistered;
 extern std::set<CWallet*> setpwalletRegistered;
 extern unsigned char pchMessageStart[4];
+extern bool fImporting;
 
 // Settings
 extern int64 nTransactionFee;
@@ -92,7 +93,7 @@
 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);
--- a/src/net.h
+++ b/src/net.h
@@ -106,6 +106,7 @@
     THREAD_ADDEDCONNECTIONS,
     THREAD_DUMPADDRESS,
     THREAD_RPCHANDLER,
+    THREAD_IMPORT,
 
     THREAD_MAX
 };
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -473,7 +473,7 @@
 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 @@
 
         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);
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -103,6 +103,11 @@
     return IsInitialBlockDownload();
 }
 
+bool ClientModel::isImporting() const
+{
+    return fImporting;
+}
+
 int ClientModel::getNumBlocksOfPeers() const
 {
     return GetNumBlocksOfPeers();
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -33,6 +33,8 @@
     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