upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/db.cpp
diff options
context:
space:
mode:
authorBitflash <admin@bitflash.network>2026-08-14 13:14:24 -0300
committerBitflash <admin@bitflash.network>2026-08-14 13:14:24 -0300
commit9b281d890168c7c912857530d787fbc82203d848 (patch)
tree760244d73f0a4e41449cb7c9da249d2bd4d45dfa /src/db.cpp
parent5b635e570ec38a8b621f19f93a4125f875e3f152 (diff)
parent82c3e10da01260650ddd2944e3f895ccf2c07ffc (diff)
Merge pull request 'db: recreate Berkeley DB environment after shutdown' (#46) from db-recreate-env-after-shutdown into main
Diffstat (limited to 'src/db.cpp')
-rw-r--r--src/db.cpp93
1 files changed, 61 insertions, 32 deletions
diff --git a/src/db.cpp b/src/db.cpp
index 0ff58e7..8b82fe5 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -52,9 +52,34 @@ static bool fDbEnvInit = false;
52// Why LoadWallet() refused, in words meant for the person who has to act on it. 52// Why LoadWallet() refused, in words meant for the person who has to act on it.
53// Empty unless the reason is one we can name. 53// Empty unless the reason is one we can name.
54string strWalletLoadError; 54string strWalletLoadError;
55DbEnv dbenv(0u); 55static DbEnv* pdbenv = NULL;
56static FILE* pdbErrFile = NULL;
56static map<string, int> mapFileUseCount; 57static map<string, int> mapFileUseCount;
57 58
59DbEnv& GetDbEnv()
60{
61 if (!pdbenv)
62 pdbenv = new DbEnv(0u);
63 return *pdbenv;
64}
65
66static void CloseDbEnv()
67{
68 if (pdbenv)
69 {
70 try { pdbenv->close(0); }
71 catch (...) { }
72 delete pdbenv;
73 pdbenv = NULL;
74 }
75 if (pdbErrFile)
76 {
77 fclose(pdbErrFile);
78 pdbErrFile = NULL;
79 }
80 fDbEnvInit = false;
81}
82
58class CDBInit 83class CDBInit
59{ 84{
60public: 85public:
@@ -64,11 +89,7 @@ public:
64 ~CDBInit() 89 ~CDBInit()
65 { 90 {
66 if (fDbEnvInit) 91 if (fDbEnvInit)
67 { 92 CloseDbEnv();
68 try { dbenv.close(0); }
69 catch (...) { }
70 fDbEnvInit = false;
71 }
72 } 93 }
73} 94}
74instance_of_cdbinit; 95instance_of_cdbinit;
@@ -104,24 +125,30 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
104 125
105 printf("dbenv.open strAppDir=%s\n", strAppDir.c_str()); 126 printf("dbenv.open strAppDir=%s\n", strAppDir.c_str());
106 127
107 dbenv.set_lg_dir(strLogDir.c_str()); 128 DbEnv& env = GetDbEnv();
108 dbenv.set_lg_max(10000000); 129 env.set_lg_dir(strLogDir.c_str());
109 dbenv.set_lk_max_locks(10000); 130 env.set_lg_max(10000000);
110 dbenv.set_lk_max_objects(10000); 131 env.set_lk_max_locks(10000);
111 dbenv.set_errfile(fopen("db.log", "a")); /// debug 132 env.set_lk_max_objects(10000);
112 ///dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1); /// causes corruption 133 pdbErrFile = fopen("db.log", "a"); /// debug
113 ret = dbenv.open(strAppDir.c_str(), 134 if (pdbErrFile)
114 DB_CREATE | 135 env.set_errfile(pdbErrFile);
115 DB_INIT_LOCK | 136 ///env.log_set_config(DB_LOG_AUTO_REMOVE, 1); /// causes corruption
116 DB_INIT_LOG | 137 ret = env.open(strAppDir.c_str(),
117 DB_INIT_MPOOL | 138 DB_CREATE |
118 DB_INIT_TXN | 139 DB_INIT_LOCK |
119 DB_THREAD | 140 DB_INIT_LOG |
120 DB_PRIVATE | 141 DB_INIT_MPOOL |
121 DB_RECOVER, 142 DB_INIT_TXN |
122 0); 143 DB_THREAD |
144 DB_PRIVATE |
145 DB_RECOVER,
146 0);
123 if (ret > 0) 147 if (ret > 0)
148 {
149 CloseDbEnv();
124 throw runtime_error(strprintf("CDB() : error %d opening database environment\n", ret)); 150 throw runtime_error(strprintf("CDB() : error %d opening database environment\n", ret));
151 }
125 fDbEnvInit = true; 152 fDbEnvInit = true;
126 153
127 // A Berkeley DB file records, in every page header, a log sequence 154 // A Berkeley DB file records, in every page header, a log sequence
@@ -151,7 +178,7 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
151 continue; 178 continue;
152 try 179 try
153 { 180 {
154 if (dbenv.lsn_reset(pszName, 0) == 0) 181 if (env.lsn_reset(pszName, 0) == 0)
155 printf("CDB() : adopted %s from another environment " 182 printf("CDB() : adopted %s from another environment "
156 "(log sequence numbers reset)\n", pszName); 183 "(log sequence numbers reset)\n", pszName);
157 } 184 }
@@ -164,7 +191,7 @@ CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
164 ++mapFileUseCount[strFile]; 191 ++mapFileUseCount[strFile];
165 } 192 }
166 193
167 pdb = new Db(&dbenv, 0); 194 pdb = new Db(&GetDbEnv(), 0);
168 195
169 ret = pdb->open(NULL, // Txn pointer 196 ret = pdb->open(NULL, // Txn pointer
170 pszFile, // Filename 197 pszFile, // Filename
@@ -199,7 +226,8 @@ void CDB::Close()
199 try { pdb->close(0); } catch (...) { } 226 try { pdb->close(0); } catch (...) { }
200 delete pdb; 227 delete pdb;
201 pdb = NULL; 228 pdb = NULL;
202 try { dbenv.txn_checkpoint(0, 0, 0); } catch (...) { } 229 if (fDbEnvInit)
230 try { GetDbEnv().txn_checkpoint(0, 0, 0); } catch (...) { }
203 231
204 CRITICAL_BLOCK(cs_db) 232 CRITICAL_BLOCK(cs_db)
205 --mapFileUseCount[strFile]; 233 --mapFileUseCount[strFile];
@@ -279,7 +307,8 @@ void DBFlush(bool fShutdown)
279 // takes the process down before the wallet has been put down cleanly, 307 // takes the process down before the wallet has been put down cleanly,
280 // which is the difference between a portable wallet.dat and one welded 308 // which is the difference between a portable wallet.dat and one welded
281 // to this directory -- the lsn_reset just below is what frees it. 309 // to this directory -- the lsn_reset just below is what frees it.
282 try { dbenv.txn_checkpoint(0, 0, 0); } 310 DbEnv& env = GetDbEnv();
311 try { env.txn_checkpoint(0, 0, 0); }
283 catch (const std::exception& e) 312 catch (const std::exception& e)
284 { printf("DBFlush() : checkpoint failed: %s\n", e.what()); } 313 { printf("DBFlush() : checkpoint failed: %s\n", e.what()); }
285 314
@@ -290,7 +319,7 @@ void DBFlush(bool fShutdown)
290 int nRefCount = (*mi).second; 319 int nRefCount = (*mi).second;
291 if (nRefCount == 0) 320 if (nRefCount == 0)
292 { 321 {
293 try { dbenv.lsn_reset(strFile.c_str(), 0); } 322 try { env.lsn_reset(strFile.c_str(), 0); }
294 catch (const std::exception& e) 323 catch (const std::exception& e)
295 { printf("DBFlush() : lsn_reset(%s) failed: %s\n", strFile.c_str(), e.what()); } 324 { printf("DBFlush() : lsn_reset(%s) failed: %s\n", strFile.c_str(), e.what()); }
296 mapFileUseCount.erase(mi++); 325 mapFileUseCount.erase(mi++);
@@ -310,9 +339,8 @@ void DBFlush(bool fShutdown)
310 // Found while making wallet encryption clean up after itself: 339 // Found while making wallet encryption clean up after itself:
311 // calling DBFlush(true) a second time crashed here every time. 340 // calling DBFlush(true) a second time crashed here every time.
312 if (mapFileUseCount.empty()) 341 if (mapFileUseCount.empty())
313 try { dbenv.log_archive(NULL, DB_ARCH_REMOVE); } catch (...) { } 342 try { env.log_archive(NULL, DB_ARCH_REMOVE); } catch (...) { }
314 try { dbenv.close(0); } catch (...) { } 343 CloseDbEnv();
315 fDbEnvInit = false;
316 } 344 }
317 } 345 }
318} 346}
@@ -1042,7 +1070,8 @@ bool BackupWallet(const string& strDest)
1042 // Committing first, so the copy is not missing the newest records. 1070 // Committing first, so the copy is not missing the newest records.
1043 // Both calls can throw, and a failed backup must not take the node 1071 // Both calls can throw, and a failed backup must not take the node
1044 // down with it. 1072 // down with it.
1045 try { dbenv.txn_checkpoint(0, 0, 0); } 1073 DbEnv& env = GetDbEnv();
1074 try { env.txn_checkpoint(0, 0, 0); }
1046 catch (const std::exception& e) 1075 catch (const std::exception& e)
1047 { return error("BackupWallet() : checkpoint failed: %s\n", e.what()); } 1076 { return error("BackupWallet() : checkpoint failed: %s\n", e.what()); }
1048 1077
@@ -1077,7 +1106,7 @@ bool BackupWallet(const string& strDest)
1077 } 1106 }
1078 1107
1079 // Without this the copy is welded to this node's database/ dir. 1108 // Without this the copy is welded to this node's database/ dir.
1080 int ret = dbenv.lsn_reset(strTemp.c_str(), 0); 1109 int ret = env.lsn_reset(strTemp.c_str(), 0);
1081 if (ret != 0) 1110 if (ret != 0)
1082 printf("BackupWallet() : warning -- lsn_reset returned %d; the copy " 1111 printf("BackupWallet() : warning -- lsn_reset returned %d; the copy "
1083 "may only open beside this node's database/ directory\n", ret); 1112 "may only open beside this node's database/ directory\n", ret);