| 125 | } |
| 126 | |
| 127 | bool BerkeleyEnvironment::Open(bool retry) |
| 128 | { |
| 129 | if (fDbEnvInit) |
| 130 | return true; |
| 131 | |
| 132 | boost::this_thread::interruption_point(); |
| 133 | |
| 134 | fs::path pathIn = strPath; |
| 135 | TryCreateDirectories(pathIn); |
| 136 | if (!LockDirectory(pathIn, ".walletlock")) { |
| 137 | LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", strPath); |
| 138 | return false; |
| 139 | } |
| 140 | |
| 141 | fs::path pathLogDir = pathIn / "database"; |
| 142 | TryCreateDirectories(pathLogDir); |
| 143 | fs::path pathErrorFile = pathIn / "db.log"; |
| 144 | LogPrintf("BerkeleyEnvironment::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); |
| 145 | |
| 146 | unsigned int nEnvFlags = 0; |
| 147 | if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB)) |
| 148 | nEnvFlags |= DB_PRIVATE; |
| 149 | |
| 150 | dbenv->set_lg_dir(pathLogDir.string().c_str()); |
| 151 | dbenv->set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet |
| 152 | dbenv->set_lg_bsize(0x10000); |
| 153 | dbenv->set_lg_max(1048576); |
| 154 | dbenv->set_lk_max_locks(40000); |
| 155 | dbenv->set_lk_max_objects(40000); |
| 156 | dbenv->set_errfile(fsbridge::fopen(pathErrorFile, "a")); /// debug |
| 157 | dbenv->set_flags(DB_AUTO_COMMIT, 1); |
| 158 | dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); |
| 159 | dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); |
| 160 | int ret = dbenv->open(strPath.c_str(), |
| 161 | DB_CREATE | |
| 162 | DB_INIT_LOCK | |
| 163 | DB_INIT_LOG | |
| 164 | DB_INIT_MPOOL | |
| 165 | DB_INIT_TXN | |
| 166 | DB_THREAD | |
| 167 | DB_RECOVER | |
| 168 | nEnvFlags, |
| 169 | S_IRUSR | S_IWUSR); |
| 170 | if (ret != 0) { |
| 171 | LogPrintf("BerkeleyEnvironment::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret)); |
| 172 | int ret2 = dbenv->close(0); |
| 173 | if (ret2 != 0) { |
| 174 | LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2)); |
| 175 | } |
| 176 | Reset(); |
| 177 | if (retry) { |
| 178 | // try moving the database env out of the way |
| 179 | fs::path pathDatabaseBak = pathIn / strprintf("database.%d.bak", GetTime()); |
| 180 | try { |
| 181 | fs::rename(pathLogDir, pathDatabaseBak); |
| 182 | LogPrintf("Moved old %s to %s. Retrying.\n", pathLogDir.string(), pathDatabaseBak.string()); |
| 183 | } catch (const fs::filesystem_error&) { |
| 184 | // failure is ok (well, not really, but it's not worse than what we started with) |
no test coverage detected