Handle incompatible BDB environments

Before, opening a -datadir that was created with a new
version of Berkeley DB would result in an un-caught DB_RUNRECOVERY
exception.

After these changes, the error is caught and the user is told
that there is a problem and is told how to try to recover from
it.
This commit is contained in:
Gavin Andresen 2012-10-08 15:18:04 -04:00
parent 43de64949c
commit 8d5f461cb6
2 changed files with 19 additions and 15 deletions

View File

@ -34,19 +34,14 @@ void CDBEnv::EnvShutdown()
return; return;
fDbEnvInit = false; fDbEnvInit = false;
try int ret = dbenv.close(0);
{ if (ret != 0)
dbenv.close(0); printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
}
catch (const DbException& e)
{
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
}
if (!fMockDb) if (!fMockDb)
DbEnv(0).remove(GetDataDir().string().c_str(), 0); DbEnv(0).remove(GetDataDir().string().c_str(), 0);
} }
CDBEnv::CDBEnv() : dbenv(0) CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
{ {
} }
@ -100,8 +95,8 @@ bool CDBEnv::Open(boost::filesystem::path pathEnv_)
DB_RECOVER | DB_RECOVER |
nEnvFlags, nEnvFlags,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
if (ret > 0) if (ret != 0)
return error("CDB() : error %d opening database environment", ret); return error("CDB() : error %s (%d) opening database environment", DbEnv::strerror(ret), ret);
fDbEnvInit = true; fDbEnvInit = true;
fMockDb = false; fMockDb = false;
@ -191,7 +186,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) :
nFlags, // Flags nFlags, // Flags
0); 0);
if (ret > 0) if (ret != 0)
{ {
delete pdb; delete pdb;
pdb = NULL; pdb = NULL;

View File

@ -439,8 +439,9 @@ bool AppInit2()
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file); if (file) fclose(file);
static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
const char* pszDataDir = GetDataDir().string().c_str();
if (!lock.try_lock()) if (!lock.try_lock())
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str())); return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), pszDataDir));
#if !defined(WIN32) && !defined(QT_GUI) #if !defined(WIN32) && !defined(QT_GUI)
if (fDaemon) if (fDaemon)
@ -472,7 +473,7 @@ bool AppInit2()
if (!fLogTimestamps) if (!fLogTimestamps)
printf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); printf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
printf("Used data directory %s\n", GetDataDir().string().c_str()); printf("Used data directory %s\n", pszDataDir);
std::ostringstream strErrors; std::ostringstream strErrors;
if (fDaemon) if (fDaemon)
@ -588,6 +589,14 @@ bool AppInit2()
// ********************************************************* Step 6: load blockchain // ********************************************************* Step 6: load blockchain
if (!bitdb.Open(GetDataDir()))
{
string msg = strprintf(_("Error initializing database environment %s!"
" To recover, BACKUP THAT DIRECTORY, then remove"
" everything from it except for wallet.dat."), pszDataDir);
return InitError(msg);
}
if (GetBoolArg("-loadblockindextest")) if (GetBoolArg("-loadblockindextest"))
{ {
CTxDB txdb("r"); CTxDB txdb("r");
@ -600,7 +609,7 @@ bool AppInit2()
printf("Loading block index...\n"); printf("Loading block index...\n");
nStart = GetTimeMillis(); nStart = GetTimeMillis();
if (!LoadBlockIndex()) if (!LoadBlockIndex())
strErrors << _("Error loading blkindex.dat") << "\n"; return InitError(_("Error loading blkindex.dat"));
// as LoadBlockIndex can take several minutes, it's possible the user // as LoadBlockIndex can take several minutes, it's possible the user
// requested to kill bitcoin-qt during the last operation. If so, exit. // requested to kill bitcoin-qt during the last operation. If so, exit.