LCOV - code coverage report
Current view: top level - src/wallet - sqlite.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 0.0 % 18 0
Test Date: 2025-01-22 04:09:46 Functions: 0.0 % 15 0

            Line data    Source code
       1              : // Copyright (c) 2020-2021 The Bitcoin Core 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              : #ifndef BITCOIN_WALLET_SQLITE_H
       6              : #define BITCOIN_WALLET_SQLITE_H
       7              : 
       8              : #include <sync.h>
       9              : #include <wallet/db.h>
      10              : 
      11              : struct bilingual_str;
      12              : 
      13              : struct sqlite3_stmt;
      14              : struct sqlite3;
      15              : 
      16              : namespace wallet {
      17              : class SQLiteDatabase;
      18              : 
      19              : /** RAII class that provides a database cursor */
      20              : class SQLiteCursor : public DatabaseCursor
      21              : {
      22              : public:
      23              :     sqlite3_stmt* m_cursor_stmt{nullptr};
      24              :     // Copies of the prefix things for the prefix cursor.
      25              :     // Prevents SQLite from accessing temp variables for the prefix things.
      26              :     std::vector<std::byte> m_prefix_range_start;
      27              :     std::vector<std::byte> m_prefix_range_end;
      28              : 
      29            0 :     explicit SQLiteCursor() = default;
      30            0 :     explicit SQLiteCursor(std::vector<std::byte> start_range, std::vector<std::byte> end_range)
      31            0 :         : m_prefix_range_start(std::move(start_range)),
      32            0 :         m_prefix_range_end(std::move(end_range))
      33            0 :     {}
      34              :     ~SQLiteCursor() override;
      35              : 
      36              :     Status Next(DataStream& key, DataStream& value) override;
      37              : };
      38              : 
      39              : /** Class responsible for executing SQL statements in SQLite databases.
      40              :  *  Methods are virtual so they can be overridden by unit tests testing unusual database conditions. */
      41            0 : class SQliteExecHandler
      42              : {
      43              : public:
      44            0 :     virtual ~SQliteExecHandler() = default;
      45              :     virtual int Exec(SQLiteDatabase& database, const std::string& statement);
      46              : };
      47              : 
      48              : /** RAII class that provides access to a WalletDatabase */
      49              : class SQLiteBatch : public DatabaseBatch
      50              : {
      51              : private:
      52              :     SQLiteDatabase& m_database;
      53              :     std::unique_ptr<SQliteExecHandler> m_exec_handler{std::make_unique<SQliteExecHandler>()};
      54              : 
      55              :     sqlite3_stmt* m_read_stmt{nullptr};
      56              :     sqlite3_stmt* m_insert_stmt{nullptr};
      57              :     sqlite3_stmt* m_overwrite_stmt{nullptr};
      58              :     sqlite3_stmt* m_delete_stmt{nullptr};
      59              :     sqlite3_stmt* m_delete_prefix_stmt{nullptr};
      60              : 
      61              :     /** Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_semaphore.
      62              :      * If the batch starts a db tx, it acquires the semaphore and sets this to true, keeping the semaphore
      63              :      * until the transaction ends to prevent other batch objects from writing to the database.
      64              :      *
      65              :      * If this batch did not start a transaction, the semaphore is acquired transiently when writing and m_txn
      66              :      * is not set.
      67              :      *
      68              :      * m_txn is different from HasActiveTxn() as it is only true when this batch has started the transaction,
      69              :      * not just when any batch has started a transaction.
      70              :      */
      71              :     bool m_txn{false};
      72              : 
      73              :     void SetupSQLStatements();
      74              :     bool ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob);
      75              : 
      76              :     bool ReadKey(DataStream&& key, DataStream& value) override;
      77              :     bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
      78              :     bool EraseKey(DataStream&& key) override;
      79              :     bool HasKey(DataStream&& key) override;
      80              :     bool ErasePrefix(Span<const std::byte> prefix) override;
      81              : 
      82              : public:
      83              :     explicit SQLiteBatch(SQLiteDatabase& database);
      84            0 :     ~SQLiteBatch() override { Close(); }
      85              : 
      86              :     void SetExecHandler(std::unique_ptr<SQliteExecHandler>&& handler) { m_exec_handler = std::move(handler); }
      87              : 
      88              :     /* No-op. See comment on SQLiteDatabase::Flush */
      89            0 :     void Flush() override {}
      90              : 
      91              :     void Close() override;
      92              : 
      93              :     std::unique_ptr<DatabaseCursor> GetNewCursor() override;
      94              :     std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(Span<const std::byte> prefix) override;
      95              :     bool TxnBegin() override;
      96              :     bool TxnCommit() override;
      97              :     bool TxnAbort() override;
      98            0 :     bool HasActiveTxn() override { return m_txn; }
      99              : };
     100              : 
     101              : /** An instance of this class represents one SQLite3 database.
     102              :  **/
     103              : class SQLiteDatabase : public WalletDatabase
     104              : {
     105              : private:
     106              :     const bool m_mock{false};
     107              : 
     108              :     const std::string m_dir_path;
     109              : 
     110              :     const std::string m_file_path;
     111              : 
     112              :     /**
     113              :      * This mutex protects SQLite initialization and shutdown.
     114              :      * sqlite3_config() and sqlite3_shutdown() are not thread-safe (sqlite3_initialize() is).
     115              :      * Concurrent threads that execute SQLiteDatabase::SQLiteDatabase() should have just one
     116              :      * of them do the init and the rest wait for it to complete before all can proceed.
     117              :      */
     118              :     static Mutex g_sqlite_mutex;
     119              :     static int g_sqlite_count GUARDED_BY(g_sqlite_mutex);
     120              : 
     121              :     void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex);
     122              : 
     123              : public:
     124              :     SQLiteDatabase() = delete;
     125              : 
     126              :     /** Create DB handle to real database */
     127              :     SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false);
     128              : 
     129              :     ~SQLiteDatabase();
     130              : 
     131              :     // Batches must acquire this semaphore on writing, and release when done writing.
     132              :     // This ensures that only one batch is modifying the database at a time.
     133              :     CSemaphore m_write_semaphore;
     134              : 
     135              :     bool Verify(bilingual_str& error);
     136              : 
     137              :     /** Open the database if it is not already opened */
     138              :     void Open() override;
     139              : 
     140              :     /** Close the database */
     141              :     void Close() override;
     142              : 
     143              :     /* These functions are unused */
     144            0 :     void AddRef() override { assert(false); }
     145            0 :     void RemoveRef() override { assert(false); }
     146              : 
     147              :     /** Rewrite the entire database on disk */
     148              :     bool Rewrite(const char* skip = nullptr) override;
     149              : 
     150              :     /** Back up the entire database to a file.
     151              :      */
     152              :     bool Backup(const std::string& dest) const override;
     153              : 
     154              :     /** No-ops
     155              :      *
     156              :      * SQLite always flushes everything to the database file after each transaction
     157              :      * (each Read/Write/Erase that we do is its own transaction unless we called
     158              :      * TxnBegin) so there is no need to have Flush or Periodic Flush.
     159              :      *
     160              :      * There is no DB env to reload, so ReloadDbEnv has nothing to do
     161              :      */
     162            0 :     void Flush() override {}
     163            0 :     bool PeriodicFlush() override { return false; }
     164            0 :     void ReloadDbEnv() override {}
     165              : 
     166            0 :     void IncrementUpdateCounter() override { ++nUpdateCounter; }
     167              : 
     168            0 :     std::string Filename() override { return m_file_path; }
     169            0 :     std::string Format() override { return "sqlite"; }
     170              : 
     171              :     /** Make a SQLiteBatch connected to this database */
     172              :     std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
     173              : 
     174              :     /** Return true if there is an on-going txn in this connection */
     175              :     bool HasActiveTxn();
     176              : 
     177              :     sqlite3* m_db{nullptr};
     178              :     bool m_use_unsafe_sync;
     179              : };
     180              : 
     181              : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     182              : 
     183              : std::string SQLiteDatabaseVersion();
     184              : } // namespace wallet
     185              : 
     186              : #endif // BITCOIN_WALLET_SQLITE_H
        

Generated by: LCOV version 2.0-1