find, begin

This commit is contained in:
bert hubert 2018-12-15 21:06:47 +01:00
parent 5af0bb3e67
commit a144209f12
3 changed files with 127 additions and 62 deletions

View File

@ -329,14 +329,10 @@ public:
return mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET); return mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET);
} }
MDB_cursor* d_cursor; MDB_cursor* d_cursor;
MDBROTransaction* d_parent; MDBROTransaction* d_parent;
}; };
class MDBRWCursor; class MDBRWCursor;
class MDBRWTransaction class MDBRWTransaction

View File

@ -62,24 +62,26 @@ int main()
{ {
cout << iter->qtype << endl; cout << iter->qtype << 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(); auto txn = tdbi.getRWTransaction();
cout<<"Currently have "<< txn.size()<< " entries"<<endl; txn.clear();
cout<<"Currently have "<< txn.size()<< " entries after clear"<<endl;
cout<<" " << txn.size<0>() << " " << txn.size<1>() << " " << txn.size<2>() << endl; cout<<" " << txn.size<0>() << " " << txn.size<1>() << " " << txn.size<2>() << endl;
cout<<" " << txn.cardinality<0>() << endl; cout<<" " << txn.cardinality<0>() << endl;
cout<<" " << txn.cardinality<1>() << endl; cout<<" " << txn.cardinality<1>() << endl;
cout<<" " << txn.cardinality<2>() << endl; cout<<" " << txn.cardinality<2>() << endl;
cout<<" " << txn.cardinality<3>() << endl; cout<<" " << txn.cardinality<3>() << endl;
txn.clear();
cout<<"Currently have "<< txn.size()<< " entries after clear"<<endl;
cout<<" " << txn.size<0>() << " " << txn.size<1>() << " " << txn.size<2>() << endl;
DNSResourceRecord rr; DNSResourceRecord rr;
rr.domain_id=0; rr.qtype = 5; rr.ttl = 3600; rr.qname = "www.powerdns.com"; rr.ordername = "www"; rr.domain_id=11; rr.qtype = 5; rr.ttl = 3600; rr.qname = "www.powerdns.com"; rr.ordername = "www";
rr.content = "powerdns.com"; rr.content = "powerdns.com";
auto id = txn.insert(rr); auto id = txn.insert(rr);
@ -97,12 +99,16 @@ int main()
rr.content = "ns2.powerdns.com"; rr.ordername = "ns2"; id = txn.insert(rr); rr.content = "ns2.powerdns.com"; rr.ordername = "ns2"; id = txn.insert(rr);
cout<<"Inserted as id "<<id<<endl; cout<<"Inserted as id "<<id<<endl;
rr.qname = "www.ds9a.nl"; rr.domain_id = 1; rr.content = "1.2.3.4"; rr.qtype = 1; rr.qname = "www.ds9a.nl"; rr.domain_id = 10; rr.content = "1.2.3.4"; rr.qtype = 1;
txn.insert(rr); 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.bl 1"; rr.qtype = 6;
txn.insert(rr); txn.insert(rr);
rr.qname = "ds9a.nl"; rr.content = "25 ns1.ds9a.nl"; rr.qtype = 15;
txn.insert(rr);
DNSResourceRecord rr2; DNSResourceRecord rr2;
id = txn.get<0>("www.powerdns.com", rr2); id = txn.get<0>("www.powerdns.com", rr2);
@ -116,17 +122,34 @@ int main()
id = txn.get<0>("powerdns.com", rr3); id = txn.get<0>("powerdns.com", rr3);
cout<< id << endl; cout<< id << endl;
cout<<"Going to iterate over powerdns.com!"<<endl;
cout<<"Going to iterate over everything, ordered by name!"<<endl;
for(auto iter = txn.begin<0>(); iter != txn.end(); ++iter) {
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
}
cout<<"Going to iterate over everything, ordered by domain_id!"<<endl;
for(auto iter = txn.begin<1>(); iter != txn.end(); ++iter) {
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<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 the name powerdns.com!"<<endl;
for(auto iter = txn.find<0>("powerdns.com"); iter != txn.end(); ++iter) { for(auto iter = txn.find<0>("powerdns.com"); iter != txn.end(); ++iter) {
cout << iter->qname << " " << iter->qtype << " " << iter->content <<endl; cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
} }
cout<<"Done iterating"<<endl; cout<<"Done iterating"<<endl;
cout<<"Going to iterate over ds9a.nl!"<<endl; cout<<"Going to iterate over the zone ds9a.nl!"<<endl;
for(auto iter = txn.find<1>(1); iter != txn.end(); ++iter) { for(auto iter = txn.find<1>(10); iter != txn.end(); ++iter) {
cout << iter->qname << " " << iter->qtype << " " << iter->content <<endl; cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
} }
cout<<"Done iterating"<<endl; cout<<"Done iterating"<<endl;

View File

@ -23,11 +23,9 @@ using std::endl;
Composite keys (powerdns needs them) Composite keys (powerdns needs them)
Insert? Put? Naming matters Insert? Put? Naming matters
Is boost the best serializer? Is boost the best serializer?
Iterator on main table
begin() and end()
Perhaps use the separate index concept from multi_index Perhaps use the separate index concept from multi_index
A dump function would be nice (typed) A dump function would be nice (typed)
Need a read-only transaction (without duplicating all the things)
*/ */
unsigned int getMaxID(MDBRWTransaction& txn, MDBDbi& dbi); unsigned int getMaxID(MDBRWTransaction& txn, MDBDbi& dbi);
@ -93,7 +91,8 @@ void serFromString(const std::string& str, T& ret)
tdbi.modify(id, [](auto& rr) { rr.ordername="blah"; }); tdbi.modify(id, [](auto& rr) { rr.ordername="blah"; });
*/ */
// 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> template<class Class,typename Type,Type Class::*PtrToMember>
struct index_on struct index_on
{ {
@ -117,12 +116,6 @@ struct index_on
d_idx = env->openDB(str, flags); d_idx = env->openDB(str, flags);
} }
uint32_t size(MDBRWTransaction& txn)
{
MDB_stat stat;
mdb_stat(txn, d_idx, &stat);
return stat.ms_entries;
}
typedef Type type; typedef Type type;
MDBDbi d_idx; MDBDbi d_idx;
@ -137,11 +130,6 @@ struct nullindex_t
void del(MDBRWTransaction& txn, const Class& t, uint32_t id) void del(MDBRWTransaction& txn, const Class& t, uint32_t id)
{} {}
uint32_t size()
{
return 0;
}
void openDB(std::shared_ptr<MDBEnv>& env, string_view str, int flags) void openDB(std::shared_ptr<MDBEnv>& env, string_view str, int flags)
{ {
@ -186,10 +174,11 @@ public:
template<int N> template<int N>
uint32_t size() uint32_t size()
{ {
return std::get<N>(d_parent.d_parent->d_tuple).size(d_parent.d_txn); MDB_stat stat;
mdb_stat(d_parent.d_txn, std::get<N>(d_parent.d_parent->d_tuple).d_idx, &stat);
return stat.ms_entries;
} }
bool get(uint32_t id, T& t) bool get(uint32_t id, T& t)
{ {
MDBOutVal data; MDBOutVal data;
@ -227,26 +216,35 @@ public:
struct eiter_t struct eiter_t
{}; {};
// can be on main, or on an index
template<int N> // when on main, return data directly
// when on index, indirect
// we can be limited to one key, or iterate over entire table
//
struct iter_t struct iter_t
{ {
explicit iter_t(Parent* parent, const typename std::tuple_element<N, tuple_t>::type::type& key) : explicit iter_t(Parent* parent, typename Parent::cursor_t&& cursor, bool on_index, bool one_key, bool end=false) :
d_parent(parent), d_parent(parent),
d_cursor(d_parent->d_txn.getCursor(std::get<N>(d_parent->d_parent->d_tuple).d_idx)), d_cursor(std::move(cursor)),
d_in(key) d_on_index(on_index),
d_one_key(one_key),
d_end(end)
{ {
d_key.d_mdbval = d_in.d_mdbval; if(d_end)
return;
MDBOutVal id, data; if(d_cursor.get(d_key, d_id, MDB_GET_CURRENT)) {
if(d_cursor.get(d_key, id, MDB_SET)) {
d_end = true; d_end = true;
return; return;
} }
if(d_parent->d_txn.get(d_parent->d_parent->d_main, id, data))
throw std::runtime_error("Missing id in constructor");
serFromString(data.get<std::string>(), d_t); if(d_on_index) {
if(d_parent->d_txn.get(d_parent->d_parent->d_main, d_id, d_data))
throw std::runtime_error("Missing id in constructor");
serFromString(d_data.get<std::string>(), d_t);
}
else
serFromString(d_id.get<std::string>(), d_t);
} }
@ -272,33 +270,83 @@ public:
iter_t& operator++() iter_t& operator++()
{ {
MDBOutVal id, data; MDBOutVal data;
int rc = d_cursor.get(d_key, id, MDB_NEXT_DUP); int rc = d_cursor.get(d_key, d_id, d_one_key ? MDB_NEXT_DUP : MDB_NEXT);
if(rc == MDB_NOTFOUND) { if(rc == MDB_NOTFOUND) {
d_end = true; d_end = true;
} }
else { else {
if(d_parent->d_txn.get(d_parent->d_parent->d_main, id, data)) if(d_on_index) {
if(d_parent->d_txn.get(d_parent->d_parent->d_main, d_id, data))
throw std::runtime_error("Missing id field"); throw std::runtime_error("Missing id field");
serFromString(data.get<std::string>(), d_t); serFromString(data.get<std::string>(), d_t);
} }
else
serFromString(d_id.get<std::string>(), d_t);
}
return *this; return *this;
} }
uint32_t getID()
{
if(d_on_index)
return d_id.get<uint32_t>();
else
return d_key.get<uint32_t>();
}
Parent* d_parent; Parent* d_parent;
typename Parent::cursor_t d_cursor; typename Parent::cursor_t d_cursor;
MDBOutVal d_key, d_data; MDBOutVal d_key, d_data, d_id;
MDBInVal d_in; bool d_on_index;
bool d_one_key;
bool d_end{false}; bool d_end{false};
T d_t; T d_t;
}; };
template<int N> template<int N>
iter_t<N> find(const typename std::tuple_element<N, tuple_t>::type::type& key) iter_t begin()
{ {
iter_t<N> ret{&d_parent, key}; typename Parent::cursor_t cursor = d_parent.d_txn.getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
return ret;
MDBOutVal out, id;
if(cursor.get(out, id, MDB_FIRST)) {
return iter_t{&d_parent, std::move(cursor), true, true, true};
}
return iter_t{&d_parent, std::move(cursor), true, false};
};
iter_t begin()
{
typename Parent::cursor_t cursor = d_parent.d_txn.getCursor(d_parent.d_parent->d_main);
MDBOutVal out, id;
if(cursor.get(out, id, MDB_FIRST)) {
return iter_t{&d_parent, std::move(cursor), false, true, true};
}
return iter_t{&d_parent, std::move(cursor), false, false};
};
template<int N>
iter_t find(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)) {
return iter_t{&d_parent, std::move(cursor), true, true, true};
}
return iter_t{&d_parent, std::move(cursor), true, true};
}; };
eiter_t end() eiter_t end()
@ -306,8 +354,6 @@ public:
return eiter_t(); return eiter_t();
} }
Parent& d_parent; Parent& d_parent;
}; };