diff options
Diffstat (limited to 'src/db.cpp')
| -rw-r--r-- | src/db.cpp | 93 |
1 files changed, 61 insertions, 32 deletions
| @@ -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. |
| 54 | string strWalletLoadError; | 54 | string strWalletLoadError; |
| 55 | DbEnv dbenv(0u); | 55 | static DbEnv* pdbenv = NULL; |
| 56 | static FILE* pdbErrFile = NULL; | ||
| 56 | static map<string, int> mapFileUseCount; | 57 | static map<string, int> mapFileUseCount; |
| 57 | 58 | ||
| 59 | DbEnv& GetDbEnv() | ||
| 60 | { | ||
| 61 | if (!pdbenv) | ||
| 62 | pdbenv = new DbEnv(0u); | ||
| 63 | return *pdbenv; | ||
| 64 | } | ||
| 65 | |||
| 66 | static 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 | |||
| 58 | class CDBInit | 83 | class CDBInit |
| 59 | { | 84 | { |
| 60 | public: | 85 | public: |
| @@ -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 | } |
| 74 | instance_of_cdbinit; | 95 | instance_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); |