0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-09 10:43:19 -05:00

db: Change DatabaseCursor::Next to return status enum

Next()'s result is a tri-state - failed, more to go, complete. Replace
the way that this is returned with an enum with values FAIL, MORE, and
DONE rather than with two booleans.
This commit is contained in:
Andrew Chow 2022-11-29 22:34:26 -05:00
parent d79e8dcf29
commit 4aebd832a4
11 changed files with 49 additions and 55 deletions

View file

@ -481,11 +481,10 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
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; DatabaseCursor::Status ret1 = cursor->Next(ssKey, ssValue);
bool ret1 = cursor->Next(ssKey, ssValue, complete); if (ret1 == DatabaseCursor::Status::DONE) {
if (complete) {
break; break;
} else if (!ret1) { } else if (ret1 == DatabaseCursor::Status::FAIL) {
fSuccess = false; fSuccess = false;
break; break;
} }
@ -668,21 +667,19 @@ BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database)
} }
} }
bool BerkeleyCursor::Next(CDataStream& ssKey, CDataStream& ssValue, bool& complete) DatabaseCursor::Status BerkeleyCursor::Next(CDataStream& ssKey, CDataStream& ssValue)
{ {
complete = false; if (m_cursor == nullptr) return Status::FAIL;
if (m_cursor == nullptr) return false;
// Read at cursor // Read at cursor
SafeDbt datKey; SafeDbt datKey;
SafeDbt datValue; SafeDbt datValue;
int ret = m_cursor->get(datKey, datValue, DB_NEXT); int ret = m_cursor->get(datKey, datValue, DB_NEXT);
if (ret == DB_NOTFOUND) { if (ret == DB_NOTFOUND) {
complete = true; return Status::DONE;
}
if (ret != 0 || datKey.get_data() == nullptr || datValue.get_data() == nullptr) {
return Status::FAIL;
} }
if (ret != 0)
return false;
else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr)
return false;
// Convert to streams // Convert to streams
ssKey.SetType(SER_DISK); ssKey.SetType(SER_DISK);
@ -691,7 +688,7 @@ bool BerkeleyCursor::Next(CDataStream& ssKey, CDataStream& ssValue, bool& comple
ssValue.SetType(SER_DISK); ssValue.SetType(SER_DISK);
ssValue.clear(); ssValue.clear();
ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()}); ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
return true; return Status::MORE;
} }
BerkeleyCursor::~BerkeleyCursor() BerkeleyCursor::~BerkeleyCursor()

View file

@ -194,7 +194,7 @@ public:
explicit BerkeleyCursor(BerkeleyDatabase& database); explicit BerkeleyCursor(BerkeleyDatabase& database);
~BerkeleyCursor() override; ~BerkeleyCursor() override;
bool Next(CDataStream& key, CDataStream& value, bool& complete) override; Status Next(CDataStream& key, CDataStream& value) override;
}; };
/** RAII class that provides access to a Berkeley database */ /** RAII class that provides access to a Berkeley database */

View file

@ -31,7 +31,14 @@ public:
DatabaseCursor(const DatabaseCursor&) = delete; DatabaseCursor(const DatabaseCursor&) = delete;
DatabaseCursor& operator=(const DatabaseCursor&) = delete; DatabaseCursor& operator=(const DatabaseCursor&) = delete;
virtual bool Next(CDataStream& key, CDataStream& value, bool& complete) { return false; } enum class Status
{
FAIL,
MORE,
DONE,
};
virtual Status Next(CDataStream& key, CDataStream& value) { return Status::FAIL; }
}; };
/** RAII class that provides access to a WalletDatabase */ /** RAII class that provides access to a WalletDatabase */
@ -168,7 +175,7 @@ public:
class DummyCursor : public DatabaseCursor class DummyCursor : public DatabaseCursor
{ {
bool Next(CDataStream& key, CDataStream& value, bool& complete) override { return false; } Status Next(CDataStream& key, CDataStream& value) override { return Status::FAIL; }
}; };
/** RAII class that provides access to a DummyDatabase. Never fails. */ /** RAII class that provides access to a DummyDatabase. Never fails. */

View file

@ -69,13 +69,13 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, 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 complete; DatabaseCursor::Status status = cursor->Next(ss_key, ss_value);
ret = cursor->Next(ss_key, ss_value, complete); if (status == DatabaseCursor::Status::DONE) {
if (complete) {
ret = true; ret = true;
break; break;
} else if (!ret) { } else if (status == DatabaseCursor::Status::FAIL) {
error = _("Error reading next record from wallet database"); error = _("Error reading next record from wallet database");
ret = false;
break; break;
} }
std::string key_str = HexStr(ss_key); std::string key_str = HexStr(ss_key);

View file

@ -470,18 +470,15 @@ bool SQLiteBatch::HasKey(CDataStream&& key)
return res == SQLITE_ROW; return res == SQLITE_ROW;
} }
bool SQLiteCursor::Next(CDataStream& key, CDataStream& value, bool& complete) DatabaseCursor::Status SQLiteCursor::Next(CDataStream& key, CDataStream& value)
{ {
complete = false;
int res = sqlite3_step(m_cursor_stmt); int res = sqlite3_step(m_cursor_stmt);
if (res == SQLITE_DONE) { if (res == SQLITE_DONE) {
complete = true; return Status::DONE;
return true;
} }
if (res != SQLITE_ROW) { if (res != SQLITE_ROW) {
LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res)); LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
return false; return Status::FAIL;
} }
// Leftmost column in result is index 0 // Leftmost column in result is index 0
@ -491,7 +488,7 @@ bool SQLiteCursor::Next(CDataStream& key, CDataStream& value, bool& complete)
const std::byte* value_data{AsBytePtr(sqlite3_column_blob(m_cursor_stmt, 1))}; const std::byte* value_data{AsBytePtr(sqlite3_column_blob(m_cursor_stmt, 1))};
size_t value_data_size(sqlite3_column_bytes(m_cursor_stmt, 1)); size_t value_data_size(sqlite3_column_bytes(m_cursor_stmt, 1));
value.write({value_data, value_data_size}); value.write({value_data, value_data_size});
return true; return Status::MORE;
} }
SQLiteCursor::~SQLiteCursor() SQLiteCursor::~SQLiteCursor()

View file

@ -22,7 +22,7 @@ public:
explicit SQLiteCursor() {} explicit SQLiteCursor() {}
~SQLiteCursor() override; ~SQLiteCursor() override;
bool Next(CDataStream& key, CDataStream& value, bool& complete) override; Status Next(CDataStream& key, CDataStream& value) override;
}; };
/** RAII class that provides access to a WalletDatabase */ /** RAII class that provides access to a WalletDatabase */

View file

@ -59,9 +59,9 @@ std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database,
while (true) { while (true) {
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; DatabaseCursor::Status status = cursor->Next(key, value);
cursor->Next(key, value, complete); assert(status != DatabaseCursor::Status::FAIL);
if (complete) break; if (status == DatabaseCursor::Status::DONE) break;
new_batch->Write(key, value); new_batch->Write(key, value);
} }

View file

@ -870,7 +870,7 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
class FailCursor : public DatabaseCursor class FailCursor : public DatabaseCursor
{ {
public: public:
bool Next(CDataStream& key, CDataStream& value, bool& complete) override { return false; } Status Next(CDataStream& key, CDataStream& value) override { return Status::FAIL; }
}; };
/** RAII class that provides access to a FailDatabase. Which fails if needed. */ /** RAII class that provides access to a FailDatabase. Which fails if needed. */

View file

@ -60,9 +60,9 @@ bool HasAnyRecordOfType(WalletDatabase& db, const std::string& key)
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; DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
BOOST_CHECK(cursor->Next(ssKey, ssValue, complete)); assert(status != DatabaseCursor::Status::FAIL);
if (complete) break; if (status == DatabaseCursor::Status::DONE) break;
std::string type; std::string type;
ssKey >> type; ssKey >> type;
if (type == key) return true; if (type == key) return true;

View file

@ -3776,12 +3776,12 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
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;
} }
bool complete = false; DatabaseCursor::Status status = DatabaseCursor::Status::FAIL;
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 = cursor->Next(ss_key, ss_value, complete); status = cursor->Next(ss_key, ss_value);
if (complete || !ret) { if (status != DatabaseCursor::Status::MORE) {
break; break;
} }
SerializeData key(ss_key.begin(), ss_key.end()); SerializeData key(ss_key.begin(), ss_key.end());
@ -3790,7 +3790,7 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)
} }
cursor.reset(); cursor.reset();
batch.reset(); batch.reset();
if (!complete) { if (status != DatabaseCursor::Status::DONE) {
error = _("Error: Unable to read all records in the database"); error = _("Error: Unable to read all records in the database");
return false; return false;
} }

View file

@ -824,13 +824,10 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
// Read next record // Read next record
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; DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
bool ret = cursor->Next(ssKey, ssValue, complete); if (status == DatabaseCursor::Status::DONE) {
if (complete) {
break; break;
} } else if (status == DatabaseCursor::Status::FAIL) {
else if (!ret)
{
cursor.reset(); 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;
@ -998,11 +995,10 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWal
// Read next record // Read next record
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; DatabaseCursor::Status status = cursor->Next(ssKey, ssValue);
bool ret = cursor->Next(ssKey, ssValue, complete); if (status == DatabaseCursor::Status::DONE) {
if (complete) {
break; break;
} else if (!ret) { } else if (status == DatabaseCursor::Status::FAIL) {
LogPrintf("Error reading next record from wallet database\n"); LogPrintf("Error reading next record from wallet database\n");
return DBErrors::CORRUPT; return DBErrors::CORRUPT;
} }
@ -1125,13 +1121,10 @@ bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
// Read next record // Read next record
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; DatabaseCursor::Status status = cursor->Next(key, value);
bool ret = cursor->Next(key, value, complete); if (status == DatabaseCursor::Status::DONE) {
if (complete) {
break; break;
} } else if (status == DatabaseCursor::Status::FAIL) {
else if (!ret)
{
return false; return false;
} }