Improve block database load error reporting
This commit is contained in:
parent
2f0fa79db2
commit
398774181a
8 changed files with 87 additions and 23 deletions
55
src/init.cpp
55
src/init.cpp
|
@ -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"));
|
||||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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*/)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue