Refactor: Move m_db pointers into BerkeleyDatabase

This is a refactoring change that doesn't affect behavior. The motivation
behind the change is give BerkeleyEnvironment objects access to
BerkeleyDatabase objects so it will be possible to simplify the duplicate
wallet check and more reliably avoid opening the same databases twice.

Github-Pull: #14552
Rebased-From: c456fbd
This commit is contained in:
Russell Yanofsky 2018-10-24 16:08:54 -04:00 committed by João Barbosa
parent caf1146b13
commit 7751ea37b6
2 changed files with 29 additions and 14 deletions

View file

@ -107,13 +107,13 @@ void BerkeleyEnvironment::Close()
fDbEnvInit = false; fDbEnvInit = false;
for (auto& db : mapDb) { for (auto& db : m_databases) {
auto count = mapFileUseCount.find(db.first); auto count = mapFileUseCount.find(db.first);
assert(count == mapFileUseCount.end() || count->second == 0); assert(count == mapFileUseCount.end() || count->second == 0);
if (db.second) { BerkeleyDatabase& database = db.second.get();
db.second->close(0); if (database.m_db) {
delete db.second; database.m_db->close(0);
db.second = nullptr; database.m_db.reset();
} }
} }
@ -480,7 +480,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
if (!env->Open(false /* retry */)) if (!env->Open(false /* retry */))
throw std::runtime_error("BerkeleyBatch: Failed to open database environment."); throw std::runtime_error("BerkeleyBatch: Failed to open database environment.");
pdb = env->mapDb[strFilename]; pdb = database.m_db.get();
if (pdb == nullptr) { if (pdb == nullptr) {
int ret; int ret;
std::unique_ptr<Db> pdb_temp = MakeUnique<Db>(env->dbenv.get(), 0); std::unique_ptr<Db> pdb_temp = MakeUnique<Db>(env->dbenv.get(), 0);
@ -525,7 +525,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
} }
pdb = pdb_temp.release(); pdb = pdb_temp.release();
env->mapDb[strFilename] = pdb; database.m_db.reset(pdb);
if (fCreate && !Exists(std::string("version"))) { if (fCreate && !Exists(std::string("version"))) {
bool fTmp = fReadOnly; bool fTmp = fReadOnly;
@ -580,12 +580,13 @@ void BerkeleyEnvironment::CloseDb(const std::string& strFile)
{ {
{ {
LOCK(cs_db); LOCK(cs_db);
if (mapDb[strFile] != nullptr) { auto it = m_databases.find(strFile);
assert(it != m_databases.end());
BerkeleyDatabase& database = it->second.get();
if (database.m_db) {
// Close the database handle // Close the database handle
Db* pdb = mapDb[strFile]; database.m_db->close(0);
pdb->close(0); database.m_db.reset();
delete pdb;
mapDb[strFile] = nullptr;
} }
} }
} }
@ -603,7 +604,7 @@ void BerkeleyEnvironment::ReloadDbEnv()
}); });
std::vector<std::string> filenames; std::vector<std::string> filenames;
for (auto it : mapDb) { for (auto it : m_databases) {
filenames.push_back(it.first); filenames.push_back(it.first);
} }
// Close the individual Db's // Close the individual Db's

View file

@ -31,6 +31,8 @@ struct WalletDatabaseFileId {
bool operator==(const WalletDatabaseFileId& rhs) const; bool operator==(const WalletDatabaseFileId& rhs) const;
}; };
class BerkeleyDatabase;
class BerkeleyEnvironment class BerkeleyEnvironment
{ {
private: private:
@ -43,7 +45,7 @@ private:
public: public:
std::unique_ptr<DbEnv> dbenv; std::unique_ptr<DbEnv> dbenv;
std::map<std::string, int> mapFileUseCount; std::map<std::string, int> mapFileUseCount;
std::map<std::string, Db*> mapDb; std::map<std::string, std::reference_wrapper<BerkeleyDatabase>> m_databases;
std::unordered_map<std::string, WalletDatabaseFileId> m_fileids; std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
std::condition_variable_any m_db_in_use; std::condition_variable_any m_db_in_use;
@ -118,6 +120,8 @@ public:
nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0)
{ {
env = GetWalletEnv(wallet_path, strFile); env = GetWalletEnv(wallet_path, strFile);
auto inserted = env->m_databases.emplace(strFile, std::ref(*this));
assert(inserted.second);
if (mock) { if (mock) {
env->Close(); env->Close();
env->Reset(); env->Reset();
@ -125,6 +129,13 @@ public:
} }
} }
~BerkeleyDatabase() {
if (env) {
size_t erased = env->m_databases.erase(strFile);
assert(erased == 1);
}
}
/** Return object for accessing database at specified path. */ /** Return object for accessing database at specified path. */
static std::unique_ptr<BerkeleyDatabase> Create(const fs::path& path) static std::unique_ptr<BerkeleyDatabase> Create(const fs::path& path)
{ {
@ -164,6 +175,9 @@ public:
unsigned int nLastFlushed; unsigned int nLastFlushed;
int64_t nLastWalletUpdate; int64_t nLastWalletUpdate;
/** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
std::unique_ptr<Db> m_db;
private: private:
/** BerkeleyDB specific */ /** BerkeleyDB specific */
BerkeleyEnvironment *env; BerkeleyEnvironment *env;