diff options
Diffstat (limited to 'src/db.cpp')
-rw-r--r-- | src/db.cpp | 144 |
1 files changed, 133 insertions, 11 deletions
diff --git a/src/db.cpp b/src/db.cpp index 7de1f8df9a..f163ac949a 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -28,6 +28,34 @@ DbEnv dbenv(0); static map<string, int> mapFileUseCount; static map<string, Db*> mapDb; +static void EnvShutdown(bool fRemoveLogFiles) +{ + if (!fDbEnvInit) + return; + + fDbEnvInit = false; + dbenv.close(0); + DbEnv(0).remove(GetDataDir().c_str(), 0); + + if (fRemoveLogFiles) + { + filesystem::path datadir(GetDataDir()); + filesystem::directory_iterator it(datadir / "database"); + while (it != filesystem::directory_iterator()) + { + const filesystem::path& p = it->path(); +#if BOOST_FILESYSTEM_VERSION == 2 + std::string f = p.filename(); +#else + std::string f = p.filename().generic_string(); +#endif + if (f.find("log.") == 0) + filesystem::remove(p); + ++it; + } + } +} + class CDBInit { public: @@ -36,11 +64,7 @@ public: } ~CDBInit() { - if (fDbEnvInit) - { - dbenv.close(0); - fDbEnvInit = false; - } + EnvShutdown(false); } } instance_of_cdbinit; @@ -165,7 +189,100 @@ void static CloseDb(const string& strFile) } } -void DBFlush(bool fShutdown) +bool CDB::Rewrite(const string& strFile, const char* pszSkip) +{ + while (!fShutdown) + { + CRITICAL_BLOCK(cs_db) + { + if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0) + { + // Flush log data to the dat file + CloseDb(strFile); + dbenv.txn_checkpoint(0, 0, 0); + dbenv.lsn_reset(strFile.c_str(), 0); + mapFileUseCount.erase(strFile); + + bool fSuccess = true; + printf("Rewriting %s...\n", strFile.c_str()); + string strFileRes = strFile + ".rewrite"; + CDB db(strFile.c_str(), "r"); + Db* pdbCopy = new Db(&dbenv, 0); + + int ret = pdbCopy->open(NULL, // Txn pointer + strFileRes.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags + 0); + if (ret > 0) + { + printf("Cannot create database file %s\n", strFileRes.c_str()); + fSuccess = false; + } + + Dbc* pcursor = db.GetCursor(); + if (pcursor) + while (fSuccess) + { + CDataStream ssKey; + CDataStream ssValue; + int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); + if (ret == DB_NOTFOUND) + break; + else if (ret != 0) + { + pcursor->close(); + fSuccess = false; + break; + } + if (pszSkip && + strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0) + continue; + if (strncmp(&ssKey[0], "\x07version", 8) == 0) + { + // Update version: + ssValue.clear(); + ssValue << VERSION; + } + Dbt datKey(&ssKey[0], ssKey.size()); + Dbt datValue(&ssValue[0], ssValue.size()); + int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE); + if (ret2 > 0) + fSuccess = false; + } + if (fSuccess) + { + Db* pdb = mapDb[strFile]; + if (pdb->close(0)) + fSuccess = false; + if (pdbCopy->close(0)) + fSuccess = false; + delete pdb; + delete pdbCopy; + mapDb[strFile] = NULL; + } + if (fSuccess) + { + Db dbA(&dbenv, 0); + if (dbA.remove(strFile.c_str(), NULL, 0)) + fSuccess = false; + Db dbB(&dbenv, 0); + if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) + fSuccess = false; + } + if (!fSuccess) + printf("Rewriting of %s FAILED!\n", strFileRes.c_str()); + return fSuccess; + } + } + Sleep(100); + } + return false; +} + + +void DBFlush(bool fShutdown, bool fRemoveLogFiles) { // Flush log data to the actual data file // on all files that are not in use @@ -196,9 +313,10 @@ void DBFlush(bool fShutdown) { char** listp; if (mapFileUseCount.empty()) + { dbenv.log_archive(&listp, DB_ARCH_REMOVE); - dbenv.close(0); - fDbEnvInit = false; + EnvShutdown(fRemoveLogFiles); + } } } } @@ -656,6 +774,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet) pwallet->vchDefaultKey.clear(); int nFileVersion = 0; vector<uint256> vWalletUpgrade; + bool fIsEncrypted = false; // Modify defaults #ifndef WIN32 @@ -781,6 +900,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet) ssValue >> vchPrivKey; if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) return DB_CORRUPT; + fIsEncrypted = true; } else if (strType == "defaultkey") { @@ -841,8 +961,11 @@ int CWalletDB::LoadWallet(CWallet* pwallet) printf("fUseUPnP = %d\n", fUseUPnP); - // Upgrade - if (nFileVersion < VERSION) + // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: + if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000)) + return DB_NEED_REWRITE; + + if (nFileVersion < VERSION) // Update { // Get rid of old debug.log file in current directory if (nFileVersion <= 105 && !pszSetDataDir[0]) @@ -851,7 +974,6 @@ int CWalletDB::LoadWallet(CWallet* pwallet) WriteVersion(VERSION); } - return DB_LOAD_OK; } |