@@ -48,7 +48,7 @@ void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filena
4848}
4949
5050CCriticalSection cs_db;
51- std::map<std::string, BerkeleyEnvironment> g_dbenvs GUARDED_BY (cs_db); // !< Map from directory name to open db environment.
51+ std::map<std::string, std::weak_ptr< BerkeleyEnvironment>> g_dbenvs GUARDED_BY (cs_db); // !< Map from directory name to db environment.
5252} // namespace
5353
5454bool WalletDatabaseFileId::operator ==(const WalletDatabaseFileId& rhs) const
@@ -80,19 +80,22 @@ bool IsWalletLoaded(const fs::path& wallet_path)
8080 LOCK (cs_db);
8181 auto env = g_dbenvs.find (env_directory.string ());
8282 if (env == g_dbenvs.end ()) return false ;
83- return env->second .IsDatabaseLoaded (database_filename);
83+ auto database = env->second .lock ();
84+ return database && database->IsDatabaseLoaded (database_filename);
8485}
8586
86- BerkeleyEnvironment* GetWalletEnv (const fs::path& wallet_path, std::string& database_filename)
87+ std::shared_ptr< BerkeleyEnvironment> GetWalletEnv (const fs::path& wallet_path, std::string& database_filename)
8788{
8889 fs::path env_directory;
8990 SplitWalletPath (wallet_path, env_directory, database_filename);
9091 LOCK (cs_db);
91- // Note: An ununsed temporary BerkeleyEnvironment object may be created inside the
92- // emplace function if the key already exists. This is a little inefficient,
93- // but not a big concern since the map will be changed in the future to hold
94- // pointers instead of objects, anyway.
95- return &g_dbenvs.emplace (std::piecewise_construct, std::forward_as_tuple (env_directory.string ()), std::forward_as_tuple (env_directory)).first ->second ;
92+ auto inserted = g_dbenvs.emplace (env_directory.string (), std::weak_ptr<BerkeleyEnvironment>());
93+ if (inserted.second ) {
94+ auto env = std::make_shared<BerkeleyEnvironment>(env_directory.string ());
95+ inserted.first ->second = env;
96+ return env;
97+ }
98+ return inserted.first ->second .lock ();
9699}
97100
98101//
@@ -137,6 +140,7 @@ BerkeleyEnvironment::BerkeleyEnvironment(const fs::path& dir_path) : strPath(dir
137140
138141BerkeleyEnvironment::~BerkeleyEnvironment ()
139142{
143+ g_dbenvs.erase (strPath);
140144 Close ();
141145}
142146
@@ -214,10 +218,9 @@ bool BerkeleyEnvironment::Open(bool retry)
214218 return true ;
215219}
216220
217- void BerkeleyEnvironment::MakeMock ()
221+ BerkeleyEnvironment::BerkeleyEnvironment ()
218222{
219- if (fDbEnvInit )
220- throw std::runtime_error (" BerkeleyEnvironment::MakeMock: Already initialized" );
223+ Reset ();
221224
222225 boost::this_thread::interruption_point ();
223226
@@ -266,7 +269,7 @@ BerkeleyEnvironment::VerifyResult BerkeleyEnvironment::Verify(const std::string&
266269bool BerkeleyBatch::Recover (const fs::path& file_path, void *callbackDataIn, bool (*recoverKVcallback)(void * callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename)
267270{
268271 std::string filename;
269- BerkeleyEnvironment* env = GetWalletEnv (file_path, filename);
272+ std::shared_ptr< BerkeleyEnvironment> env = GetWalletEnv (file_path, filename);
270273
271274 // Recovery procedure:
272275 // move wallet file to walletfilename.timestamp.bak
@@ -335,7 +338,7 @@ bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, boo
335338bool BerkeleyBatch::VerifyEnvironment (const fs::path& file_path, std::string& errorStr)
336339{
337340 std::string walletFile;
338- BerkeleyEnvironment* env = GetWalletEnv (file_path, walletFile);
341+ std::shared_ptr< BerkeleyEnvironment> env = GetWalletEnv (file_path, walletFile);
339342 fs::path walletDir = env->Directory ();
340343
341344 LogPrintf (" Using BerkeleyDB version %s\n " , DbEnv::version (0 , 0 , 0 ));
@@ -359,7 +362,7 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er
359362bool BerkeleyBatch::VerifyDatabaseFile (const fs::path& file_path, std::string& warningStr, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
360363{
361364 std::string walletFile;
362- BerkeleyEnvironment* env = GetWalletEnv (file_path, walletFile);
365+ std::shared_ptr< BerkeleyEnvironment> env = GetWalletEnv (file_path, walletFile);
363366 fs::path walletDir = env->Directory ();
364367
365368 if (fs::exists (walletDir / walletFile))
@@ -463,7 +466,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
463466{
464467 fReadOnly = (!strchr (pszMode, ' +' ) && !strchr (pszMode, ' w' ));
465468 fFlushOnClose = fFlushOnCloseIn ;
466- env = database.env ;
469+ env = database.env . get () ;
467470 if (database.IsDummy ()) {
468471 return ;
469472 }
@@ -520,7 +523,7 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo
520523 // versions of BDB have an set_lk_exclusive method for this
521524 // purpose, but the older version we use does not.)
522525 for (auto & env : g_dbenvs) {
523- CheckUniqueFileid (env.second , strFilename, *pdb_temp, this ->env ->m_fileids [strFilename]);
526+ CheckUniqueFileid (* env.second . lock (). get () , strFilename, *pdb_temp, this ->env ->m_fileids [strFilename]);
524527 }
525528
526529 pdb = pdb_temp.release ();
@@ -621,7 +624,7 @@ bool BerkeleyBatch::Rewrite(BerkeleyDatabase& database, const char* pszSkip)
621624 if (database.IsDummy ()) {
622625 return true ;
623626 }
624- BerkeleyEnvironment *env = database.env ;
627+ BerkeleyEnvironment *env = database.env . get () ;
625628 const std::string& strFile = database.strFile ;
626629 while (true ) {
627630 {
@@ -752,7 +755,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
752755 return true ;
753756 }
754757 bool ret = false ;
755- BerkeleyEnvironment *env = database.env ;
758+ BerkeleyEnvironment *env = database.env . get () ;
756759 const std::string& strFile = database.strFile ;
757760 TRY_LOCK (cs_db, lockDb);
758761 if (lockDb)
0 commit comments