add compound keys and iterator--
This commit is contained in:
parent
29aaa63a69
commit
bb981d6d31
|
@ -39,13 +39,23 @@ void serialize(Archive & ar, DNSResourceRecord& g, const unsigned int version)
|
|||
}
|
||||
|
||||
|
||||
struct compound
|
||||
{
|
||||
std::string operator()(const DNSResourceRecord& rr)
|
||||
{
|
||||
std::string ret;
|
||||
ret.assign((char*)&rr.domain_id, 4);
|
||||
ret.append(rr.ordername);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
TypedDBI<DNSResourceRecord,
|
||||
index_on<DNSResourceRecord, string, &DNSResourceRecord::qname>,
|
||||
index_on<DNSResourceRecord, uint32_t, &DNSResourceRecord::domain_id>,
|
||||
index_on<DNSResourceRecord, string, &DNSResourceRecord::ordername>,
|
||||
index_on<DNSResourceRecord, bool, &DNSResourceRecord::auth>
|
||||
index_on_function<DNSResourceRecord, string, compound>
|
||||
> tdbi(getMDBEnv("./typed.lmdb", MDB_NOSUBDIR, 0600), "records");
|
||||
|
||||
{
|
||||
|
@ -57,17 +67,17 @@ int main()
|
|||
else {
|
||||
cout <<"Did not find id 2" << endl;
|
||||
}
|
||||
cout<<"Iterating: "<<endl;
|
||||
for(auto iter = rotxn.find<0>("powerdns.com"); iter !=rotxn.end(); ++iter)
|
||||
cout<<"Iterating over name 'powerdns.com': "<<endl;
|
||||
auto range = rotxn.equal_range<0>("powerdns.com");
|
||||
for(auto& iter = range.first; iter != range.second; ++iter)
|
||||
{
|
||||
cout << iter->qtype << endl;
|
||||
cout << iter->qname << " " << iter->qtype << " " <<iter->content <<endl;
|
||||
}
|
||||
cout<<"Currently have "<< rotxn.size()<< " entries"<<endl;
|
||||
cout<<" " << rotxn.size<0>() << " " << rotxn.size<1>() << " " << rotxn.size<2>() << endl;
|
||||
cout<<" " << rotxn.cardinality<0>() << endl;
|
||||
cout<<" " << rotxn.cardinality<1>() << endl;
|
||||
cout<<" " << rotxn.cardinality<2>() << endl;
|
||||
cout<<" " << rotxn.cardinality<3>() << endl;
|
||||
}
|
||||
|
||||
auto txn = tdbi.getRWTransaction();
|
||||
|
@ -78,7 +88,6 @@ int main()
|
|||
cout<<" " << txn.cardinality<0>() << endl;
|
||||
cout<<" " << txn.cardinality<1>() << endl;
|
||||
cout<<" " << txn.cardinality<2>() << endl;
|
||||
cout<<" " << txn.cardinality<3>() << endl;
|
||||
|
||||
DNSResourceRecord rr;
|
||||
rr.domain_id=11; rr.qtype = 5; rr.ttl = 3600; rr.qname = "www.powerdns.com"; rr.ordername = "www";
|
||||
|
@ -87,7 +96,7 @@ int main()
|
|||
auto id = txn.insert(rr);
|
||||
cout<<"Inserted as id "<<id<<endl;
|
||||
|
||||
rr.qname = "powerdns.com"; rr.qtype = 1; rr.ordername=" "; rr.content = "1.2.3.4";
|
||||
rr.qname = "powerdns.com"; rr.qtype = 1; rr.ordername=""; rr.content = "1.2.3.4";
|
||||
|
||||
id = txn.insert(rr);
|
||||
cout<<"Inserted as id "<<id<<endl;
|
||||
|
@ -100,14 +109,29 @@ int main()
|
|||
cout<<"Inserted as id "<<id<<endl;
|
||||
|
||||
rr.qname = "www.ds9a.nl"; rr.domain_id = 10; rr.content = "1.2.3.4"; rr.qtype = 1;
|
||||
rr.ordername="www";
|
||||
txn.insert(rr);
|
||||
|
||||
rr.qname = "ds9a.nl"; rr.content = "ns1.ds9a.nl bert.ds9a.bl 1"; rr.qtype = 6;
|
||||
rr.qname = "ds9a.nl"; rr.content = "ns1.ds9a.nl bert.ds9a.nl 1"; rr.qtype = 6;
|
||||
rr.ordername="";
|
||||
txn.insert(rr);
|
||||
|
||||
rr.qname = "ds9a.nl"; rr.content = "25 ns1.ds9a.nl"; rr.qtype = 15;
|
||||
txn.insert(rr);
|
||||
|
||||
rr.qname = "ns1.ds9a.nl"; rr.content = "1.2.3.4"; rr.qtype = 1;
|
||||
rr.ordername="ns1";
|
||||
txn.insert(rr);
|
||||
rr.qname = "ns1.ds9a.nl"; rr.content = "::1"; rr.qtype = 26;
|
||||
txn.insert(rr);
|
||||
|
||||
rr.qname = "ns2.ds9a.nl"; rr.content = "1.2.3.4"; rr.qtype = 1;
|
||||
rr.ordername="ns2";
|
||||
txn.insert(rr);
|
||||
rr.qname = "ns2.ds9a.nl"; rr.content = "::1"; rr.qtype = 26;
|
||||
txn.insert(rr);
|
||||
|
||||
|
||||
|
||||
DNSResourceRecord rr2;
|
||||
id = txn.get<0>("www.powerdns.com", rr2);
|
||||
|
@ -133,16 +157,30 @@ int main()
|
|||
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
|
||||
}
|
||||
|
||||
cout<<"Going to iterate over everything, ordered by id!"<<endl;
|
||||
cout<<"Going to iterate over everything, ordered by id!"<<endl;
|
||||
for(auto iter = txn.begin(); iter != txn.end(); ++iter) {
|
||||
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
|
||||
}
|
||||
|
||||
cout<<"Going to iterate over everything, ordered by compound index!"<<endl;
|
||||
for(auto iter = txn.begin<2>(); iter != txn.end(); ++iter) {
|
||||
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<" # "<<iter->ordername << endl;
|
||||
}
|
||||
|
||||
compound c;
|
||||
rr3.ordername = "www";
|
||||
rr3.domain_id = 10;
|
||||
auto iter = txn.find<2>(c(rr3));
|
||||
cout <<"Found using compound index: "<<iter->qname<< " # " <<iter->ordername<<endl;
|
||||
for(int n =0 ; n < 4; ++n) {
|
||||
--iter;
|
||||
cout <<"Found PREV using compound index: "<<iter->qname<< " # " <<iter->ordername<<endl;
|
||||
}
|
||||
|
||||
cout<<"Going to iterate over the name powerdns.com!"<<endl;
|
||||
|
||||
for(auto iter = txn.find<0>("powerdns.com"); iter != txn.end(); ++iter) {
|
||||
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
|
||||
for(auto iter = txn.equal_range<0>("powerdns.com"); iter.first != iter.second; ++iter.first) {
|
||||
cout << iter.first.getID()<<": "<<iter.first->qname << " " << iter.first->qtype << " " << iter.first->content <<endl;
|
||||
}
|
||||
cout<<"Done iterating"<<endl;
|
||||
|
||||
|
|
|
@ -19,11 +19,12 @@ using std::endl;
|
|||
|
||||
Everything should go into a namespace
|
||||
What is an error? What is an exception?
|
||||
Is id=0 still magic?
|
||||
could id=0 be magic? ('no such id')
|
||||
Composite keys (powerdns needs them)
|
||||
functional keys
|
||||
Insert? Put? Naming matters
|
||||
Is boost the best serializer?
|
||||
|
||||
rename find to equal_range
|
||||
Perhaps use the separate index concept from multi_index
|
||||
A dump function would be nice (typed)
|
||||
*/
|
||||
|
@ -92,33 +93,56 @@ void serFromString(const std::string& str, T& ret)
|
|||
*/
|
||||
|
||||
// this only needs methods that must happen for all indexes at once
|
||||
// so specifically, not size<t> or get<t>, people ask for those
|
||||
template<class Class,typename Type,Type Class::*PtrToMember>
|
||||
struct index_on
|
||||
{
|
||||
static Type getMember(const Class& c)
|
||||
{
|
||||
return c.*PtrToMember;
|
||||
}
|
||||
// so specifically, not size<t> or get<t>, people ask for those themselves, and
|
||||
// should no do that on indexes that don't exist
|
||||
|
||||
template<class Class,typename Type, typename Parent>
|
||||
struct LMDBIndexOps
|
||||
{
|
||||
explicit LMDBIndexOps(Parent* parent) : d_parent(parent){}
|
||||
void put(MDBRWTransaction& txn, const Class& t, uint32_t id)
|
||||
{
|
||||
txn.put(d_idx, getMember(t), id);
|
||||
txn.put(d_idx, d_parent->getMember(t), id);
|
||||
}
|
||||
|
||||
void del(MDBRWTransaction& txn, const Class& t, uint32_t id)
|
||||
{
|
||||
txn.del(d_idx, getMember(t), id);
|
||||
txn.del(d_idx, d_parent->getMember(t), id);
|
||||
}
|
||||
|
||||
void openDB(std::shared_ptr<MDBEnv>& env, string_view str, int flags)
|
||||
{
|
||||
d_idx = env->openDB(str, flags);
|
||||
}
|
||||
MDBDbi d_idx;
|
||||
Parent* d_parent;
|
||||
};
|
||||
|
||||
template<class Class,typename Type,Type Class::*PtrToMember>
|
||||
struct index_on : LMDBIndexOps<Class, Type, index_on<Class, Type, PtrToMember>>
|
||||
{
|
||||
index_on() : LMDBIndexOps<Class, Type, index_on<Class, Type, PtrToMember>>(this)
|
||||
{}
|
||||
static Type getMember(const Class& c)
|
||||
{
|
||||
return c.*PtrToMember;
|
||||
}
|
||||
|
||||
typedef Type type;
|
||||
MDBDbi d_idx;
|
||||
};
|
||||
|
||||
template<class Class, typename Type, class Func>
|
||||
struct index_on_function : LMDBIndexOps<Class, Type, index_on_function<Class, Type, Func> >
|
||||
{
|
||||
index_on_function() : LMDBIndexOps<Class, Type, index_on_function<Class, Type, Func> >(this)
|
||||
{}
|
||||
static Type getMember(const Class& c)
|
||||
{
|
||||
Func f;
|
||||
return f(c);
|
||||
}
|
||||
|
||||
typedef Type type;
|
||||
};
|
||||
|
||||
struct nullindex_t
|
||||
|
@ -268,10 +292,10 @@ public:
|
|||
return &d_t;
|
||||
}
|
||||
|
||||
iter_t& operator++()
|
||||
iter_t& genoperator(MDB_cursor_op dupop, MDB_cursor_op op)
|
||||
{
|
||||
MDBOutVal data;
|
||||
int rc = d_cursor.get(d_key, d_id, d_one_key ? MDB_NEXT_DUP : MDB_NEXT);
|
||||
int rc = d_cursor.get(d_key, d_id, d_one_key ? dupop : op);
|
||||
if(rc == MDB_NOTFOUND) {
|
||||
d_end = true;
|
||||
}
|
||||
|
@ -288,6 +312,15 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
iter_t& operator++()
|
||||
{
|
||||
return genoperator(MDB_NEXT_DUP, MDB_NEXT);
|
||||
}
|
||||
iter_t& operator--()
|
||||
{
|
||||
return genoperator(MDB_PREV_DUP, MDB_PREV);
|
||||
}
|
||||
|
||||
uint32_t getID()
|
||||
{
|
||||
if(d_on_index)
|
||||
|
@ -298,7 +331,7 @@ public:
|
|||
|
||||
Parent* d_parent;
|
||||
typename Parent::cursor_t d_cursor;
|
||||
MDBOutVal d_key, d_data, d_id;
|
||||
MDBOutVal d_key{0,0}, d_data{0,0}, d_id{0,0};
|
||||
bool d_on_index;
|
||||
bool d_one_key;
|
||||
bool d_end{false};
|
||||
|
@ -312,8 +345,9 @@ public:
|
|||
|
||||
MDBOutVal out, id;
|
||||
|
||||
if(cursor.get(out, id, MDB_FIRST)) {
|
||||
return iter_t{&d_parent, std::move(cursor), true, true, true};
|
||||
if(cursor.get(out, id, MDB_FIRST))
|
||||
{ // on_index, one_key, end
|
||||
return iter_t{&d_parent, std::move(cursor), true, false, true};
|
||||
}
|
||||
|
||||
return iter_t{&d_parent, std::move(cursor), true, false};
|
||||
|
@ -326,7 +360,8 @@ public:
|
|||
MDBOutVal out, id;
|
||||
|
||||
if(cursor.get(out, id, MDB_FIRST)) {
|
||||
return iter_t{&d_parent, std::move(cursor), false, true, true};
|
||||
// on_index, one_key, end
|
||||
return iter_t{&d_parent, std::move(cursor), false, false, true};
|
||||
}
|
||||
|
||||
return iter_t{&d_parent, std::move(cursor), false, false};
|
||||
|
@ -343,11 +378,30 @@ public:
|
|||
out.d_mdbval = in.d_mdbval;
|
||||
|
||||
if(cursor.get(out, id, MDB_SET)) {
|
||||
return iter_t{&d_parent, std::move(cursor), true, true, true};
|
||||
// on_index, one_key, end
|
||||
return iter_t{&d_parent, std::move(cursor), true, false, true};
|
||||
}
|
||||
|
||||
return iter_t{&d_parent, std::move(cursor), true, true};
|
||||
return iter_t{&d_parent, std::move(cursor), true, false};
|
||||
};
|
||||
|
||||
template<int N>
|
||||
std::pair<iter_t,eiter_t> equal_range(const typename std::tuple_element<N, tuple_t>::type::type& key)
|
||||
{
|
||||
typename Parent::cursor_t cursor = d_parent.d_txn.getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
|
||||
|
||||
MDBInVal in(key);
|
||||
MDBOutVal out, id;
|
||||
out.d_mdbval = in.d_mdbval;
|
||||
|
||||
if(cursor.get(out, id, MDB_SET)) {
|
||||
// on_index, one_key, end
|
||||
return {iter_t{&d_parent, std::move(cursor), true, true, true}, eiter_t()};
|
||||
}
|
||||
|
||||
return {iter_t{&d_parent, std::move(cursor), true, true}, eiter_t()};
|
||||
};
|
||||
|
||||
|
||||
eiter_t end()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue