LCOV - code coverage report
Current view: top level - src/wallet - bdb.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 15 16 93.8 %
Date: 2020-09-26 01:30:44 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2020 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 <atomic>
      17             : #include <map>
      18             : #include <memory>
      19             : #include <string>
      20             : #include <unordered_map>
      21             : #include <vector>
      22             : 
      23             : #if defined(__GNUC__) && !defined(__clang__)
      24             : #pragma GCC diagnostic push
      25             : #pragma GCC diagnostic ignored "-Wsuggest-override"
      26             : #endif
      27             : #include <db_cxx.h>
      28             : #if defined(__GNUC__) && !defined(__clang__)
      29             : #pragma GCC diagnostic pop
      30             : #endif
      31             : 
      32             : struct bilingual_str;
      33             : 
      34             : static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
      35             : static const bool DEFAULT_WALLET_PRIVDB = true;
      36             : 
      37             : struct WalletDatabaseFileId {
      38             :     u_int8_t value[DB_FILE_ID_LEN];
      39             :     bool operator==(const WalletDatabaseFileId& rhs) const;
      40             : };
      41             : 
      42             : class BerkeleyDatabase;
      43             : 
      44             : class BerkeleyEnvironment
      45             : {
      46             : private:
      47             :     bool fDbEnvInit;
      48             :     bool fMockDb;
      49             :     // Don't change into fs::path, as that can result in
      50             :     // shutdown problems/crashes caused by a static initialized internal pointer.
      51             :     std::string strPath;
      52             : 
      53             : public:
      54             :     std::unique_ptr<DbEnv> dbenv;
      55             :     std::map<std::string, std::reference_wrapper<BerkeleyDatabase>> m_databases;
      56             :     std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
      57             :     std::condition_variable_any m_db_in_use;
      58             : 
      59             :     BerkeleyEnvironment(const fs::path& env_directory);
      60             :     BerkeleyEnvironment();
      61             :     ~BerkeleyEnvironment();
      62             :     void Reset();
      63             : 
      64        3286 :     bool IsMock() const { return fMockDb; }
      65             :     bool IsInitialized() const { return fDbEnvInit; }
      66        1374 :     fs::path Directory() const { return strPath; }
      67             : 
      68             :     bool Open(bilingual_str& error);
      69             :     void Close();
      70             :     void Flush(bool fShutdown);
      71             :     void CheckpointLSN(const std::string& strFile);
      72             : 
      73             :     void CloseDb(const std::string& strFile);
      74             :     void ReloadDbEnv();
      75             : 
      76          17 :     DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC)
      77             :     {
      78          17 :         DbTxn* ptxn = nullptr;
      79          17 :         int ret = dbenv->txn_begin(nullptr, &ptxn, flags);
      80          17 :         if (!ptxn || ret != 0)
      81           0 :             return nullptr;
      82          17 :         return ptxn;
      83          17 :     }
      84             : };
      85             : 
      86             : /** Get BerkeleyEnvironment and database filename given a wallet path. */
      87             : std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
      88             : 
      89             : /** Check format of database file */
      90             : bool IsBDBFile(const fs::path& path);
      91             : 
      92             : class BerkeleyBatch;
      93             : 
      94             : /** An instance of this class represents one database.
      95             :  * For BerkeleyDB this is just a (env, strFile) tuple.
      96             :  **/
      97             : class BerkeleyDatabase : public WalletDatabase
      98             : {
      99             : public:
     100             :     BerkeleyDatabase() = delete;
     101             : 
     102             :     /** Create DB handle to real database */
     103        1852 :     BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, std::string filename) :
     104        2778 :         WalletDatabase(), env(std::move(env)), strFile(std::move(filename))
     105        1852 :     {
     106         926 :         auto inserted = this->env->m_databases.emplace(strFile, std::ref(*this));
     107         926 :         assert(inserted.second);
     108        1852 :     }
     109             : 
     110             :     ~BerkeleyDatabase() override;
     111             : 
     112             :     /** Open the database if it is not already opened.
     113             :      *  Dummy function, doesn't do anything right now, but is needed for class abstraction */
     114             :     void Open(const char* mode) override;
     115             : 
     116             :     /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
     117             :      */
     118             :     bool Rewrite(const char* pszSkip=nullptr) override;
     119             : 
     120             :     /** Indicate the a new database user has began using the database. */
     121             :     void AddRef() override;
     122             :     /** Indicate that database user has stopped using the database and that it could be flushed or closed. */
     123             :     void RemoveRef() override;
     124             : 
     125             :     /** Back up the entire database to a file.
     126             :      */
     127             :     bool Backup(const std::string& strDest) const override;
     128             : 
     129             :     /** Make sure all changes are flushed to database file.
     130             :      */
     131             :     void Flush() override;
     132             :     /** Flush to the database file and close the database.
     133             :      *  Also close the environment if no other databases are open in it.
     134             :      */
     135             :     void Close() override;
     136             :     /* flush the wallet passively (TRY_LOCK)
     137             :        ideal to be called periodically */
     138             :     bool PeriodicFlush() override;
     139             : 
     140             :     void IncrementUpdateCounter() override;
     141             : 
     142             :     void ReloadDbEnv() override;
     143             : 
     144             :     /** Verifies the environment and database file */
     145             :     bool Verify(bilingual_str& error);
     146             : 
     147             :     /** Return path to main database filename */
     148         655 :     std::string Filename() override { return (env->Directory() / strFile).string(); }
     149             : 
     150             :     /**
     151             :      * Pointer to shared database environment.
     152             :      *
     153             :      * Normally there is only one BerkeleyDatabase object per
     154             :      * BerkeleyEnvivonment, but in the special, backwards compatible case where
     155             :      * multiple wallet BDB data files are loaded from the same directory, this
     156             :      * will point to a shared instance that gets freed when the last data file
     157             :      * is closed.
     158             :      */
     159             :     std::shared_ptr<BerkeleyEnvironment> env;
     160             : 
     161             :     /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
     162             :     std::unique_ptr<Db> m_db;
     163             : 
     164             :     std::string strFile;
     165             : 
     166             :     /** Make a BerkeleyBatch connected to this database */
     167             :     std::unique_ptr<DatabaseBatch> MakeBatch(const char* mode = "r+", bool flush_on_close = true) override;
     168             : };
     169             : 
     170             : /** RAII class that provides access to a Berkeley database */
     171             : class BerkeleyBatch : public DatabaseBatch
     172             : {
     173             :     /** RAII class that automatically cleanses its data on destruction */
     174             :     class SafeDbt final
     175             :     {
     176             :         Dbt m_dbt;
     177             : 
     178             :     public:
     179             :         // construct Dbt with internally-managed data
     180             :         SafeDbt();
     181             :         // construct Dbt with provided data
     182             :         SafeDbt(void* data, size_t size);
     183             :         ~SafeDbt();
     184             : 
     185             :         // delegate to Dbt
     186             :         const void* get_data() const;
     187             :         u_int32_t get_size() const;
     188             : 
     189             :         // conversion operator to access the underlying Dbt
     190             :         operator Dbt*();
     191             :     };
     192             : 
     193             : private:
     194             :     bool ReadKey(CDataStream&& key, CDataStream& value) override;
     195             :     bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
     196             :     bool EraseKey(CDataStream&& key) override;
     197             :     bool HasKey(CDataStream&& key) override;
     198             : 
     199             : protected:
     200             :     Db* pdb;
     201             :     std::string strFile;
     202             :     DbTxn* activeTxn;
     203             :     Dbc* m_cursor;
     204             :     bool fReadOnly;
     205             :     bool fFlushOnClose;
     206             :     BerkeleyEnvironment *env;
     207             :     BerkeleyDatabase& m_database;
     208             : 
     209             : public:
     210             :     explicit BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode = "r+", bool fFlushOnCloseIn=true);
     211             :     ~BerkeleyBatch() override;
     212             : 
     213             :     BerkeleyBatch(const BerkeleyBatch&) = delete;
     214             :     BerkeleyBatch& operator=(const BerkeleyBatch&) = delete;
     215             : 
     216             :     void Flush() override;
     217             :     void Close() override;
     218             : 
     219             :     bool StartCursor() override;
     220             :     bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override;
     221             :     void CloseCursor() override;
     222             :     bool TxnBegin() override;
     223             :     bool TxnCommit() override;
     224             :     bool TxnAbort() override;
     225             : };
     226             : 
     227             : std::string BerkeleyDatabaseVersion();
     228             : 
     229             : //! Check if Berkeley database exists at specified path.
     230             : bool ExistsBerkeleyDatabase(const fs::path& path);
     231             : 
     232             : //! Return object giving access to Berkeley database at specified path.
     233             : std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     234             : 
     235             : #endif // BITCOIN_WALLET_BDB_H

Generated by: LCOV version 1.15