aboutsummaryrefslogtreecommitdiff
path: root/src/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/db.cpp')
-rw-r--r--src/db.cpp91
1 files changed, 79 insertions, 12 deletions
diff --git a/src/db.cpp b/src/db.cpp
index 867703fbd2..9ad67892f1 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -34,19 +34,14 @@ void CDBEnv::EnvShutdown()
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 @@ bool CDBEnv::Open(boost::filesystem::path pathEnv_)
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;
@@ -141,6 +136,69 @@ void CDBEnv::MakeMock()
fMockDb = true;
}
+CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile))
+{
+ LOCK(cs_db);
+ assert(mapFileUseCount.count(strFile) == 0);
+
+ Db db(&dbenv, 0);
+ int result = db.verify(strFile.c_str(), NULL, NULL, 0);
+ if (result == 0)
+ return VERIFY_OK;
+ else if (recoverFunc == NULL)
+ return RECOVER_FAIL;
+
+ // Try to recover:
+ bool fRecovered = (*recoverFunc)(*this, strFile);
+ return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
+}
+
+bool CDBEnv::Salvage(std::string strFile, bool fAggressive,
+ std::vector<CDBEnv::KeyValPair >& vResult)
+{
+ LOCK(cs_db);
+ assert(mapFileUseCount.count(strFile) == 0);
+
+ u_int32_t flags = DB_SALVAGE;
+ if (fAggressive) flags |= DB_AGGRESSIVE;
+
+ stringstream strDump;
+
+ Db db(&dbenv, 0);
+ int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
+ if (result != 0)
+ {
+ printf("ERROR: db salvage failed\n");
+ return false;
+ }
+
+ // Format of bdb dump is ascii lines:
+ // header lines...
+ // HEADER=END
+ // hexadecimal key
+ // hexadecimal value
+ // ... repeated
+ // DATA=END
+
+ string strLine;
+ while (!strDump.eof() && strLine != "HEADER=END")
+ getline(strDump, strLine); // Skip past header
+
+ std::string keyHex, valueHex;
+ while (!strDump.eof() && keyHex != "DATA=END")
+ {
+ getline(strDump, keyHex);
+ if (keyHex != "DATA_END")
+ {
+ getline(strDump, valueHex);
+ vResult.push_back(make_pair(ParseHex(keyHex),ParseHex(valueHex)));
+ }
+ }
+
+ return (result == 0);
+}
+
+
void CDBEnv::CheckpointLSN(std::string strFile)
{
dbenv.txn_checkpoint(0, 0, 0);
@@ -191,7 +249,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) :
nFlags, // Flags
0);
- if (ret > 0)
+ if (ret != 0)
{
delete pdb;
pdb = NULL;
@@ -262,6 +320,15 @@ void CDBEnv::CloseDb(const string& strFile)
}
}
+bool CDBEnv::RemoveDb(const string& strFile)
+{
+ this->CloseDb(strFile);
+
+ LOCK(cs_db);
+ int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
+ return (rc == 0);
+}
+
bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{
while (!fShutdown)