wallet: introduce active db txn listeners

Useful to ensure that the in-memory state is updated only
after successfully committing the data to disk.
This commit is contained in:
furszy 2024-03-26 10:48:30 -03:00
parent 91e065ec17
commit 57249ff669
No known key found for this signature in database
GPG key ID: 5DD23CCC686AA623
8 changed files with 44 additions and 2 deletions

View file

@ -208,6 +208,7 @@ public:
bool TxnBegin() override;
bool TxnCommit() override;
bool TxnAbort() override;
bool HasActiveTxn() override { return activeTxn != nullptr; }
DbTxn* txn() const { return activeTxn; }
};

View file

@ -122,6 +122,7 @@ public:
virtual bool TxnBegin() = 0;
virtual bool TxnCommit() = 0;
virtual bool TxnAbort() = 0;
virtual bool HasActiveTxn() = 0;
};
/** An instance of this class represents one database.

View file

@ -115,6 +115,7 @@ public:
bool TxnBegin() override { return false; }
bool TxnCommit() override { return false; }
bool TxnAbort() override { return false; }
bool HasActiveTxn() override { return false; }
};
//! Return object giving access to Berkeley Read Only database at specified path.

View file

@ -44,6 +44,7 @@ public:
bool TxnBegin() override { return true; }
bool TxnCommit() override { return true; }
bool TxnAbort() override { return true; }
bool HasActiveTxn() override { return false; }
};
/** A dummy WalletDatabase that does nothing and never fails. Only used by salvage.

View file

@ -95,6 +95,7 @@ public:
bool TxnBegin() override;
bool TxnCommit() override;
bool TxnAbort() override;
bool HasActiveTxn() override { return m_txn; }
};
/** An instance of this class represents one SQLite3 database.

View file

@ -95,6 +95,7 @@ public:
bool TxnBegin() override { return m_pass; }
bool TxnCommit() override { return m_pass; }
bool TxnAbort() override { return m_pass; }
bool HasActiveTxn() override { return false; }
};
/** A WalletDatabase whose contents and return values can be modified as needed for testing

View file

@ -1347,12 +1347,34 @@ bool WalletBatch::TxnBegin()
bool WalletBatch::TxnCommit()
{
return m_batch->TxnCommit();
bool res = m_batch->TxnCommit();
if (res) {
for (const auto& listener : m_txn_listeners) {
listener.on_commit();
}
// txn finished, clear listeners
m_txn_listeners.clear();
}
return res;
}
bool WalletBatch::TxnAbort()
{
return m_batch->TxnAbort();
bool res = m_batch->TxnAbort();
if (res) {
for (const auto& listener : m_txn_listeners) {
listener.on_abort();
}
// txn finished, clear listeners
m_txn_listeners.clear();
}
return res;
}
void WalletBatch::RegisterTxnListener(const DbTxnListener& l)
{
assert(m_batch->HasActiveTxn());
m_txn_listeners.emplace_back(l);
}
std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)

View file

@ -180,6 +180,11 @@ public:
}
};
struct DbTxnListener
{
std::function<void()> on_commit, on_abort;
};
/** Access to the wallet database.
* Opens the database and provides read and write access to it. Each read and write is its own transaction.
* Multiple operation transactions can be started using TxnBegin() and committed using TxnCommit()
@ -292,9 +297,18 @@ public:
bool TxnCommit();
//! Abort current transaction
bool TxnAbort();
bool HasActiveTxn() { return m_batch->HasActiveTxn(); }
//! Registers db txn callback functions
void RegisterTxnListener(const DbTxnListener& l);
private:
std::unique_ptr<DatabaseBatch> m_batch;
WalletDatabase& m_database;
// External functions listening to the current db txn outcome.
// Listeners are cleared at the end of the transaction.
std::vector<DbTxnListener> m_txn_listeners;
};
/**