diff options
author | Ryan Ofsky <ryan@ofsky.org> | 2020-04-12 13:40:43 -0400 |
---|---|---|
committer | Ryan Ofsky <ryan@ofsky.org> | 2023-04-12 05:30:43 -0400 |
commit | 5938ad0bdb013953861c7cd15a95f00998a06f44 (patch) | |
tree | 5c760ab363b8c3ee305f1762766af2007cd65b00 /src/wallet/bdb.cpp | |
parent | cae0608ad4b195652e0cfcc905e19b50197d43ab (diff) | |
download | bitcoin-5938ad0bdb013953861c7cd15a95f00998a06f44.tar.xz |
wallet: Add DatabaseBatch::ErasePrefix method
This new function is not used yet this commit, but next commit adds usages and
test coverage for both BDB and sqlite.
Diffstat (limited to 'src/wallet/bdb.cpp')
-rw-r--r-- | src/wallet/bdb.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp index dd425c1160..6daf0f47a5 100644 --- a/src/wallet/bdb.cpp +++ b/src/wallet/bdb.cpp @@ -665,12 +665,14 @@ void BerkeleyDatabase::ReloadDbEnv() env->ReloadDbEnv(); } -BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database) +BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, BerkeleyBatch* batch) { if (!database.m_db.get()) { throw std::runtime_error(STR_INTERNAL_BUG("BerkeleyDatabase does not exist")); } - int ret = database.m_db->cursor(nullptr, &m_cursor, 0); + // Transaction argument to cursor is only needed when using the cursor to + // write to the database. Read-only cursors do not need a txn pointer. + int ret = database.m_db->cursor(batch ? batch->txn() : nullptr, &m_cursor, 0); if (ret != 0) { throw std::runtime_error(STR_INTERNAL_BUG(strprintf("BDB Cursor could not be created. Returned %d", ret))); } @@ -817,6 +819,25 @@ bool BerkeleyBatch::HasKey(DataStream&& key) return ret == 0; } +bool BerkeleyBatch::ErasePrefix(Span<const std::byte> prefix) +{ + if (!TxnBegin()) return false; + auto cursor{std::make_unique<BerkeleyCursor>(m_database, this)}; + // const_cast is safe below even though prefix_key is an in/out parameter, + // because we are not using the DB_DBT_USERMEM flag, so BDB will allocate + // and return a different output data pointer + Dbt prefix_key{const_cast<std::byte*>(prefix.data()), static_cast<uint32_t>(prefix.size())}, prefix_value{}; + int ret{cursor->dbc()->get(&prefix_key, &prefix_value, DB_SET_RANGE)}; + for (int flag{DB_CURRENT}; ret == 0; flag = DB_NEXT) { + SafeDbt key, value; + ret = cursor->dbc()->get(key, value, flag); + if (ret != 0 || key.get_size() < prefix.size() || memcmp(key.get_data(), prefix.data(), prefix.size()) != 0) break; + ret = cursor->dbc()->del(0); + } + cursor.reset(); + return TxnCommit() && (ret == 0 || ret == DB_NOTFOUND); +} + void BerkeleyDatabase::AddRef() { LOCK(cs_db); |