LCOV - code coverage report
Current view: top level - src - dbwrapper.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 57 70 81.4 %
Date: 2025-02-23 09:33:43 Functions: 9 11 81.8 %

          Line data    Source code
       1             : // Copyright (c) 2012-2014 The Bitcoin developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "dbwrapper.h"
       6             : 
       7             : #include <leveldb/cache.h>
       8             : #include <leveldb/env.h>
       9             : #include <leveldb/filter_policy.h>
      10             : #include <memenv.h>
      11             : #include <stdint.h>
      12             : 
      13             : 
      14        3153 : static void SetMaxOpenFiles(leveldb::Options *options) {
      15             :     // On most platforms the default setting of max_open_files (which is 1000)
      16             :     // is optimal. On Windows using a large file count is OK because the handles
      17             :     // do not interfere with select() loops. On 64-bit Unix hosts this value is
      18             :     // also OK, because up to that amount LevelDB will use an mmap
      19             :     // implementation that does not use extra file descriptors (the fds are
      20             :     // closed after being mapped).
      21             :     //
      22             :     // Increasing the value beyond the default is dangerous because LevelDB will
      23             :     // fall back to a non-mmap implementation when the file count is too large.
      24             :     // On 32-bit Unix host we should decrease the value because the handles use
      25             :     // up real fds, and we want to avoid fd exhaustion issues.
      26             :     //
      27             :     // See PR #12495 for further discussion.
      28             : 
      29        3153 :     int default_open_files = options->max_open_files;
      30             : #ifndef WIN32
      31        3153 :     if (sizeof(void*) < 8) {
      32             :         options->max_open_files = 64;
      33             :     }
      34             : #endif
      35        3153 :     LogPrint(BCLog::LEVELDB, "LevelDB using max_open_files=%d (default=%d)\n",
      36             :              options->max_open_files, default_open_files);
      37        3153 : }
      38             : 
      39        3153 : static leveldb::Options GetOptions(size_t nCacheSize)
      40             : {
      41        3153 :     leveldb::Options options;
      42        3153 :     options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
      43        3153 :     options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
      44        3153 :     options.filter_policy = leveldb::NewBloomFilterPolicy(10);
      45        3153 :     options.compression = leveldb::kNoCompression;
      46        3153 :     if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
      47             :         // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
      48             :         // on corruption in later versions.
      49        3153 :         options.paranoid_checks = true;
      50             :     }
      51        3153 :     SetMaxOpenFiles(&options);
      52        3153 :     return options;
      53             : }
      54             : 
      55        3153 : CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, int nVersion)
      56             : {
      57        3153 :     penv = nullptr;
      58        3153 :     readoptions.verify_checksums = true;
      59        3153 :     iteroptions.verify_checksums = true;
      60        3153 :     iteroptions.fill_cache = false;
      61        3153 :     syncoptions.sync = true;
      62        3153 :     options = GetOptions(nCacheSize);
      63        3153 :     options.create_if_missing = true;
      64        3153 :     this->nVersion = nVersion;
      65        3153 :     if (fMemory) {
      66        1010 :         penv = leveldb::NewMemEnv(leveldb::Env::Default());
      67        1010 :         options.env = penv;
      68             :     } else {
      69        2143 :         if (fWipe) {
      70          23 :             LogPrintf("Wiping LevelDB in %s\n", path.string());
      71          46 :             leveldb::Status result = leveldb::DestroyDB(path.string(), options);
      72          23 :             dbwrapper_private::HandleError(result);
      73             :         }
      74        2143 :         TryCreateDirectories(path);
      75        2143 :         LogPrintf("Opening LevelDB in %s\n", path.string());
      76             :     }
      77        3153 :     leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
      78        3153 :     dbwrapper_private::HandleError(status);
      79        3153 :     LogPrintf("Opened LevelDB successfully\n");
      80        3153 : }
      81             : 
      82        6306 : CDBWrapper::~CDBWrapper()
      83             : {
      84        3153 :     delete pdb;
      85        3153 :     pdb = nullptr;
      86        3153 :     delete options.filter_policy;
      87        3153 :     options.filter_policy = nullptr;
      88        3153 :     delete options.block_cache;
      89        3153 :     options.block_cache = nullptr;
      90        3153 :     delete penv;
      91        3153 :     options.env = nullptr;
      92        3153 : }
      93             : 
      94       51560 : bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
      95             : {
      96       51560 :     leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
      97       51560 :     dbwrapper_private::HandleError(status);
      98       51560 :     return true;
      99             : }
     100             : 
     101           0 : bool CDBWrapper::IsEmpty()
     102             : {
     103           0 :     std::unique_ptr<CDBIterator> it(NewIterator());
     104           0 :     it->SeekToFirst();
     105           0 :     return !(it->Valid());
     106             : }
     107             : 
     108       19608 : CDBIterator::~CDBIterator() { delete piter; }
     109     6496401 : bool CDBIterator::Valid() { return piter->Valid(); }
     110           0 : void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
     111     6404548 : void CDBIterator::Next() { piter->Next(); }
     112             : 
     113             : 
     114             : namespace dbwrapper_private {
     115             : 
     116       54736 : void HandleError(const leveldb::Status& status)
     117             : {
     118       54736 :     if (status.ok())
     119       54736 :         return;
     120           0 :     LogPrintf("%s\n", status.ToString());
     121           0 :     if (status.IsCorruption())
     122           0 :         throw dbwrapper_error("Database corrupted");
     123           0 :     if (status.IsIOError())
     124           0 :         throw dbwrapper_error("Database I/O error");
     125           0 :     if (status.IsNotFound())
     126           0 :         throw dbwrapper_error("Database entry missing");
     127           0 :     throw dbwrapper_error("Unknown database error");
     128             : }
     129             : 
     130             : };

Generated by: LCOV version 1.14