From cd9696fc97fc06831c1edede62a063028f2afe75 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 13 May 2012 21:37:39 -0400 Subject: Encapsulate BDB environment inside new CDBEnv class Cleans up and organizes several scattered functions and variables related to the BDB env. Class CDBInit() existed to provide a guaranteed-via-C++-destructor cleanup of the db environment. A formal CDBEnv class provides all of this inside a single wrapper. --- src/db.cpp | 141 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 64 deletions(-) (limited to 'src/db.cpp') diff --git a/src/db.cpp b/src/db.cpp index 50f0891626..988c10caa2 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -26,14 +26,11 @@ unsigned int nWalletDBUpdated; // CDB // -CCriticalSection cs_db; -static bool fDbEnvInit = false; -bool fDetachDB = false; -DbEnv dbenv(0); +CDBEnv bitdb; map mapFileUseCount; static map mapDb; -static void EnvShutdown() +void CDBEnv::EnvShutdown() { if (!fDbEnvInit) return; @@ -50,18 +47,67 @@ static void EnvShutdown() DbEnv(0).remove(GetDataDir().string().c_str(), 0); } -class CDBInit +CDBEnv::CDBEnv() : dbenv(0) { -public: - CDBInit() - { - } - ~CDBInit() - { - EnvShutdown(); - } } -instance_of_cdbinit; + +CDBEnv::~CDBEnv() +{ + EnvShutdown(); +} + +void CDBEnv::Close() +{ + EnvShutdown(); +} + +bool CDBEnv::Open(boost::filesystem::path pathEnv_) +{ + if (fDbEnvInit) + return true; + + if (fShutdown) + return false; + + pathEnv = pathEnv_; + filesystem::path pathDataDir = pathEnv; + filesystem::path pathLogDir = pathDataDir / "database"; + filesystem::create_directory(pathLogDir); + filesystem::path pathErrorFile = pathDataDir / "db.log"; + printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str()); + + int nDbCache = GetArg("-dbcache", 25); + dbenv.set_lg_dir(pathLogDir.string().c_str()); + dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1); + dbenv.set_lg_bsize(1048576); + dbenv.set_lg_max(10485760); + dbenv.set_lk_max_locks(10000); + dbenv.set_lk_max_objects(10000); + 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(pathDataDir.string().c_str(), + DB_CREATE | + DB_INIT_LOCK | + DB_INIT_LOG | + DB_INIT_MPOOL | + DB_INIT_TXN | + DB_THREAD | + DB_RECOVER, + S_IRUSR | S_IWUSR); + if (ret > 0) + return error("CDB() : error %d opening database environment", ret); + + fDbEnvInit = true; + return true; +} + +void CDBEnv::CheckpointLSN(std::string strFile) +{ + dbenv.txn_checkpoint(0, 0, 0); + dbenv.lsn_reset(strFile.c_str(), 0); +} CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL) @@ -77,48 +123,16 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL) nFlags |= DB_CREATE; { - LOCK(cs_db); - if (!fDbEnvInit) - { - if (fShutdown) - return; - filesystem::path pathDataDir = GetDataDir(); - filesystem::path pathLogDir = pathDataDir / "database"; - filesystem::create_directory(pathLogDir); - filesystem::path pathErrorFile = pathDataDir / "db.log"; - printf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str()); - - int nDbCache = GetArg("-dbcache", 25); - dbenv.set_lg_dir(pathLogDir.string().c_str()); - dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1); - dbenv.set_lg_bsize(1048576); - dbenv.set_lg_max(10485760); - dbenv.set_lk_max_locks(10000); - dbenv.set_lk_max_objects(10000); - dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug - dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); - dbenv.set_flags(DB_AUTO_COMMIT, 1); - dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); - ret = dbenv.open(pathDataDir.string().c_str(), - DB_CREATE | - DB_INIT_LOCK | - DB_INIT_LOG | - DB_INIT_MPOOL | - DB_INIT_TXN | - DB_THREAD | - DB_RECOVER, - S_IRUSR | S_IWUSR); - if (ret > 0) - throw runtime_error(strprintf("CDB() : error %d opening database environment", ret)); - fDbEnvInit = true; - } + LOCK(bitdb.cs_db); + if (!bitdb.Open(GetDataDir())) + throw runtime_error("env open failed"); strFile = pszFile; ++mapFileUseCount[strFile]; pdb = mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(&dbenv, 0); + pdb = new Db(&bitdb.dbenv, 0); ret = pdb->open(NULL, // Txn pointer pszFile, // Filename @@ -132,7 +146,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) : pdb(NULL) delete pdb; pdb = NULL; { - LOCK(cs_db); + LOCK(bitdb.cs_db); --mapFileUseCount[strFile]; } strFile = ""; @@ -170,10 +184,10 @@ void CDB::Close() if (strFile == "blkindex.dat" && IsInitialBlockDownload()) nMinutes = 5; - dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); + bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); { - LOCK(cs_db); + LOCK(bitdb.cs_db); --mapFileUseCount[strFile]; } } @@ -181,7 +195,7 @@ void CDB::Close() void CloseDb(const string& strFile) { { - LOCK(cs_db); + LOCK(bitdb.cs_db); if (mapDb[strFile] != NULL) { // Close the database handle @@ -198,13 +212,12 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) while (!fShutdown) { { - LOCK(cs_db); + LOCK(bitdb.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); + bitdb.CheckpointLSN(strFile); mapFileUseCount.erase(strFile); bool fSuccess = true; @@ -212,7 +225,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(&dbenv, 0); + Db* pdbCopy = new Db(&bitdb.dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -270,10 +283,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } if (fSuccess) { - Db dbA(&dbenv, 0); + Db dbA(&bitdb.dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(&dbenv, 0); + Db dbB(&bitdb.dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } @@ -288,12 +301,12 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } -void DBFlush(bool fShutdown) +void CDBEnv::Flush(bool fShutdown) { int64 nStart = GetTimeMillis(); // Flush log data to the actual data file // on all files that are not in use - printf("DBFlush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started"); + printf("Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " db not started"); if (!fDbEnvInit) return; { @@ -327,7 +340,7 @@ void DBFlush(bool fShutdown) if (mapFileUseCount.empty()) { dbenv.log_archive(&listp, DB_ARCH_REMOVE); - EnvShutdown(); + Close(); } } } -- cgit v1.2.3