aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/sqlite.h
diff options
context:
space:
mode:
authorAva Chow <github@achow101.com>2023-12-18 17:06:04 -0500
committerAva Chow <github@achow101.com>2024-02-06 12:24:36 -0500
commit395bcd245476d7c83abf2d82e31e90b6d0c432f3 (patch)
tree0ff1b94cd7319a1eb4eb8d22055a5b14be9d32e2 /src/wallet/sqlite.h
parent6f7395b3ff21228183df190f3ed1bdc3049f39e2 (diff)
downloadbitcoin-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.h16
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 */