Branch data 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 : 0 : 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() {} 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 : : /** RAII class that provides access to a WalletDatabase */ 40 : : class SQLiteBatch : public DatabaseBatch 41 : : { 42 : : private: 43 : : SQLiteDatabase& m_database; 44 : : 45 : : sqlite3_stmt* m_read_stmt{nullptr}; 46 : : sqlite3_stmt* m_insert_stmt{nullptr}; 47 : : sqlite3_stmt* m_overwrite_stmt{nullptr}; 48 : : sqlite3_stmt* m_delete_stmt{nullptr}; 49 : : sqlite3_stmt* m_delete_prefix_stmt{nullptr}; 50 : : 51 : : void SetupSQLStatements(); 52 : : bool ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob); 53 : : 54 : : bool ReadKey(DataStream&& key, DataStream& value) override; 55 : : bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override; 56 : : bool EraseKey(DataStream&& key) override; 57 : : bool HasKey(DataStream&& key) override; 58 : : bool ErasePrefix(Span<const std::byte> prefix) override; 59 : : 60 : : public: 61 : : explicit SQLiteBatch(SQLiteDatabase& database); 62 [ # # ]: 0 : ~SQLiteBatch() override { Close(); } 63 : : 64 : : /* No-op. See comment on SQLiteDatabase::Flush */ 65 : 0 : void Flush() override {} 66 : : 67 : : void Close() override; 68 : : 69 : : std::unique_ptr<DatabaseCursor> GetNewCursor() override; 70 : : std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(Span<const std::byte> prefix) override; 71 : : bool TxnBegin() override; 72 : : bool TxnCommit() override; 73 : : bool TxnAbort() override; 74 : : }; 75 : : 76 : : /** An instance of this class represents one SQLite3 database. 77 : : **/ 78 : : class SQLiteDatabase : public WalletDatabase 79 : : { 80 : : private: 81 : : const bool m_mock{false}; 82 : : 83 : : const std::string m_dir_path; 84 : : 85 : : const std::string m_file_path; 86 : : 87 : : /** 88 : : * This mutex protects SQLite initialization and shutdown. 89 : : * sqlite3_config() and sqlite3_shutdown() are not thread-safe (sqlite3_initialize() is). 90 : : * Concurrent threads that execute SQLiteDatabase::SQLiteDatabase() should have just one 91 : : * of them do the init and the rest wait for it to complete before all can proceed. 92 : : */ 93 : : static Mutex g_sqlite_mutex; 94 : : static int g_sqlite_count GUARDED_BY(g_sqlite_mutex); 95 : : 96 : : void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex); 97 : : 98 : : public: 99 : : SQLiteDatabase() = delete; 100 : : 101 : : /** Create DB handle to real database */ 102 : : SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false); 103 : : 104 : : ~SQLiteDatabase(); 105 : : 106 : : bool Verify(bilingual_str& error); 107 : : 108 : : /** Open the database if it is not already opened */ 109 : : void Open() override; 110 : : 111 : : /** Close the database */ 112 : : void Close() override; 113 : : 114 : : /* These functions are unused */ 115 : 0 : void AddRef() override { assert(false); } 116 : 0 : void RemoveRef() override { assert(false); } 117 : : 118 : : /** Rewrite the entire database on disk */ 119 : : bool Rewrite(const char* skip = nullptr) override; 120 : : 121 : : /** Back up the entire database to a file. 122 : : */ 123 : : bool Backup(const std::string& dest) const override; 124 : : 125 : : /** No-ops 126 : : * 127 : : * SQLite always flushes everything to the database file after each transaction 128 : : * (each Read/Write/Erase that we do is its own transaction unless we called 129 : : * TxnBegin) so there is no need to have Flush or Periodic Flush. 130 : : * 131 : : * There is no DB env to reload, so ReloadDbEnv has nothing to do 132 : : */ 133 : 0 : void Flush() override {} 134 : 0 : bool PeriodicFlush() override { return false; } 135 : 0 : void ReloadDbEnv() override {} 136 : : 137 : 0 : void IncrementUpdateCounter() override { ++nUpdateCounter; } 138 : : 139 : 0 : std::string Filename() override { return m_file_path; } 140 [ # # ]: 0 : std::string Format() override { return "sqlite"; } 141 : : 142 : : /** Make a SQLiteBatch connected to this database */ 143 : : std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override; 144 : : 145 : : sqlite3* m_db{nullptr}; 146 : : bool m_use_unsafe_sync; 147 : : }; 148 : : 149 : : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error); 150 : : 151 : : std::string SQLiteDatabaseVersion(); 152 : : } // namespace wallet 153 : : 154 : : #endif // BITCOIN_WALLET_SQLITE_H