find, begin
This commit is contained in:
parent
5af0bb3e67
commit
a144209f12
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
122
lmdb-typed.hh
122
lmdb-typed.hh
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue