Line data Source code
1 : // Copyright (c) 2020 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 access to a WalletDatabase */ 20 : class SQLiteBatch : public DatabaseBatch 21 : { 22 : private: 23 : SQLiteDatabase& m_database; 24 : 25 : bool m_cursor_init = false; 26 : 27 : // True iff TxnBegin() succeeded on this batch and has not yet been 28 : // matched by TxnCommit()/TxnAbort(). Only the batch that started the 29 : // transaction auto-aborts in Close(); other batches sharing the SQLite 30 : // connection while an outer transaction is in flight must not interfere. 31 : bool m_txn_started{false}; 32 : 33 : sqlite3_stmt* m_read_stmt{nullptr}; 34 : sqlite3_stmt* m_insert_stmt{nullptr}; 35 : sqlite3_stmt* m_overwrite_stmt{nullptr}; 36 : sqlite3_stmt* m_delete_stmt{nullptr}; 37 : sqlite3_stmt* m_cursor_stmt{nullptr}; 38 : sqlite3_stmt* m_delete_prefix_stmt{nullptr}; 39 : 40 : void SetupSQLStatements(); 41 : bool ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob); 42 : 43 : bool ReadKey(CDataStream&& key, CDataStream& value) override; 44 : bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override; 45 : bool EraseKey(CDataStream&& key) override; 46 : bool HasKey(CDataStream&& key) override; 47 : bool ErasePrefix(Span<const std::byte> prefix) override; 48 : 49 : public: 50 : explicit SQLiteBatch(SQLiteDatabase& database); 51 626592 : ~SQLiteBatch() override { Close(); } 52 : 53 : /* No-op. See comment on SQLiteDatabase::Flush */ 54 137 : void Flush() override {} 55 : 56 : void Close() override; 57 : 58 : bool StartCursor() override; 59 : bool ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete) override; 60 : void CloseCursor() override; 61 : bool TxnBegin() override; 62 : bool TxnCommit() override; 63 : bool TxnAbort() override; 64 : }; 65 : 66 : /** An instance of this class represents one SQLite3 database. 67 : **/ 68 : class SQLiteDatabase : public WalletDatabase 69 : { 70 : private: 71 : const bool m_mock{false}; 72 : 73 : const std::string m_dir_path; 74 : 75 : const std::string m_file_path; 76 : 77 : /** 78 : * This mutex protects SQLite initialization and shutdown. 79 : * sqlite3_config() and sqlite3_shutdown() are not thread-safe (sqlite3_initialize() is). 80 : * Concurrent threads that execute SQLiteDatabase::SQLiteDatabase() should have just one 81 : * of them do the init and the rest wait for it to complete before all can proceed. 82 : */ 83 : static Mutex g_sqlite_mutex; 84 : static int g_sqlite_count GUARDED_BY(g_sqlite_mutex); 85 : 86 : void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex); 87 : 88 : public: 89 : SQLiteDatabase() = delete; 90 : 91 : /** Create DB handle to real database */ 92 : SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false); 93 : 94 : ~SQLiteDatabase(); 95 : 96 : bool Verify(bilingual_str& error); 97 : 98 : /** Open the database if it is not already opened */ 99 : void Open() override; 100 : 101 : /** Close the database */ 102 : void Close() override; 103 : 104 : /* These functions are unused */ 105 0 : void AddRef() override { assert(false); } 106 0 : void RemoveRef() override { assert(false); } 107 : 108 : /** Rewrite the entire database on disk */ 109 : bool Rewrite(const char* skip = nullptr) override; 110 : 111 : /** Back up the entire database to a file. 112 : */ 113 : bool Backup(const std::string& dest) const override; 114 : 115 : /** No-ops 116 : * 117 : * SQLite always flushes everything to the database file after each transaction 118 : * (each Read/Write/Erase that we do is its own transaction unless we called 119 : * TxnBegin) so there is no need to have Flush or Periodic Flush. 120 : * 121 : * There is no DB env to reload, so ReloadDbEnv has nothing to do 122 : */ 123 1461 : void Flush() override {} 124 2846 : bool PeriodicFlush() override { return false; } 125 35 : void ReloadDbEnv() override {} 126 : 127 225505 : void IncrementUpdateCounter() override { ++nUpdateCounter; } 128 : 129 251997 : std::string Filename() override { return m_file_path; } 130 802 : std::string Format() override { return "sqlite"; } 131 : 132 : /** Make a SQLiteBatch connected to this database */ 133 : std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override; 134 : 135 : sqlite3* m_db{nullptr}; 136 : bool m_use_unsafe_sync; 137 : }; 138 : 139 : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error); 140 : 141 : std::string SQLiteDatabaseVersion(); 142 : } // namespace wallet 143 : 144 : #endif // BITCOIN_WALLET_SQLITE_H