LCOV - code coverage report
Current view: top level - src/wallet - bdb.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 17 18 94.4 %
Date: 2026-06-25 07:23:43 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_WALLET_BDB_H
       7             : #define BITCOIN_WALLET_BDB_H
       8             : 
       9             : #include <clientversion.h>
      10             : #include <fs.h>
      11             : #include <serialize.h>
      12             : #include <streams.h>
      13             : #include <util/system.h>
      14             : #include <wallet/db.h>
      15             : 
      16             : #include <map>
      17             : #include <memory>
      18             : #include <string>
      19             : #include <unordered_map>
      20             : #include <vector>
      21             : 
      22             : struct bilingual_str;
      23             : 
      24             : #include <db_cxx.h>
      25             : 
      26             : namespace wallet {
      27             : struct WalletDatabaseFileId {
      28             :     uint8_t value[DB_FILE_ID_LEN];
      29             :     bool operator==(const WalletDatabaseFileId& rhs) const;
      30             : };
      31             : 
      32             : class BerkeleyDatabase;
      33             : 
      34             : class BerkeleyEnvironment
      35             : {
      36             : private:
      37             :     bool fDbEnvInit;
      38             :     bool fMockDb;
      39             :     // Don't change into fs::path, as that can result in
      40             :     // shutdown problems/crashes caused by a static initialized internal pointer.
      41             :     std::string strPath;
      42             : 
      43             : public:
      44             :     std::unique_ptr<DbEnv> dbenv;
      45             :     std::map<fs::path, std::reference_wrapper<BerkeleyDatabase>> m_databases;
      46             :     std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
      47             :     std::condition_variable_any m_db_in_use;
      48             :     bool m_use_shared_memory;
      49             : 
      50             :     explicit BerkeleyEnvironment(const fs::path& env_directory, bool use_shared_memory);
      51             :     BerkeleyEnvironment();
      52             :     ~BerkeleyEnvironment();
      53             :     void Reset();
      54             : 
      55        8252 :     bool IsMock() const { return fMockDb; }
      56             :     bool IsInitialized() const { return fDbEnvInit; }
      57        3194 :     fs::path Directory() const { return fs::PathFromString(strPath); }
      58             : 
      59             :     bool Open(bilingual_str& error);
      60             :     void Close();
      61             :     void Flush(bool fShutdown);
      62             :     void CheckpointLSN(const std::string& strFile);
      63             : 
      64             :     void CloseDb(const fs::path& filename);
      65             :     void ReloadDbEnv();
      66             : 
      67          66 :     DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
      68             :     {
      69          66 :         DbTxn* ptxn = nullptr;
      70          66 :         int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
      71          66 :         if (!ptxn || ret != 0)
      72           0 :             return nullptr;
      73          66 :         return ptxn;
      74          66 :     }
      75             : };
      76             : 
      77             : /** Get BerkeleyEnvironment given a directory path. */
      78             : std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory, bool use_shared_memory);
      79             : 
      80             : class BerkeleyBatch;
      81             : 
      82             : /** An instance of this class represents one database.
      83             :  * For BerkeleyDB this is just a (env, strFile) tuple.
      84             :  **/
      85             : class BerkeleyDatabase : public WalletDatabase
      86             : {
      87             : public:
      88             :     BerkeleyDatabase() = delete;
      89             : 
      90             :     /** Create DB handle to real database */
      91        5775 :     BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, fs::path filename, const DatabaseOptions& options) :
      92        5775 :         WalletDatabase(), env(std::move(env)), m_filename(std::move(filename)), m_max_log_mb(options.max_log_mb)
      93        3850 :     {
      94        1925 :         auto inserted = this->env->m_databases.emplace(m_filename, std::ref(*this));
      95        1925 :         assert(inserted.second);
      96        3850 :     }
      97             : 
      98             :     ~BerkeleyDatabase() override;
      99             : 
     100             :     /** Open the database if it is not already opened. */
     101             :     void Open() override;
     102             : 
     103             :     /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
     104             :      */
     105             :     bool Rewrite(const char* pszSkip=nullptr) override;
     106             : 
     107             :     /** Indicate that a new database user has begun using the database. */
     108             :     void AddRef() override;
     109             :     /** Indicate that database user has stopped using the database and that it could be flushed or closed. */
     110             :     void RemoveRef() override;
     111             : 
     112             :     /** Back up the entire database to a file.
     113             :      */
     114             :     bool Backup(const std::string& strDest) const override;
     115             : 
     116             :     /** Make sure all changes are flushed to database file.
     117             :      */
     118             :     void Flush() override;
     119             :     /** Flush to the database file and close the database.
     120             :      *  Also close the environment if no other databases are open in it.
     121             :      */
     122             :     void Close() override;
     123             :     /* flush the wallet passively (TRY_LOCK)
     124             :        ideal to be called periodically */
     125             :     bool PeriodicFlush() override;
     126             : 
     127             :     void IncrementUpdateCounter() override;
     128             : 
     129             :     void ReloadDbEnv() override;
     130             : 
     131             :     /** Verifies the environment and database file */
     132             :     bool Verify(bilingual_str& error);
     133             : 
     134             :     /** Return path to main database filename */
     135        1535 :     std::string Filename() override { return fs::PathToString(env->Directory() / m_filename); }
     136             : 
     137        1328 :     std::string Format() override { return "bdb"; }
     138             :     /**
     139             :      * Pointer to shared database environment.
     140             :      *
     141             :      * Normally there is only one BerkeleyDatabase object per
     142             :      * BerkeleyEnvivonment, but in the special, backwards compatible case where
     143             :      * multiple wallet BDB data files are loaded from the same directory, this
     144             :      * will point to a shared instance that gets freed when the last data file
     145             :      * is closed.
     146             :      */
     147             :     std::shared_ptr<BerkeleyEnvironment> env;
     148             : 
     149             :     /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
     150             :     std::unique_ptr<Db> m_db;
     151             : 
     152             :     fs::path m_filename;
     153             :     int64_t m_max_log_mb;
     154             : 
     155             :     /** Make a BerkeleyBatch connected to this database */
     156             :     std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
     157             : 
     158        2234 :     virtual bool SupportsAutoBackup() override { return true; }
     159             : };
     160             : 
     161             : /** RAII class that provides access to a Berkeley database */
     162             : class BerkeleyBatch : public DatabaseBatch
     163             : {
     164             : public:
     165             :     /** RAII class that automatically cleanses its data on destruction */
     166             :     class SafeDbt final
     167             :     {
     168             :         Dbt m_dbt;
     169             : 
     170             :     public:
     171             :         // construct Dbt with internally-managed data
     172             :         SafeDbt();
     173             :         // construct Dbt with provided data
     174             :         SafeDbt(void* data, size_t size);
     175             :         ~SafeDbt();
     176             : 
     177             :         // delegate to Dbt
     178             :         const void* get_data() const;
     179             :         uint32_t get_size() const;
     180             : 
     181             :         // conversion operator to access the underlying Dbt
     182             :         operator Dbt*();
     183             :     };
     184             : 
     185             : private:
     186             :     bool ReadKey(CDataStream&& key, CDataStream& value) override;
     187             :     bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
     188             :     bool EraseKey(CDataStream&& key) override;
     189             :     bool HasKey(CDataStream&& key) override;
     190             :     bool ErasePrefix(Span<const std::byte> prefix) override;
     191             : 
     192             : protected:
     193             :     Db* pdb{nullptr};
     194             :     std::string strFile;
     195             :     DbTxn* activeTxn{nullptr};
     196             :     Dbc* m_cursor{nullptr};
     197             :     bool fReadOnly;
     198             :     bool fFlushOnClose;
     199             :     BerkeleyEnvironment *env;
     200             :     BerkeleyDatabase& m_database;
     201             : 
     202             : public:
     203             :     explicit BerkeleyBatch(BerkeleyDatabase& database, const bool fReadOnly, bool fFlushOnCloseIn=true);
     204             :     ~BerkeleyBatch() override;
     205             : 
     206             :     BerkeleyBatch(const BerkeleyBatch&) = delete;
     207             :     BerkeleyBatch& operator=(const BerkeleyBatch&) = delete;
     208             : 
     209             :     void Flush() override;
     210             :     void Close() override;
     211             : 
     212             :     bool StartCursor() override;
     213             :     bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override;
     214             :     void CloseCursor() override;
     215             :     bool TxnBegin() override;
     216             :     bool TxnCommit() override;
     217             :     bool TxnAbort() override;
     218             :     DbTxn* txn() const { return activeTxn; }
     219             : };
     220             : 
     221             : std::string BerkeleyDatabaseVersion();
     222             : 
     223             : /** Perform sanity check of runtime BDB version versus linked BDB version.
     224             :  */
     225             : bool BerkeleyDatabaseSanityCheck();
     226             : 
     227             : //! Return object giving access to Berkeley database at specified path.
     228             : std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     229             : } // namespace wallet
     230             : 
     231             : #endif // BITCOIN_WALLET_BDB_H

Generated by: LCOV version 1.16