wallet: db, introduce 'RunWithinTxn()' helper function

'RunWithinTxn()' provides a way to execute db operations within a
transactional context. It avoids writing repetitive boilerplate code for
starting and committing the database transaction.
This commit is contained in:
furszy 2024-02-08 12:34:26 -03:00
parent 6ff0aa089c
commit cf4d72a75e
No known key found for this signature in database
GPG key ID: 5DD23CCC686AA623
3 changed files with 41 additions and 2 deletions

View file

@ -2411,8 +2411,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s
bool CWallet::DelAddressBook(const CTxDestination& address)
{
WalletBatch batch(GetDatabase());
return DelAddressBookWithDB(batch, address);
return RunWithinTxn(GetDatabase(), /*process_desc=*/"address book entry removal", [&](WalletBatch& batch){
return DelAddressBookWithDB(batch, address);
});
}
bool CWallet::DelAddressBookWithDB(WalletBatch& batch, const CTxDestination& address)

View file

@ -1230,6 +1230,30 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
return result;
}
bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func)
{
WalletBatch batch(database);
if (!batch.TxnBegin()) {
LogPrint(BCLog::WALLETDB, "Error: cannot create db txn for %s\n", process_desc);
return false;
}
// Run procedure
if (!func(batch)) {
LogPrint(BCLog::WALLETDB, "Error: %s failed\n", process_desc);
batch.TxnAbort();
return false;
}
if (!batch.TxnCommit()) {
LogPrint(BCLog::WALLETDB, "Error: cannot commit db txn for %s\n", process_desc);
return false;
}
// All good
return true;
}
void MaybeCompactWalletDB(WalletContext& context)
{
static std::atomic<bool> fOneThread(false);

View file

@ -294,6 +294,20 @@ private:
WalletDatabase& m_database;
};
/**
* Executes the provided function 'func' within a database transaction context.
*
* This function ensures that all db modifications performed within 'func()' are
* atomically committed to the db at the end of the process. And, in case of a
* failure during execution, all performed changes are rolled back.
*
* @param database The db connection instance to perform the transaction on.
* @param process_desc A description of the process being executed, used for logging purposes in the event of a failure.
* @param func The function to be executed within the db txn context. It returns a boolean indicating whether to commit or roll back the txn.
* @return true if the db txn executed successfully, false otherwise.
*/
bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func);
//! Compacts BDB state so that wallet.dat is self-contained (if there are changes)
void MaybeCompactWalletDB(WalletContext& context);