diff options
author | Jonas Schnelli <jonas.schnelli@include7.ch> | 2015-02-03 21:09:47 +0100 |
---|---|---|
committer | Jonas Schnelli <jonas.schnelli@include7.ch> | 2015-03-12 14:13:02 +0100 |
commit | 50c72f23ad5f7fcd13bf016f79cac6323c329caf (patch) | |
tree | 2ea49700ab27d3e9705f7a035f1a5783beed4ca2 /src/db.cpp | |
parent | e564e63ef04e55b1e446f8440d51c611bc41cec6 (diff) |
[Move Only] Move wallet related things to src/wallet/
could once be renamed from /src/wallet to /src/legacywallet.
Diffstat (limited to 'src/db.cpp')
-rw-r--r-- | src/db.cpp | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/src/db.cpp b/src/db.cpp deleted file mode 100644 index 36946b7dcc..0000000000 --- a/src/db.cpp +++ /dev/null @@ -1,462 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "db.h" - -#include "addrman.h" -#include "hash.h" -#include "protocol.h" -#include "util.h" -#include "utilstrencodings.h" - -#include <stdint.h> - -#ifndef WIN32 -#include <sys/stat.h> -#endif - -#include <boost/filesystem.hpp> -#include <boost/thread.hpp> -#include <boost/version.hpp> - -using namespace std; - - -unsigned int nWalletDBUpdated; - - -// -// CDB -// - -CDBEnv bitdb; - -void CDBEnv::EnvShutdown() -{ - if (!fDbEnvInit) - return; - - fDbEnvInit = false; - int ret = dbenv->close(0); - if (ret != 0) - LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); - if (!fMockDb) - DbEnv(0).remove(path.string().c_str(), 0); -} - -void CDBEnv::Reset() -{ - delete dbenv; - dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS); - fDbEnvInit = false; - fMockDb = false; -} - -CDBEnv::CDBEnv() : dbenv(NULL) -{ - Reset(); -} - -CDBEnv::~CDBEnv() -{ - EnvShutdown(); - delete dbenv; - dbenv = NULL; -} - -void CDBEnv::Close() -{ - EnvShutdown(); -} - -bool CDBEnv::Open(const boost::filesystem::path& pathIn) -{ - if (fDbEnvInit) - return true; - - boost::this_thread::interruption_point(); - - path = pathIn; - boost::filesystem::path pathLogDir = path / "database"; - TryCreateDirectory(pathLogDir); - boost::filesystem::path pathErrorFile = path / "db.log"; - LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); - - unsigned int nEnvFlags = 0; - if (GetBoolArg("-privdb", true)) - nEnvFlags |= DB_PRIVATE; - - dbenv->set_lg_dir(pathLogDir.string().c_str()); - dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet - dbenv->set_lg_bsize(0x10000); - dbenv->set_lg_max(1048576); - dbenv->set_lk_max_locks(40000); - dbenv->set_lk_max_objects(40000); - dbenv->set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug - dbenv->set_flags(DB_AUTO_COMMIT, 1); - dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); - dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); - int ret = dbenv->open(path.string().c_str(), - DB_CREATE | - DB_INIT_LOCK | - DB_INIT_LOG | - DB_INIT_MPOOL | - DB_INIT_TXN | - DB_THREAD | - DB_RECOVER | - nEnvFlags, - S_IRUSR | S_IWUSR); - if (ret != 0) - return error("CDBEnv::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret)); - - fDbEnvInit = true; - fMockDb = false; - return true; -} - -void CDBEnv::MakeMock() -{ - if (fDbEnvInit) - throw runtime_error("CDBEnv::MakeMock: Already initialized"); - - boost::this_thread::interruption_point(); - - LogPrint("db", "CDBEnv::MakeMock\n"); - - dbenv->set_cachesize(1, 0, 1); - dbenv->set_lg_bsize(10485760 * 4); - dbenv->set_lg_max(10485760); - dbenv->set_lk_max_locks(10000); - dbenv->set_lk_max_objects(10000); - dbenv->set_flags(DB_AUTO_COMMIT, 1); - dbenv->log_set_config(DB_LOG_IN_MEMORY, 1); - int ret = dbenv->open(NULL, - DB_CREATE | - DB_INIT_LOCK | - DB_INIT_LOG | - DB_INIT_MPOOL | - DB_INIT_TXN | - DB_THREAD | - DB_PRIVATE, - S_IRUSR | S_IWUSR); - if (ret > 0) - throw runtime_error(strprintf("CDBEnv::MakeMock: Error %d opening database environment.", ret)); - - fDbEnvInit = true; - 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 == DB_VERIFY_BAD) { - LogPrintf("CDBEnv::Salvage: Database salvage found errors, all data may not be recoverable.\n"); - if (!fAggressive) { - LogPrintf("CDBEnv::Salvage: Rerun with aggressive mode to ignore errors and continue.\n"); - return false; - } - } - if (result != 0 && result != DB_VERIFY_BAD) { - LogPrintf("CDBEnv::Salvage: Database salvage failed with result %d.\n", result); - 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(const std::string& strFile) -{ - dbenv->txn_checkpoint(0, 0, 0); - if (fMockDb) - return; - dbenv->lsn_reset(strFile.c_str(), 0); -} - - -CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) -{ - int ret; - fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); - fFlushOnClose = fFlushOnCloseIn; - if (strFilename.empty()) - return; - - bool fCreate = strchr(pszMode, 'c') != NULL; - unsigned int nFlags = DB_THREAD; - if (fCreate) - nFlags |= DB_CREATE; - - { - LOCK(bitdb.cs_db); - if (!bitdb.Open(GetDataDir())) - throw runtime_error("CDB: Failed to open database environment."); - - strFile = strFilename; - ++bitdb.mapFileUseCount[strFile]; - pdb = bitdb.mapDb[strFile]; - if (pdb == NULL) { - pdb = new Db(bitdb.dbenv, 0); - - bool fMockDb = bitdb.IsMock(); - if (fMockDb) { - DbMpoolFile* mpf = pdb->get_mpf(); - ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); - if (ret != 0) - throw runtime_error(strprintf("CDB: Failed to configure for no temp file backing for database %s", strFile)); - } - - ret = pdb->open(NULL, // Txn pointer - fMockDb ? NULL : strFile.c_str(), // Filename - fMockDb ? strFile.c_str() : "main", // Logical db name - DB_BTREE, // Database type - nFlags, // Flags - 0); - - if (ret != 0) { - delete pdb; - pdb = NULL; - --bitdb.mapFileUseCount[strFile]; - strFile = ""; - throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFile)); - } - - if (fCreate && !Exists(string("version"))) { - bool fTmp = fReadOnly; - fReadOnly = false; - WriteVersion(CLIENT_VERSION); - fReadOnly = fTmp; - } - - bitdb.mapDb[strFile] = pdb; - } - } -} - -void CDB::Flush() -{ - if (activeTxn) - return; - - // Flush database activity from memory pool to disk log - unsigned int nMinutes = 0; - if (fReadOnly) - nMinutes = 1; - - bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); -} - -void CDB::Close() -{ - if (!pdb) - return; - if (activeTxn) - activeTxn->abort(); - activeTxn = NULL; - pdb = NULL; - - if (fFlushOnClose) - Flush(); - - { - LOCK(bitdb.cs_db); - --bitdb.mapFileUseCount[strFile]; - } -} - -void CDBEnv::CloseDb(const string& strFile) -{ - { - LOCK(cs_db); - if (mapDb[strFile] != NULL) { - // Close the database handle - Db* pdb = mapDb[strFile]; - pdb->close(0); - delete pdb; - mapDb[strFile] = NULL; - } - } -} - -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 (true) { - { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) { - // Flush log data to the dat file - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(strFile); - - bool fSuccess = true; - LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile); - string strFileRes = strFile + ".rewrite"; - { // surround usage of db with extra {} - CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(bitdb.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) { - LogPrintf("CDB::Rewrite: Can't create database file %s\n", strFileRes); - fSuccess = false; - } - - Dbc* pcursor = db.GetCursor(); - if (pcursor) - while (fSuccess) { - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); - if (ret == DB_NOTFOUND) { - pcursor->close(); - 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 << CLIENT_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.Close(); - bitdb.CloseDb(strFile); - if (pdbCopy->close(0)) - fSuccess = false; - delete pdbCopy; - } - } - if (fSuccess) { - Db dbA(bitdb.dbenv, 0); - if (dbA.remove(strFile.c_str(), NULL, 0)) - fSuccess = false; - Db dbB(bitdb.dbenv, 0); - if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) - fSuccess = false; - } - if (!fSuccess) - LogPrintf("CDB::Rewrite: Failed to rewrite database file %s\n", strFileRes); - return fSuccess; - } - } - MilliSleep(100); - } - return false; -} - - -void CDBEnv::Flush(bool fShutdown) -{ - int64_t nStart = GetTimeMillis(); - // Flush log data to the actual data file on all files that are not in use - LogPrint("db", "CDBEnv::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started"); - if (!fDbEnvInit) - return; - { - LOCK(cs_db); - map<string, int>::iterator mi = mapFileUseCount.begin(); - while (mi != mapFileUseCount.end()) { - string strFile = (*mi).first; - int nRefCount = (*mi).second; - LogPrint("db", "CDBEnv::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount); - if (nRefCount == 0) { - // Move log data to the dat file - CloseDb(strFile); - LogPrint("db", "CDBEnv::Flush: %s checkpoint\n", strFile); - dbenv->txn_checkpoint(0, 0, 0); - LogPrint("db", "CDBEnv::Flush: %s detach\n", strFile); - if (!fMockDb) - dbenv->lsn_reset(strFile.c_str(), 0); - LogPrint("db", "CDBEnv::Flush: %s closed\n", strFile); - mapFileUseCount.erase(mi++); - } else - mi++; - } - LogPrint("db", "CDBEnv::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); - if (fShutdown) { - char** listp; - if (mapFileUseCount.empty()) { - dbenv->log_archive(&listp, DB_ARCH_REMOVE); - Close(); - if (!fMockDb) - boost::filesystem::remove_all(path / "database"); - } - } - } -} |