aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/bdb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/bdb.cpp')
-rw-r--r--src/wallet/bdb.cpp26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index 7a1916ddc3..68abdcd81e 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -668,7 +668,8 @@ void BerkeleyDatabase::ReloadDbEnv()
env->ReloadDbEnv();
}
-BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch)
+BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch, Span<const std::byte> prefix)
+ : m_key_prefix(prefix.begin(), prefix.end())
{
if (!database.m_db.get()) {
throw std::runtime_error(STR_INTERNAL_BUG("BerkeleyDatabase does not exist"));
@@ -685,9 +686,15 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
{
if (m_cursor == nullptr) return Status::FAIL;
// Read at cursor
- SafeDbt datKey;
+ SafeDbt datKey(m_key_prefix.data(), m_key_prefix.size());
SafeDbt datValue;
- int ret = m_cursor->get(datKey, datValue, DB_NEXT);
+ int ret = -1;
+ if (m_first && !m_key_prefix.empty()) {
+ ret = m_cursor->get(datKey, datValue, DB_SET_RANGE);
+ } else {
+ ret = m_cursor->get(datKey, datValue, DB_NEXT);
+ }
+ m_first = false;
if (ret == DB_NOTFOUND) {
return Status::DONE;
}
@@ -695,9 +702,14 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
return Status::FAIL;
}
+ Span<const std::byte> raw_key = {AsBytePtr(datKey.get_data()), datKey.get_size()};
+ if (!m_key_prefix.empty() && std::mismatch(raw_key.begin(), raw_key.end(), m_key_prefix.begin(), m_key_prefix.end()).second != m_key_prefix.end()) {
+ return Status::DONE;
+ }
+
// Convert to streams
ssKey.clear();
- ssKey.write({AsBytePtr(datKey.get_data()), datKey.get_size()});
+ ssKey.write(raw_key);
ssValue.clear();
ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
return Status::MORE;
@@ -716,6 +728,12 @@ std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewCursor()
return std::make_unique<BerkeleyCursor>(m_database, *this);
}
+std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewPrefixCursor(Span<const std::byte> prefix)
+{
+ if (!pdb) return nullptr;
+ return std::make_unique<BerkeleyCursor>(m_database, *this, prefix);
+}
+
bool BerkeleyBatch::TxnBegin()
{
if (!pdb || activeTxn)