diff options
author | Ava Chow <github@achow101.com> | 2023-12-18 17:06:04 -0500 |
---|---|---|
committer | Ava Chow <github@achow101.com> | 2024-02-06 12:24:36 -0500 |
commit | 395bcd245476d7c83abf2d82e31e90b6d0c432f3 (patch) | |
tree | 0ff1b94cd7319a1eb4eb8d22055a5b14be9d32e2 /src/wallet/sqlite.h | |
parent | 6f7395b3ff21228183df190f3ed1bdc3049f39e2 (diff) | |
download | bitcoin-395bcd245476d7c83abf2d82e31e90b6d0c432f3.tar.xz |
sqlite: Ensure that only one SQLiteBatch is writing to db at a time
A SQLiteBatch need to wait for any other batch to finish writing before
it can begin writing, otherwise db txn state may be incorrectly
modified. To enforce this, each SQLiteDatabase has a semaphore which
acts as a lock and is acquired by a batch when it begins a write, erase,
or a transaction, and is released by it when it is done.
To avoid deadlocking on itself for writing during a transaction,
SQLiteBatch also keeps track of whether it has begun a transaction.
Diffstat (limited to 'src/wallet/sqlite.h')
-rw-r--r-- | src/wallet/sqlite.h | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h index ad91be1064..0a3243fe19 100644 --- a/src/wallet/sqlite.h +++ b/src/wallet/sqlite.h @@ -58,6 +58,18 @@ private: sqlite3_stmt* m_delete_stmt{nullptr}; sqlite3_stmt* m_delete_prefix_stmt{nullptr}; + /** Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_semaphore. + * If the batch starts a db tx, it acquires the semaphore and sets this to true, keeping the semaphore + * until the transaction ends to prevent other batch objects from writing to the database. + * + * If this batch did not start a transaction, the semaphore is acquired transiently when writing and m_txn + * is not set. + * + * m_txn is different from HasActiveTxn() as it is only true when this batch has started the transaction, + * not just when any batch has started a transaction. + */ + bool m_txn{false}; + void SetupSQLStatements(); bool ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob); @@ -115,6 +127,10 @@ public: ~SQLiteDatabase(); + // Batches must acquire this semaphore on writing, and release when done writing. + // This ensures that only one batch is modifying the database at a time. + CSemaphore m_write_semaphore; + bool Verify(bilingual_str& error); /** Open the database if it is not already opened */ |