Permalink
Browse files

Merge pull request #2315 from sipa/loaderror

Improve block database load error reporting
  • Loading branch information...
2 parents 06bbb7a + f7f3a96 commit dbac38170a537206d6aeb00f119b881560890e44 @gavinandresen gavinandresen committed Feb 18, 2013
Showing with 94 additions and 26 deletions.
  1. +4 −0 src/checkqueue.h
  2. +61 −18 src/init.cpp
  3. +12 −0 src/main.cpp
  4. +2 −0 src/main.h
  5. +2 −2 src/noui.cpp
  6. +6 −2 src/qt/bitcoin.cpp
  7. +4 −2 src/qt/bitcoingui.cpp
  8. +2 −1 src/qt/bitcoingui.h
  9. +1 −1 src/ui_interface.h
View
4 src/checkqueue.h
@@ -163,6 +163,10 @@ template<typename T> class CCheckQueue {
condQuit.wait(lock);
}
+ ~CCheckQueue() {
+ Quit();
+ }
+
friend class CCheckQueueControl<T>;
};
View
79 src/init.cpp
@@ -82,6 +82,7 @@ void Shutdown(void* parg)
if (fFirstThread)
{
fShutdown = true;
+ fRequestShutdown = true;
nTransactionsUpdated++;
bitdb.Flush(false);
{
@@ -791,27 +792,69 @@ bool AppInit2()
nTotalCache -= nCoinDBCache;
nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes
- uiInterface.InitMessage(_("Loading block index..."));
+ bool fLoaded = false;
+ while (!fLoaded) {
+ bool fReset = fReindex;
+ std::string strLoadError;
- nStart = GetTimeMillis();
- pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
- pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
- pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
-
- if (fReindex)
- pblocktree->WriteReindexing(true);
-
- if (!LoadBlockIndex())
- return InitError(_("Error loading block database"));
+ uiInterface.InitMessage(_("Loading block index..."));
- // Initialize the block index (no-op if non-empty database was already loaded)
- if (!InitBlockIndex())
- return InitError(_("Error initializing block database"));
-
- uiInterface.InitMessage(_("Verifying block database integrity..."));
+ nStart = GetTimeMillis();
+ do {
+ try {
+ UnloadBlockIndex();
+ delete pcoinsTip;
+ delete pcoinsdbview;
+ delete pblocktree;
+
+ pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
+ pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
+ pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
+
+ if (fReindex)
+ pblocktree->WriteReindexing(true);
+
+ if (!LoadBlockIndex()) {
+ strLoadError = _("Error loading block database");
+ break;
+ }
+
+ // Initialize the block index (no-op if non-empty database was already loaded)
+ if (!InitBlockIndex()) {
+ strLoadError = _("Error initializing block database");
+ break;
+ }
+
+ uiInterface.InitMessage(_("Verifying block database integrity..."));
+ if (!VerifyDB()) {
+ strLoadError = _("Corrupted block database detected");
+ break;
+ }
+ } catch(std::exception &e) {
+ strLoadError = _("Error opening block database");
+ break;
+ }
- if (!VerifyDB())
- return InitError(_("Corrupted block database detected. Please restart the client with -reindex."));
+ fLoaded = true;
+ } while(false);
+
+ if (!fLoaded) {
+ // first suggest a reindex
+ if (!fReset) {
+ bool fRet = uiInterface.ThreadSafeMessageBox(
+ strLoadError + ".\n" + _("Do you want to rebuild the block database now?"),
+ "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
+ if (fRet) {
+ fReindex = true;
+ fRequestShutdown = false;
+ } else {
+ return false;
+ }
+ } else {
+ return InitError(strLoadError);
+ }
+ }
+ }
if (mapArgs.count("-txindex") && fTxIndex != GetBoolArg("-txindex", false))
return InitError(_("You need to rebuild the databases using -reindex to change -txindex"));
View
12 src/main.cpp
@@ -2653,6 +2653,18 @@ bool VerifyDB() {
return true;
}
+void UnloadBlockIndex()
+{
+ mapBlockIndex.clear();
+ setBlockIndexValid.clear();
+ pindexGenesisBlock = NULL;
+ nBestHeight = 0;
+ bnBestChainWork = 0;
+ bnBestInvalidWork = 0;
+ hashBestChain = 0;
+ pindexBest = NULL;
+}
+
bool LoadBlockIndex()
{
if (fTestNet)
View
2 src/main.h
@@ -139,6 +139,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL);
bool InitBlockIndex();
/** Load the block tree and coins database from disk */
bool LoadBlockIndex();
+/** Unload database information */
+void UnloadBlockIndex();
/** Verify consistency of the block and coin databases */
bool VerifyDB();
/** Print the loaded block tree */
View
4 src/noui.cpp
@@ -9,7 +9,7 @@
#include <string>
-static int noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
+static bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
{
std::string strCaption;
// Check for usage of predefined caption
@@ -29,7 +29,7 @@ static int noui_ThreadSafeMessageBox(const std::string& message, const std::stri
printf("%s: %s\n", strCaption.c_str(), message.c_str());
fprintf(stderr, "%s: %s\n", strCaption.c_str(), message.c_str());
- return 4;
+ return false;
}
static bool noui_ThreadSafeAskFee(int64 /*nFeeRequired*/)
View
8 src/qt/bitcoin.cpp
@@ -34,23 +34,27 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
static BitcoinGUI *guiref;
static QSplashScreen *splashref;
-static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
+static bool ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
{
// Message from network thread
if(guiref)
{
bool modal = (style & CClientUIInterface::MODAL);
+ bool ret = false;
// In case of modal message, use blocking connection to wait for user to click a button
QMetaObject::invokeMethod(guiref, "message",
modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(caption)),
Q_ARG(QString, QString::fromStdString(message)),
- Q_ARG(unsigned int, style));
+ Q_ARG(unsigned int, style),
+ Q_ARG(bool*, &ret));
+ return ret;
}
else
{
printf("%s: %s\n", caption.c_str(), message.c_str());
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
+ return false;
}
}
View
6 src/qt/bitcoingui.cpp
@@ -606,7 +606,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
progressBar->setToolTip(tooltip);
}
-void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style)
+void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, bool *ret)
{
QString strTitle = tr("Bitcoin") + " - ";
// Default to information icon
@@ -646,7 +646,9 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
buttons = QMessageBox::Ok;
QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons);
- mBox.exec();
+ int r = mBox.exec();
+ if (ret != NULL)
+ *ret = r == QMessageBox::Ok;
}
else
notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
View
3 src/qt/bitcoingui.h
@@ -126,8 +126,9 @@ public slots:
@param[in] message the displayed text
@param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes)
@see CClientUIInterface::MessageBoxFlags
+ @param[in] ret pointer to a bool that will be modified to whether Ok was clicked (modal only)
*/
- void message(const QString &title, const QString &message, unsigned int style);
+ void message(const QString &title, const QString &message, unsigned int style, bool *ret = NULL);
/** Asks the user whether to pay the transaction fee or to cancel the transaction.
It is currently not possible to pass a return value to another thread through
BlockingQueuedConnection, so an indirected pointer is used.
View
2 src/ui_interface.h
@@ -68,7 +68,7 @@ class CClientUIInterface
};
/** Show message box. */
- boost::signals2::signal<void (const std::string& message, const std::string& caption, unsigned int style)> ThreadSafeMessageBox;
+ boost::signals2::signal<bool (const std::string& message, const std::string& caption, unsigned int style), boost::signals2::last_value<bool> > ThreadSafeMessageBox;
/** Ask the user whether they want to pay a fee or not. */
boost::signals2::signal<bool (int64 nFeeRequired), boost::signals2::last_value<bool> > ThreadSafeAskFee;

0 comments on commit dbac381

Please sign in to comment.