| 218 | }; |
| 219 | |
| 220 | CDBWrapper::CDBWrapper(const DBParams& params) |
| 221 | : m_db_context{std::make_unique<LevelDBContext>()}, m_name{fs::PathToString(params.path.stem())} |
| 222 | { |
| 223 | DBContext().penv = nullptr; |
| 224 | DBContext().readoptions.verify_checksums = true; |
| 225 | DBContext().iteroptions.verify_checksums = true; |
| 226 | DBContext().iteroptions.fill_cache = false; |
| 227 | DBContext().syncoptions.sync = true; |
| 228 | DBContext().options = GetOptions(params.cache_bytes); |
| 229 | DBContext().options.create_if_missing = true; |
| 230 | DBContext().options.max_file_size = params.max_file_size; |
| 231 | assert(!(params.testing_env && params.memory_only)); |
| 232 | if (params.testing_env) { |
| 233 | DBContext().options.env = params.testing_env; |
| 234 | } else if (params.memory_only) { |
| 235 | DBContext().penv = leveldb::NewMemEnv(leveldb::Env::Default()); |
| 236 | DBContext().options.env = DBContext().penv; |
| 237 | } |
| 238 | if (!params.memory_only) { |
| 239 | if (params.wipe_data) { |
| 240 | LogInfo("Wiping LevelDB in %s", fs::PathToString(params.path)); |
| 241 | leveldb::Status result = leveldb::DestroyDB(fs::PathToString(params.path), DBContext().options); |
| 242 | HandleError(result); |
| 243 | } |
| 244 | if (!params.testing_env) { |
| 245 | TryCreateDirectories(params.path); |
| 246 | } |
| 247 | LogInfo("Opening LevelDB in %s", fs::PathToString(params.path)); |
| 248 | } |
| 249 | // PathToString() return value is safe to pass to leveldb open function, |
| 250 | // because on POSIX leveldb passes the byte string directly to ::open(), and |
| 251 | // on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW |
| 252 | // (see env_posix.cc and env_windows.cc). |
| 253 | leveldb::Status status = leveldb::DB::Open(DBContext().options, fs::PathToString(params.path), &DBContext().pdb); |
| 254 | HandleError(status); |
| 255 | LogInfo("Opened LevelDB successfully"); |
| 256 | |
| 257 | if (params.options.force_compact) { |
| 258 | LogInfo("Starting database compaction of %s", fs::PathToString(params.path)); |
| 259 | CompactFull(); |
| 260 | LogInfo("Finished database compaction of %s", fs::PathToString(params.path)); |
| 261 | } |
| 262 | |
| 263 | if (!Read(OBFUSCATION_KEY, m_obfuscation) && params.obfuscate && IsEmpty()) { |
| 264 | // Generate and write the new obfuscation key. |
| 265 | const Obfuscation obfuscation{FastRandomContext{}.randbytes<Obfuscation::KEY_SIZE>()}; |
| 266 | assert(!m_obfuscation); // Make sure the key is written without obfuscation. |
| 267 | Write(OBFUSCATION_KEY, obfuscation); |
| 268 | m_obfuscation = obfuscation; |
| 269 | LogInfo("Wrote new obfuscation key for %s: %s", fs::PathToString(params.path), m_obfuscation.HexKey()); |
| 270 | } |
| 271 | LogInfo("Using obfuscation key for %s: %s", fs::PathToString(params.path), m_obfuscation.HexKey()); |
| 272 | } |
| 273 | |
| 274 | CDBWrapper::~CDBWrapper() |
| 275 | { |
nothing calls this directly
no test coverage detected