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)
{
fShutdown = true;
fRequestShutdown = true;
nTransactionsUpdated++;
bitdb.Flush(false);
{
@ -791,9 +792,21 @@ bool AppInit2()
nTotalCache -= nCoinDBCache;
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..."));
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);
@ -801,17 +814,47 @@ bool AppInit2()
if (fReindex)
pblocktree->WriteReindexing(true);
if (!LoadBlockIndex())
return InitError(_("Error loading block database"));
if (!LoadBlockIndex()) {
strLoadError = _("Error loading block database");
break;
}
// Initialize the block index (no-op if non-empty database was already loaded)
if (!InitBlockIndex())
return InitError(_("Error initializing block database"));
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 file

@ -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 file

@ -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 file

@ -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 file

@ -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 file

@ -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 file

@ -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 file

@ -68,7 +68,7 @@ public:
};
/** 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;