| 239 | |
| 240 | |
| 241 | CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) |
| 242 | { |
| 243 | int ret; |
| 244 | fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); |
| 245 | fFlushOnClose = fFlushOnCloseIn; |
| 246 | if (strFilename.empty()) |
| 247 | return; |
| 248 | |
| 249 | bool fCreate = strchr(pszMode, 'c') != NULL; |
| 250 | unsigned int nFlags = DB_THREAD; |
| 251 | if (fCreate) |
| 252 | nFlags |= DB_CREATE; |
| 253 | |
| 254 | { |
| 255 | LOCK(bitdb.cs_db); |
| 256 | if (!bitdb.Open(GetDataDir())) |
| 257 | throw runtime_error("CDB: Failed to open database environment."); |
| 258 | |
| 259 | strFile = strFilename; |
| 260 | ++bitdb.mapFileUseCount[strFile]; |
| 261 | pdb = bitdb.mapDb[strFile]; |
| 262 | if (pdb == NULL) { |
| 263 | pdb = new Db(bitdb.dbenv, 0); |
| 264 | |
| 265 | bool fMockDb = bitdb.IsMock(); |
| 266 | if (fMockDb) { |
| 267 | DbMpoolFile* mpf = pdb->get_mpf(); |
| 268 | ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); |
| 269 | if (ret != 0) |
| 270 | throw runtime_error(strprintf("CDB: Failed to configure for no temp file backing for database %s", strFile)); |
| 271 | } |
| 272 | |
| 273 | ret = pdb->open(NULL, // Txn pointer |
| 274 | fMockDb ? NULL : strFile.c_str(), // Filename |
| 275 | fMockDb ? strFile.c_str() : "main", // Logical db name |
| 276 | DB_BTREE, // Database type |
| 277 | nFlags, // Flags |
| 278 | 0); |
| 279 | |
| 280 | if (ret != 0) { |
| 281 | delete pdb; |
| 282 | pdb = NULL; |
| 283 | --bitdb.mapFileUseCount[strFile]; |
| 284 | strFile = ""; |
| 285 | throw runtime_error(strprintf("CDB: Error[%d]=%s, can't open database %s", ret, db_strerror(ret), strFile)); |
| 286 | } |
| 287 | |
| 288 | if (fCreate && !Exists(string("version"))) { |
| 289 | bool fTmp = fReadOnly; |
| 290 | fReadOnly = false; |
| 291 | WriteVersion(CLIENT_VERSION); |
| 292 | fReadOnly = fTmp; |
| 293 | } |
| 294 | |
| 295 | bitdb.mapDb[strFile] = pdb; |
| 296 | } |
| 297 | } |
| 298 | } |