walletdb: scope bdb::EraseRecords under a single db txn

so we erase all the records atomically or abort the entire
procedure.

and, at the same time, we can share the same db txn context
for the db cursor and the erase functionality.

extra note from the Db.cursor doc:
"If transaction protection is enabled, cursors must be
opened and closed within the context of a transaction"

thus why added a `CloseCursor` call before calling to
`TxnAbort/TxnCommit`.
This commit is contained in:
furszy 2022-12-05 18:04:56 -03:00
parent 043fcb0b05
commit 12daf6fcdc
No known key found for this signature in database
GPG key ID: 5DD23CCC686AA623

View file

@ -1136,6 +1136,9 @@ bool WalletBatch::WriteWalletFlags(const uint64_t flags)
bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
{
// Begin db txn
if (!m_batch->TxnBegin()) return false;
// Get cursor
std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
if (!cursor)
@ -1144,8 +1147,7 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
}
// Iterate the DB and look for any records that have the type prefixes
while (true)
{
while (true) {
// Read next record
DataStream key{};
DataStream value{};
@ -1153,6 +1155,8 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
if (status == DatabaseCursor::Status::DONE) {
break;
} else if (status == DatabaseCursor::Status::FAIL) {
cursor.reset(nullptr);
m_batch->TxnAbort(); // abort db txn
return false;
}
@ -1163,10 +1167,16 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
key >> type;
if (types.count(type) > 0) {
m_batch->Erase(key_data);
if (!m_batch->Erase(key_data)) {
cursor.reset(nullptr);
m_batch->TxnAbort();
return false; // erase failed
}
}
}
return true;
// Finish db txn
cursor.reset(nullptr);
return m_batch->TxnCommit();
}
bool WalletBatch::TxnBegin()