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 TxnBegin() override;
bool TxnCommit() override; bool TxnCommit() override;
bool TxnAbort() override; bool TxnAbort() override;
bool HasActiveTxn() override { return activeTxn != nullptr; }
DbTxn* txn() const { return activeTxn; } DbTxn* txn() const { return activeTxn; }
}; };

View file

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

View file

@ -115,6 +115,7 @@ public:
bool TxnBegin() override { return false; } bool TxnBegin() override { return false; }
bool TxnCommit() override { return false; } bool TxnCommit() override { return false; }
bool TxnAbort() 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. //! 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 TxnBegin() override { return true; }
bool TxnCommit() override { return true; } bool TxnCommit() override { return true; }
bool TxnAbort() 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. /** A dummy WalletDatabase that does nothing and never fails. Only used by salvage.

View file

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

View file

@ -95,6 +95,7 @@ public:
bool TxnBegin() override { return m_pass; } bool TxnBegin() override { return m_pass; }
bool TxnCommit() override { return m_pass; } bool TxnCommit() override { return m_pass; }
bool TxnAbort() 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 /** 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() 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() 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) 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. /** Access to the wallet database.
* Opens the database and provides read and write access to it. Each read and write is its own transaction. * 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() * Multiple operation transactions can be started using TxnBegin() and committed using TxnCommit()
@ -292,9 +297,18 @@ public:
bool TxnCommit(); bool TxnCommit();
//! Abort current transaction //! Abort current transaction
bool TxnAbort(); bool TxnAbort();
bool HasActiveTxn() { return m_batch->HasActiveTxn(); }
//! Registers db txn callback functions
void RegisterTxnListener(const DbTxnListener& l);
private: private:
std::unique_ptr<DatabaseBatch> m_batch; std::unique_ptr<DatabaseBatch> m_batch;
WalletDatabase& m_database; 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;
}; };
/** /**