wallet: Have cursor users use DatabaseCursor directly

Instead of having the DatabaseBatch manage the cursor, having the
consumer handle it directly
This commit is contained in:
Andrew Chow 2022-04-11 16:07:58 -04:00 committed by Andrew Chow
parent 7a198bba0a
commit d79e8dcf29
7 changed files with 29 additions and 43 deletions

View File

@ -399,7 +399,6 @@ void BerkeleyBatch::Close()
activeTxn->abort(); activeTxn->abort();
activeTxn = nullptr; activeTxn = nullptr;
pdb = nullptr; pdb = nullptr;
CloseCursor();
if (fFlushOnClose) if (fFlushOnClose)
Flush(); Flush();
@ -477,12 +476,13 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
fSuccess = false; fSuccess = false;
} }
if (db.StartCursor()) { std::unique_ptr<DatabaseCursor> cursor = db.GetNewCursor();
if (cursor) {
while (fSuccess) { while (fSuccess) {
CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssKey(SER_DISK, CLIENT_VERSION);
CDataStream ssValue(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
bool ret1 = db.ReadAtCursor(ssKey, ssValue, complete); bool ret1 = cursor->Next(ssKey, ssValue, complete);
if (complete) { if (complete) {
break; break;
} else if (!ret1) { } else if (!ret1) {
@ -503,7 +503,7 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
if (ret2 > 0) if (ret2 > 0)
fSuccess = false; fSuccess = false;
} }
db.CloseCursor(); cursor.reset();
} }
if (fSuccess) { if (fSuccess) {
db.Close(); db.Close();

View File

@ -38,8 +38,6 @@ public:
class DatabaseBatch class DatabaseBatch
{ {
private: private:
std::unique_ptr<DatabaseCursor> m_cursor;
virtual bool ReadKey(CDataStream&& key, CDataStream& value) = 0; virtual bool ReadKey(CDataStream&& key, CDataStream& value) = 0;
virtual bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) = 0; virtual bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) = 0;
virtual bool EraseKey(CDataStream&& key) = 0; virtual bool EraseKey(CDataStream&& key) = 0;
@ -107,20 +105,6 @@ public:
} }
virtual std::unique_ptr<DatabaseCursor> GetNewCursor() = 0; virtual std::unique_ptr<DatabaseCursor> GetNewCursor() = 0;
bool StartCursor()
{
m_cursor = GetNewCursor();
return m_cursor != nullptr;
}
bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete)
{
if (!m_cursor) return false;
return m_cursor->Next(ssKey, ssValue, complete);
}
void CloseCursor()
{
m_cursor.reset();
}
virtual bool TxnBegin() = 0; virtual bool TxnBegin() = 0;
virtual bool TxnCommit() = 0; virtual bool TxnCommit() = 0;
virtual bool TxnAbort() = 0; virtual bool TxnAbort() = 0;

View File

@ -47,7 +47,8 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
std::unique_ptr<DatabaseBatch> batch = db.MakeBatch(); std::unique_ptr<DatabaseBatch> batch = db.MakeBatch();
bool ret = true; bool ret = true;
if (!batch->StartCursor()) { std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
if (!cursor) {
error = _("Error: Couldn't create cursor into database"); error = _("Error: Couldn't create cursor into database");
ret = false; ret = false;
} }
@ -69,7 +70,7 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
CDataStream ss_key(SER_DISK, CLIENT_VERSION); CDataStream ss_key(SER_DISK, CLIENT_VERSION);
CDataStream ss_value(SER_DISK, CLIENT_VERSION); CDataStream ss_value(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
ret = batch->ReadAtCursor(ss_key, ss_value, complete); ret = cursor->Next(ss_key, ss_value, complete);
if (complete) { if (complete) {
ret = true; ret = true;
break; break;
@ -85,7 +86,7 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
} }
} }
batch->CloseCursor(); cursor.reset();
batch.reset(); batch.reset();
// Close the wallet after we're done with it. The caller won't be doing this // Close the wallet after we're done with it. The caller won't be doing this

View File

@ -50,7 +50,7 @@ std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database,
// Get a cursor to the original database // Get a cursor to the original database
auto batch = database.MakeBatch(); auto batch = database.MakeBatch();
batch->StartCursor(); std::unique_ptr<wallet::DatabaseCursor> cursor = batch->GetNewCursor();
// Get a batch for the new database // Get a batch for the new database
auto new_batch = new_database->MakeBatch(); auto new_batch = new_database->MakeBatch();
@ -60,7 +60,7 @@ std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database,
CDataStream key(SER_DISK, CLIENT_VERSION); CDataStream key(SER_DISK, CLIENT_VERSION);
CDataStream value(SER_DISK, CLIENT_VERSION); CDataStream value(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
batch->ReadAtCursor(key, value, complete); cursor->Next(key, value, complete);
if (complete) break; if (complete) break;
new_batch->Write(key, value); new_batch->Write(key, value);
} }

View File

@ -54,12 +54,14 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_unknown_descriptor, TestingSetup)
bool HasAnyRecordOfType(WalletDatabase& db, const std::string& key) bool HasAnyRecordOfType(WalletDatabase& db, const std::string& key)
{ {
std::unique_ptr<DatabaseBatch> batch = db.MakeBatch(false); std::unique_ptr<DatabaseBatch> batch = db.MakeBatch(false);
BOOST_CHECK(batch->StartCursor()); BOOST_CHECK(batch);
std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
BOOST_CHECK(cursor);
while (true) { while (true) {
CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssKey(SER_DISK, CLIENT_VERSION);
CDataStream ssValue(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
BOOST_CHECK(batch->ReadAtCursor(ssKey, ssValue, complete)); BOOST_CHECK(cursor->Next(ssKey, ssValue, complete));
if (complete) break; if (complete) break;
std::string type; std::string type;
ssKey >> type; ssKey >> type;

View File

@ -3770,8 +3770,9 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
// Get all of the records for DB type migration // Get all of the records for DB type migration
std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch(); std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
std::unique_ptr<DatabaseCursor> cursor = batch->GetNewCursor();
std::vector<std::pair<SerializeData, SerializeData>> records; std::vector<std::pair<SerializeData, SerializeData>> records;
if (!batch->StartCursor()) { if (!cursor) {
error = _("Error: Unable to begin reading all records in the database"); error = _("Error: Unable to begin reading all records in the database");
return false; return false;
} }
@ -3779,15 +3780,15 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
while (true) { while (true) {
CDataStream ss_key(SER_DISK, CLIENT_VERSION); CDataStream ss_key(SER_DISK, CLIENT_VERSION);
CDataStream ss_value(SER_DISK, CLIENT_VERSION); CDataStream ss_value(SER_DISK, CLIENT_VERSION);
bool ret = batch->ReadAtCursor(ss_key, ss_value, complete); bool ret = cursor->Next(ss_key, ss_value, complete);
if (!ret) { if (complete || !ret) {
break; break;
} }
SerializeData key(ss_key.begin(), ss_key.end()); SerializeData key(ss_key.begin(), ss_key.end());
SerializeData value(ss_value.begin(), ss_value.end()); SerializeData value(ss_value.begin(), ss_value.end());
records.emplace_back(key, value); records.emplace_back(key, value);
} }
batch->CloseCursor(); cursor.reset();
batch.reset(); batch.reset();
if (!complete) { if (!complete) {
error = _("Error: Unable to read all records in the database"); error = _("Error: Unable to read all records in the database");

View File

@ -812,7 +812,8 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
#endif #endif
// Get cursor // Get cursor
if (!m_batch->StartCursor()) std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
if (!cursor)
{ {
pwallet->WalletLogPrintf("Error getting wallet database cursor\n"); pwallet->WalletLogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT; return DBErrors::CORRUPT;
@ -824,13 +825,13 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssKey(SER_DISK, CLIENT_VERSION);
CDataStream ssValue(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete); bool ret = cursor->Next(ssKey, ssValue, complete);
if (complete) { if (complete) {
break; break;
} }
else if (!ret) else if (!ret)
{ {
m_batch->CloseCursor(); cursor.reset();
pwallet->WalletLogPrintf("Error reading next record from wallet database\n"); pwallet->WalletLogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT; return DBErrors::CORRUPT;
} }
@ -878,7 +879,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
} catch (...) { } catch (...) {
result = DBErrors::CORRUPT; result = DBErrors::CORRUPT;
} }
m_batch->CloseCursor();
// Set the active ScriptPubKeyMans // Set the active ScriptPubKeyMans
for (auto spk_man_pair : wss.m_active_external_spks) { for (auto spk_man_pair : wss.m_active_external_spks) {
@ -986,7 +986,8 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
} }
// Get cursor // Get cursor
if (!m_batch->StartCursor()) std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
if (!cursor)
{ {
LogPrintf("Error getting wallet database cursor\n"); LogPrintf("Error getting wallet database cursor\n");
return DBErrors::CORRUPT; return DBErrors::CORRUPT;
@ -998,11 +999,10 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssKey(SER_DISK, CLIENT_VERSION);
CDataStream ssValue(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
bool ret = m_batch->ReadAtCursor(ssKey, ssValue, complete); bool ret = cursor->Next(ssKey, ssValue, complete);
if (complete) { if (complete) {
break; break;
} else if (!ret) { } else if (!ret) {
m_batch->CloseCursor();
LogPrintf("Error reading next record from wallet database\n"); LogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT; return DBErrors::CORRUPT;
} }
@ -1020,7 +1020,6 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
} catch (...) { } catch (...) {
result = DBErrors::CORRUPT; result = DBErrors::CORRUPT;
} }
m_batch->CloseCursor();
return result; return result;
} }
@ -1114,7 +1113,8 @@ bool WalletBatch::WriteWalletFlags(const uint64_t flags)
bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types) bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
{ {
// Get cursor // Get cursor
if (!m_batch->StartCursor()) std::unique_ptr<DatabaseCursor> cursor = m_batch->GetNewCursor();
if (!cursor)
{ {
return false; return false;
} }
@ -1126,13 +1126,12 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
CDataStream key(SER_DISK, CLIENT_VERSION); CDataStream key(SER_DISK, CLIENT_VERSION);
CDataStream value(SER_DISK, CLIENT_VERSION); CDataStream value(SER_DISK, CLIENT_VERSION);
bool complete; bool complete;
bool ret = m_batch->ReadAtCursor(key, value, complete); bool ret = cursor->Next(key, value, complete);
if (complete) { if (complete) {
break; break;
} }
else if (!ret) else if (!ret)
{ {
m_batch->CloseCursor();
return false; return false;
} }
@ -1146,7 +1145,6 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
m_batch->Erase(key_data); m_batch->Erase(key_data);
} }
} }
m_batch->CloseCursor();
return true; return true;
} }