diff --git a/ext/lmdb-safe/lmdb-safe.hh b/ext/lmdb-safe/lmdb-safe.hh index 1c62d8802964..4370fb31b703 100644 --- a/ext/lmdb-safe/lmdb-safe.hh +++ b/ext/lmdb-safe/lmdb-safe.hh @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "config.h" @@ -24,6 +26,13 @@ #endif using std::string_view; +using std::string; + +#if BOOST_VERSION >= 106100 +#define StringView string_view +#else +#define StringView string +#endif /* open issues: * @@ -300,6 +309,9 @@ public: return ret; } + template + T get() const; + operator MDB_val&() { return d_mdbval; @@ -312,6 +324,12 @@ private: #endif }; +template <> +inline std::string MDBInVal::get() const +{ + return {static_cast(d_mdbval.mv_data), d_mdbval.mv_size}; +} + class MDBROCursor; class MDBROTransactionImpl @@ -415,6 +433,7 @@ class MDBGenCursor private: std::vector *d_registry; MDB_cursor* d_cursor{nullptr}; + std::string d_prefix{""}; public: MDB_txn* d_txn{nullptr}; // ew, public uint64_t d_txtime{0}; @@ -523,6 +542,9 @@ private: while (true) { auto sval = data.getNoStripHeader(); + if (d_prefix.length() > 0 && key.getNoStripHeader().rfind(d_prefix, 0) != 0) { + return MDB_NOTFOUND; + } if (!LMDBLS::LSisDeleted(sval)) { // done! @@ -573,6 +595,7 @@ private: public: int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) { + d_prefix.clear(); int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op); if(rc && rc != MDB_NOTFOUND) throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc))); @@ -581,6 +604,7 @@ public: int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) { + d_prefix.clear(); key.d_mdbval = in.d_mdbval; int rc=mdb_cursor_get(d_cursor, const_cast(&key.d_mdbval), &data.d_mdbval, MDB_SET); if(rc && rc != MDB_NOTFOUND) @@ -588,7 +612,19 @@ public: return skipDeleted(key, data, MDB_SET, rc); } + int prefix(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) + { + d_prefix = in.get(); + return _lower_bound(in, key, data); + } + int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) + { + d_prefix.clear(); + return _lower_bound(in, key, data); + } + + int _lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) // used by prefix() and lower_bound() { key.d_mdbval = in.d_mdbval; diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index 2997e9911202..1806b0b001f5 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -1405,10 +1405,7 @@ bool LMDBBackend::list(const DNSName& target, int /* id */, bool include_disable d_matchkey = co(di.id); MDBOutVal key, val; - auto a = d_getcursor->lower_bound(d_matchkey, key, val); - auto b0 = key.getNoStripHeader(); - auto b = b0.rfind(d_matchkey, 0); - if (a || b != 0) { + if (d_getcursor->prefix(d_matchkey, key, val) != 0) { d_getcursor.reset(); } @@ -1470,7 +1467,7 @@ void LMDBBackend::lookup(const QType& type, const DNSName& qdomain, int zoneId, d_matchkey = co(zoneId, relqname, type.getCode()); } - if (d_getcursor->lower_bound(d_matchkey, key, val) || key.getNoStripHeader().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->prefix(d_matchkey, key, val) != 0) { d_getcursor.reset(); if (d_dolog) { g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute (found nothing)" << endl; @@ -1508,7 +1505,7 @@ bool LMDBBackend::get(DNSZoneRecord& zr) if (zr.dr.d_type == QType::NSEC3) { // Hit a magic NSEC3 skipping - if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) != 0) { // cerr<<"resetting d_getcursor 1"<= d_currentrrset.size()) { d_currentrrset.clear(); // will invalidate lrr - if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) != 0) { // cerr<<"resetting d_getcursor 2"<txn->getCursor(txn->db->dbi); MDBOutVal key, val; - if (cursor.lower_bound(matchkey, key, val)) { + if (cursor.prefix(matchkey, key, val) != 0) { // cout << "Could not find anything"<().rfind(matchkey, 0) == 0;) { + do { vector lrrs; if (co.getQType(key.getNoStripHeader()) != QType::NSEC3) { @@ -2456,9 +2453,7 @@ bool LMDBBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName } } - if (cursor.next(key, val)) - break; - } + } while (cursor.next(key, val) == 0); bool del = false; LMDBResourceRecord lrr;