Make sure database has a unique fileid within the environment. If it doesn't, throw an error. BDB caches do not work properly when more than one open database has the same fileid (values written to one database may show up in reads to other databases). BerkeleyDB generates unique fileids by default (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html), so bitcoin shou
| 30 | //! so bitcoin should never create different databases with the same fileid, but |
| 31 | //! this error can be triggered if users manually copy database files. |
| 32 | void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filename, Db& db) |
| 33 | { |
| 34 | if (env.IsMock()) return; |
| 35 | |
| 36 | u_int8_t fileid[DB_FILE_ID_LEN]; |
| 37 | int ret = db.get_mpf()->get_fileid(fileid); |
| 38 | if (ret != 0) { |
| 39 | throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (get_fileid failed with %d)", filename, ret)); |
| 40 | } |
| 41 | |
| 42 | for (const auto& item : env.mapDb) { |
| 43 | u_int8_t item_fileid[DB_FILE_ID_LEN]; |
| 44 | if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 && |
| 45 | memcmp(fileid, item_fileid, sizeof(fileid)) == 0) { |
| 46 | const char* item_filename = nullptr; |
| 47 | item.second->get_dbname(&item_filename, nullptr); |
| 48 | throw std::runtime_error(strprintf("BerkeleyBatch: Can't open database %s (duplicates fileid %s from %s)", filename, |
| 49 | HexStr(std::begin(item_fileid), std::end(item_fileid)), |
| 50 | item_filename ? item_filename : "(unknown database)")); |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | CCriticalSection cs_db; |
| 56 | std::map<std::string, BerkeleyEnvironment> g_dbenvs GUARDED_BY(cs_db); //!< Map from directory name to open db environment. |
no test coverage detected