#include <mutex>
#include <vector>
#include <algorithm>
+#include <string>
+#include <string_view>
#include <atomic>
#include <arpa/inet.h>
#endif
using std::string_view;
+using std::string;
+
+#if BOOST_VERSION >= 106100
+#define StringView string_view
+#else
+#define StringView string
+#endif
/* open issues:
*
return ret;
}
+ template <class T>
+ T get() const;
+
operator MDB_val&()
{
return d_mdbval;
#endif
};
+template <>
+inline std::string MDBInVal::get<std::string>() const
+{
+ return {static_cast<char*>(d_mdbval.mv_data), d_mdbval.mv_size};
+}
+
class MDBROCursor;
class MDBROTransactionImpl
private:
std::vector<T*> *d_registry;
MDB_cursor* d_cursor{nullptr};
+ std::string d_prefix{""};
public:
MDB_txn* d_txn{nullptr}; // ew, public
uint64_t d_txtime{0};
while (true) {
auto sval = data.getNoStripHeader<std::string_view>();
+ if (d_prefix.length() > 0 && key.getNoStripHeader<StringView>().rfind(d_prefix, 0) != 0) {
+ return MDB_NOTFOUND;
+ }
if (!LMDBLS::LSisDeleted(sval)) {
// done!
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)));
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<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET);
if(rc && rc != MDB_NOTFOUND)
return skipDeleted(key, data, MDB_SET, rc);
}
+ int prefix(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
+ {
+ d_prefix = in.get<string>();
+ 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;
d_matchkey = co(di.id);
MDBOutVal key, val;
- auto a = d_getcursor->lower_bound(d_matchkey, key, val);
+ auto a = d_getcursor->prefix(d_matchkey, key, val);
auto b0 = key.getNoStripHeader<StringView>();
auto b = b0.rfind(d_matchkey, 0);
if (a || b != 0) {
d_matchkey = co(zoneId, relqname, type.getCode());
}
- if (d_getcursor->lower_bound(d_matchkey, key, val) || key.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->prefix(d_matchkey, key, val)) {
d_getcursor.reset();
if (d_dolog) {
g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute (found nothing)" << endl;
if (zr.dr.d_type == QType::NSEC3) {
// Hit a magic NSEC3 skipping
- if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->next(d_currentKey, d_currentVal)) {
// cerr<<"resetting d_getcursor 1"<<endl;
d_getcursor.reset();
}
if (d_currentrrsetpos >= d_currentrrset.size()) {
d_currentrrset.clear(); // will invalidate lrr
- if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->next(d_currentKey, d_currentVal)) {
// cerr<<"resetting d_getcursor 2"<<endl;
d_getcursor.reset();
}