diff options
Diffstat (limited to 'src/db.cpp')
-rw-r--r-- | src/db.cpp | 91 |
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) |