From c0c94ec9860ac121e342e6c2102ffaf30630c244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Wed, 14 Jan 2026 23:48:48 +0100 Subject: [PATCH] dbwrapper: have `Read` and `Exists` reuse `ReadRaw` `ExistsImpl` was removed since it duplicates `CDBWrapper::ReadImpl`. The only difference is that `ExistsImpl` discards the value while `ReadImpl` returns it as `std::string`. In this series, `HaveCoin` database lookups go through `GetCoin`/`Read`, and successful reads are cached in `CCoinsViewCache`, so this copy is not a separate recurring cost. `CDBWrapper::Exists()` and `::ReadRaw()` both issue a LevelDB `::Get`. Introduce a small helper returning the raw value bytes (as `std::string`) for a given key. Move `Exists` closer to the read methods. --- src/dbwrapper.cpp | 15 --------------- src/dbwrapper.h | 28 +++++++++++++++------------- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index eb222078b5e..d9fa63badef 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -316,21 +316,6 @@ std::optional CDBWrapper::ReadImpl(std::span key) return strValue; } -bool CDBWrapper::ExistsImpl(std::span key) const -{ - leveldb::Slice slKey(CharCast(key.data()), key.size()); - - std::string strValue; - leveldb::Status status = DBContext().pdb->Get(DBContext().readoptions, slKey, &strValue); - if (!status.ok()) { - if (status.IsNotFound()) - return false; - LogError("LevelDB read failure: %s", status.ToString()); - HandleError(status); - } - return true; -} - size_t CDBWrapper::EstimateSizeImpl(std::span key1, std::span key2) const { leveldb::Slice slKey1(CharCast(key1.data()), key1.size()); diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 2eee6c1c023..b89a099b58f 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -192,7 +192,6 @@ private: inline static const std::string OBFUSCATION_KEY{"\000obfuscate_key", 14}; // explicit size to avoid truncation at leading \0 std::optional ReadImpl(std::span key) const; - bool ExistsImpl(std::span key) const; size_t EstimateSizeImpl(std::span key1, std::span key2) const; auto& DBContext() const LIFETIMEBOUND { return *Assert(m_db_context); } @@ -203,13 +202,19 @@ public: CDBWrapper(const CDBWrapper&) = delete; CDBWrapper& operator=(const CDBWrapper&) = delete; - template - bool Read(const K& key, V& value) const + template + std::optional ReadRaw(const K& key) const { DataStream ssKey{}; ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); ssKey << key; - std::optional strValue{ReadImpl(ssKey)}; + return ReadImpl(ssKey); + } + + template + bool Read(const K& key, V& value) const + { + auto strValue{ReadRaw(key)}; if (!strValue) { return false; } @@ -223,6 +228,12 @@ public: return true; } + template + bool Exists(const K& key) const + { + return !!ReadRaw(key); + } + template void Write(const K& key, const V& value, bool fSync = false) { @@ -231,15 +242,6 @@ public: WriteBatch(batch, fSync); } - template - bool Exists(const K& key) const - { - DataStream ssKey{}; - ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE); - ssKey << key; - return ExistsImpl(ssKey); - } - template void Erase(const K& key, bool fSync = false) {