changeset 3603:a3ef3e3e0ee2 draft

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.
author Gavin Andresen <gavinandresen@gmail.com>
date Mon, 08 Oct 2012 15:18:04 -0400
parents 837b10c010b6
children fbf468eac50a
files src/db.cpp src/init.cpp
diffstat 2 files changed, 19 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -34,19 +34,14 @@
         return;
 
     fDbEnvInit = false;
-    try
-    {
-        dbenv.close(0);
-    }
-    catch (const DbException& e)
-    {
-        printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
-    }
+    int ret = dbenv.close(0);
+    if (ret != 0)
+        printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
     if (!fMockDb)
         DbEnv(0).remove(GetDataDir().string().c_str(), 0);
 }
 
-CDBEnv::CDBEnv() : dbenv(0)
+CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
 {
 }
 
@@ -100,8 +95,8 @@
                      DB_RECOVER    |
                      nEnvFlags,
                      S_IRUSR | S_IWUSR);
-    if (ret > 0)
-        return error("CDB() : error %d opening database environment", ret);
+    if (ret != 0)
+        return error("CDB() : error %s (%d) opening database environment", DbEnv::strerror(ret), ret);
 
     fDbEnvInit = true;
     fMockDb = false;
@@ -191,7 +186,7 @@
                             nFlags,    // Flags
                             0);
 
-            if (ret > 0)
+            if (ret != 0)
             {
                 delete pdb;
                 pdb = NULL;
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -439,8 +439,9 @@
     FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
     if (file) fclose(file);
     static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
+    const char* pszDataDir = GetDataDir().string().c_str();
     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 (fDaemon)
@@ -472,7 +473,7 @@
     if (!fLogTimestamps)
         printf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).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;
 
     if (fDaemon)
@@ -588,6 +589,14 @@
 
     // ********************************************************* 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"))
     {
         CTxDB txdb("r");
@@ -600,7 +609,7 @@
     printf("Loading block index...\n");
     nStart = GetTimeMillis();
     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
     // requested to kill bitcoin-qt during the last operation. If so, exit.