Improve block database load error reporting

This commit is contained in:
Pieter Wuille 2013-02-16 17:58:45 +01:00
parent 2f0fa79db2
commit 398774181a
8 changed files with 87 additions and 23 deletions

View file

@ -82,6 +82,7 @@ void Shutdown(void* parg)
if (fFirstThread) if (fFirstThread)
{ {
fShutdown = true; fShutdown = true;
fRequestShutdown = true;
nTransactionsUpdated++; nTransactionsUpdated++;
bitdb.Flush(false); bitdb.Flush(false);
{ {
@ -791,9 +792,21 @@ bool AppInit2()
nTotalCache -= nCoinDBCache; nTotalCache -= nCoinDBCache;
nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes nCoinCacheSize = nTotalCache / 300; // coins in memory require around 300 bytes
bool fLoaded = false;
while (!fLoaded) {
bool fReset = fReindex;
std::string strLoadError;
uiInterface.InitMessage(_("Loading block index...")); uiInterface.InitMessage(_("Loading block index..."));
nStart = GetTimeMillis(); nStart = GetTimeMillis();
do {
try {
UnloadBlockIndex();
delete pcoinsTip;
delete pcoinsdbview;
delete pblocktree;
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
pcoinsTip = new CCoinsViewCache(*pcoinsdbview); pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
@ -801,17 +814,47 @@ bool AppInit2()
if (fReindex) if (fReindex)
pblocktree->WriteReindexing(true); pblocktree->WriteReindexing(true);
if (!LoadBlockIndex()) if (!LoadBlockIndex()) {
return InitError(_("Error loading block database")); strLoadError = _("Error loading block database");
break;
}
// Initialize the block index (no-op if non-empty database was already loaded) // Initialize the block index (no-op if non-empty database was already loaded)
if (!InitBlockIndex()) if (!InitBlockIndex()) {
return InitError(_("Error initializing block database")); strLoadError = _("Error initializing block database");
break;
}
uiInterface.InitMessage(_("Verifying block database integrity...")); 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()) fLoaded = true;
return InitError(_("Corrupted block database detected. Please restart the client with -reindex.")); } 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)) if (mapArgs.count("-txindex") && fTxIndex != GetBoolArg("-txindex", false))
return InitError(_("You need to rebuild the databases using -reindex to change -txindex")); return InitError(_("You need to rebuild the databases using -reindex to change -txindex"));

View file

@ -2653,6 +2653,18 @@ bool VerifyDB() {
return true; return true;
} }
void UnloadBlockIndex()
{
mapBlockIndex.clear();
setBlockIndexValid.clear();
pindexGenesisBlock = NULL;
nBestHeight = 0;
bnBestChainWork = 0;
bnBestInvalidWork = 0;
hashBestChain = 0;
pindexBest = NULL;
}
bool LoadBlockIndex() bool LoadBlockIndex()
{ {
if (fTestNet) if (fTestNet)

View file

@ -139,6 +139,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL);
bool InitBlockIndex(); bool InitBlockIndex();
/** Load the block tree and coins database from disk */ /** Load the block tree and coins database from disk */
bool LoadBlockIndex(); bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
/** Verify consistency of the block and coin databases */ /** Verify consistency of the block and coin databases */
bool VerifyDB(); bool VerifyDB();
/** Print the loaded block tree */ /** Print the loaded block tree */

View file

@ -9,7 +9,7 @@
#include <string> #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; std::string strCaption;
// Check for usage of predefined caption // 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()); printf("%s: %s\n", strCaption.c_str(), message.c_str());
fprintf(stderr, "%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*/) static bool noui_ThreadSafeAskFee(int64 /*nFeeRequired*/)

View file

@ -34,23 +34,27 @@ Q_IMPORT_PLUGIN(qtaccessiblewidgets)
static BitcoinGUI *guiref; static BitcoinGUI *guiref;
static QSplashScreen *splashref; 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 // Message from network thread
if(guiref) if(guiref)
{ {
bool modal = (style & CClientUIInterface::MODAL); bool modal = (style & CClientUIInterface::MODAL);
bool ret = false;
// In case of modal message, use blocking connection to wait for user to click a button // In case of modal message, use blocking connection to wait for user to click a button
QMetaObject::invokeMethod(guiref, "message", QMetaObject::invokeMethod(guiref, "message",
modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(caption)), Q_ARG(QString, QString::fromStdString(caption)),
Q_ARG(QString, QString::fromStdString(message)), Q_ARG(QString, QString::fromStdString(message)),
Q_ARG(unsigned int, style)); Q_ARG(unsigned int, style),
Q_ARG(bool*, &ret));
return ret;
} }
else else
{ {
printf("%s: %s\n", caption.c_str(), message.c_str()); printf("%s: %s\n", caption.c_str(), message.c_str());
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
return false;
} }
} }

View file

@ -606,7 +606,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
progressBar->setToolTip(tooltip); 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") + " - "; QString strTitle = tr("Bitcoin") + " - ";
// Default to information icon // Default to information icon
@ -646,7 +646,9 @@ void BitcoinGUI::message(const QString &title, const QString &message, unsigned
buttons = QMessageBox::Ok; buttons = QMessageBox::Ok;
QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons); QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons);
mBox.exec(); int r = mBox.exec();
if (ret != NULL)
*ret = r == QMessageBox::Ok;
} }
else else
notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message); notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);

View file

@ -126,8 +126,9 @@ public slots:
@param[in] message the displayed text @param[in] message the displayed text
@param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes) @param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes)
@see CClientUIInterface::MessageBoxFlags @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. /** 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 It is currently not possible to pass a return value to another thread through
BlockingQueuedConnection, so an indirected pointer is used. BlockingQueuedConnection, so an indirected pointer is used.

View file

@ -68,7 +68,7 @@ public:
}; };
/** Show message box. */ /** 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. */ /** Ask the user whether they want to pay a fee or not. */
boost::signals2::signal<bool (int64 nFeeRequired), boost::signals2::last_value<bool> > ThreadSafeAskFee; boost::signals2::signal<bool (int64 nFeeRequired), boost::signals2::last_value<bool> > ThreadSafeAskFee;