Format tests and examples as well

This commit is contained in:
Martchus 2022-01-30 21:32:08 +01:00
parent 1e393bf3fe
commit ec4a44e4de
10 changed files with 811 additions and 824 deletions

View File

@ -61,6 +61,16 @@ use_package(TARGET_NAME Catch2::Catch2 PACKAGE_NAME Catch2 LIBRARIES_VARIABLE "T
# find threading library (required by examples) # find threading library (required by examples)
use_package(TARGET_NAME Threads::Threads PACKAGE_NAME Threads LIBRARIES_VARIABLE "TEST_LIBRARIES") use_package(TARGET_NAME Threads::Threads PACKAGE_NAME Threads LIBRARIES_VARIABLE "TEST_LIBRARIES")
# add test/example files to EXCLUDED_FILES so they're formatted
set(TESTS basic typed)
set(EXAMPLES basic multi rel resize scale typed view)
foreach (TEST ${TESTS})
list(APPEND EXCLUDED_FILES "tests/${TEST}.cc")
endforeach ()
foreach (EXAMPLE ${EXAMPLES})
list(APPEND EXCLUDED_FILES "examples/${EXAMPLE}.cc")
endforeach ()
# include modules to apply configuration # include modules to apply configuration
include(BasicConfig) include(BasicConfig)
include(WindowsResources) include(WindowsResources)
@ -71,11 +81,9 @@ include(ConfigHeader)
# configure test targets # configure test targets
include(TestUtilities) include(TestUtilities)
list(APPEND TEST_LIBRARIES ${META_TARGET_NAME}) list(APPEND TEST_LIBRARIES ${META_TARGET_NAME})
set(TESTS basic typed)
foreach (TEST ${TESTS}) foreach (TEST ${TESTS})
configure_test_target(TEST_NAME "${TEST}_tests" SRC_FILES "tests/${TEST}.cc" LIBRARIES "${TEST_LIBRARIES}") configure_test_target(TEST_NAME "${TEST}_tests" SRC_FILES "tests/${TEST}.cc" LIBRARIES "${TEST_LIBRARIES}")
endforeach () endforeach ()
set(EXAMPLES basic multi rel resize scale typed view)
foreach (EXAMPLE ${EXAMPLES}) foreach (EXAMPLE ${EXAMPLES})
configure_test_target(TEST_NAME "${EXAMPLE}_example" SRC_FILES "examples/${EXAMPLE}.cc" LIBRARIES "${TEST_LIBRARIES}") configure_test_target(TEST_NAME "${EXAMPLE}_example" SRC_FILES "examples/${EXAMPLE}.cc" LIBRARIES "${TEST_LIBRARIES}")
endforeach () endforeach ()

View File

@ -3,15 +3,14 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
void checkLMDB(MDBEnv* env, MDBDbi dbi) void checkLMDB(MDBEnv *env, MDBDbi dbi)
{ {
auto rotxn = env->getROTransaction(); auto rotxn = env->getROTransaction();
MDBOutVal data; MDBOutVal data;
if(!rotxn->get(dbi, "lmdb", data)) { if (!rotxn->get(dbi, "lmdb", data)) {
cout<< "Outside RW transaction, found that lmdb = " << data.get<string_view>() <<endl; cout << "Outside RW transaction, found that lmdb = " << data.get<string_view>() << endl;
} } else
else cout << "Outside RW transaction, found nothing" << endl;
cout<<"Outside RW transaction, found nothing" << endl;
} }
int main() int main()
@ -24,18 +23,17 @@ int main()
txn->put(dbi, "lmdb", "great"); txn->put(dbi, "lmdb", "great");
MDBOutVal data; MDBOutVal data;
if(!txn->get(dbi, "lmdb", data)) { if (!txn->get(dbi, "lmdb", data)) {
cout<< "Within RW transaction, found that lmdb = " << data.get<string_view>() <<endl; cout << "Within RW transaction, found that lmdb = " << data.get<string_view>() << endl;
} } else
else cout << "Found nothing" << endl;
cout<<"Found nothing" << endl;
std::thread elsewhere(checkLMDB, env.get(), dbi); std::thread elsewhere(checkLMDB, env.get(), dbi);
elsewhere.join(); elsewhere.join();
txn->commit(); txn->commit();
cout<<"Committed data"<<endl; cout << "Committed data" << endl;
checkLMDB(env.get(), dbi); checkLMDB(env.get(), dbi);
txn = env->getRWTransaction(); txn = env->getRWTransaction();

View File

@ -22,10 +22,9 @@ int main()
txn->put(dbi, "mdb", "old name"); txn->put(dbi, "mdb", "old name");
string_view v1; string_view v1;
if(!txn->get(dbi, "mdb", v1)) { if (!txn->get(dbi, "mdb", v1)) {
cout<<v1<<endl; cout << v1 << endl;
} } else {
else {
cout << "found nothing" << endl; cout << "found nothing" << endl;
} }
txn->commit(); txn->commit();
@ -35,28 +34,26 @@ int main()
MDBOutVal key, data; MDBOutVal key, data;
for(int rc = cursor.find("lmdb", key, data); !rc; rc = cursor.get(key, data, MDB_NEXT_DUP)) { for (int rc = cursor.find("lmdb", key, data); !rc; rc = cursor.get(key, data, MDB_NEXT_DUP)) {
cout << key.get<string_view>() << " = " << data.get<string_view>() <<endl; cout << key.get<string_view>() << " = " << data.get<string_view>() << endl;
} }
cout<<"Dump of complete database: "<<endl; cout << "Dump of complete database: " << endl;
for(int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) { for (int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) {
cout << key.get<string_view>() << " = " << data.get<string_view>() <<endl; cout << key.get<string_view>() << " = " << data.get<string_view>() << endl;
} }
cout << "Done!" <<endl; cout << "Done!" << endl;
cout << "Now going to delete 'lmdb' keys" << endl; cout << "Now going to delete 'lmdb' keys" << endl;
for(int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) { for (int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) {
if(key.get<string_view>() == "lmdb") if (key.get<string_view>() == "lmdb")
cursor.del(); cursor.del();
} }
cout <<"Complete database after deleting 'lmdb' keys: " << endl; cout << "Complete database after deleting 'lmdb' keys: " << endl;
for(int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) { for (int rc = cursor.first(key, data); !rc; rc = cursor.next(key, data)) {
cout << key.get<string_view>() << " = " << data.get<string_view>() <<endl; cout << key.get<string_view>() << " = " << data.get<string_view>() << endl;
} }
} }

View File

@ -1,7 +1,7 @@
#include "../lmdb-safe.hh" #include "../lmdb-safe.hh"
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <c++utilities/application/global.h> #include <c++utilities/application/global.h>
@ -10,43 +10,40 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
struct Record struct Record {
{
friend class boost::serialization::access; friend class boost::serialization::access;
template<class Archive> template <class Archive> void serialize(Archive &ar, const unsigned int version)
void serialize(Archive & ar, const unsigned int version)
{ {
CPP_UTILITIES_UNUSED(version) CPP_UTILITIES_UNUSED(version)
ar & id & domain_id & name & type & ttl & content & enabled & auth; ar &id &domain_id &name &type &ttl &content &enabled &auth;
} }
unsigned int id; unsigned int id;
unsigned int domain_id; // needs index unsigned int domain_id; // needs index
std::string name; // needs index std::string name; // needs index
std::string type; std::string type;
unsigned int ttl{0}; unsigned int ttl{ 0 };
std::string content; std::string content;
bool enabled{true}; bool enabled{ true };
bool auth{true}; bool auth{ true };
}; };
static unsigned int getMaxID(MDBRWTransaction& txn, MDBDbi& dbi) static unsigned int getMaxID(MDBRWTransaction &txn, MDBDbi &dbi)
{ {
auto cursor = txn->getRWCursor(dbi); auto cursor = txn->getRWCursor(dbi);
MDBOutVal maxidval, maxcontent; MDBOutVal maxidval, maxcontent;
unsigned int maxid{0}; unsigned int maxid{ 0 };
if(!cursor.get(maxidval, maxcontent, MDB_LAST)) { if (!cursor.get(maxidval, maxcontent, MDB_LAST)) {
maxid = maxidval.get<unsigned int>(); maxid = maxidval.get<unsigned int>();
} }
return maxid; return maxid;
} }
static void store(MDBRWTransaction& txn, MDBDbi& records, MDBDbi& domainidx, MDBDbi&nameidx, const Record& r) static void store(MDBRWTransaction &txn, MDBDbi &records, MDBDbi &domainidx, MDBDbi &nameidx, const Record &r)
{ {
ostringstream oss; ostringstream oss;
boost::archive::binary_oarchive oa(oss,boost::archive::no_header ); boost::archive::binary_oarchive oa(oss, boost::archive::no_header);
oa << r; oa << r;
txn->put(records, r.id, oss.str(), MDB_APPEND); txn->put(records, r.id, oss.str(), MDB_APPEND);
@ -54,11 +51,10 @@ static void store(MDBRWTransaction& txn, MDBDbi& records, MDBDbi& domainidx, MDB
txn->put(nameidx, r.name, r.id); txn->put(nameidx, r.name, r.id);
} }
int main(int argc, char **argv)
int main(int argc, char** argv)
{ {
auto env = getMDBEnv("pdns", MDB_NOSUBDIR, 0600); auto env = getMDBEnv("pdns", MDB_NOSUBDIR, 0600);
auto records = env->openDB("records", MDB_INTEGERKEY | MDB_CREATE ); auto records = env->openDB("records", MDB_INTEGERKEY | MDB_CREATE);
auto domainidx = env->openDB("domainidx", MDB_INTEGERKEY | MDB_DUPFIXED | MDB_DUPSORT | MDB_CREATE); auto domainidx = env->openDB("domainidx", MDB_INTEGERKEY | MDB_DUPFIXED | MDB_DUPSORT | MDB_CREATE);
auto nameidx = env->openDB("nameidx", MDB_DUPFIXED | MDB_DUPSORT | MDB_CREATE); auto nameidx = env->openDB("nameidx", MDB_DUPFIXED | MDB_DUPSORT | MDB_CREATE);
@ -71,21 +67,21 @@ int main(int argc, char** argv)
txn.clear(nameidx); txn.clear(nameidx);
*/ */
unsigned int maxid=getMaxID(txn, records); unsigned int maxid = getMaxID(txn, records);
unsigned int maxdomainid=getMaxID(txn, domainidx); unsigned int maxdomainid = getMaxID(txn, domainidx);
cout<<"Maxid = "<<maxid<<", Max domain ID = "<<maxdomainid<<endl; cout << "Maxid = " << maxid << ", Max domain ID = " << maxdomainid << endl;
string prefix(argc >= 2 ? argv[1] : "prefix"); string prefix(argc >= 2 ? argv[1] : "prefix");
auto lim=atoi(argc >= 3 ? argv[2] : "10"); auto lim = atoi(argc >= 3 ? argv[2] : "10");
for(int n=0; n < lim; ++n) { for (int n = 0; n < lim; ++n) {
string domain; string domain;
if(n) if (n)
domain.assign(prefix+std::to_string(n)+".com"); domain.assign(prefix + std::to_string(n) + ".com");
else else
domain="powerdns.com"; domain = "powerdns.com";
Record r; Record r;
r.id=++maxid; r.id = ++maxid;
r.domain_id = ++maxdomainid; r.domain_id = ++maxdomainid;
r.name = domain; r.name = domain;
r.ttl = 3600; r.ttl = 3600;
@ -94,38 +90,36 @@ int main(int argc, char** argv)
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id=++maxid; r.id = ++maxid;
r.type="NS"; r.type = "NS";
r.content="ns1.powerdns.com"; r.content = "ns1.powerdns.com";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id = ++maxid;
r.id=++maxid; r.type = "A";
r.type="A"; r.content = "1.2.3.4";
r.content="1.2.3.4";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id=++maxid; r.id = ++maxid;
r.type="AAAA"; r.type = "AAAA";
r.content="::1"; r.content = "::1";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id=++maxid; r.id = ++maxid;
r.type="CAA"; r.type = "CAA";
r.content="letsencrypt.org"; r.content = "letsencrypt.org";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id = ++maxid;
r.id=++maxid; r.type = "AAAA";
r.type="AAAA"; r.name = "www." + domain;
r.name="www."+domain; r.content = "::1";
r.content="::1";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
r.id=++maxid; r.id = ++maxid;
r.type="A"; r.type = "A";
r.name="www."+domain; r.name = "www." + domain;
r.content="127.0.0.1"; r.content = "127.0.0.1";
store(txn, records, domainidx, nameidx, r); store(txn, records, domainidx, nameidx, r);
} }
@ -145,22 +139,20 @@ int main(int argc, char** argv)
// ugh // ugh
while(!rocursor.get(key, data, count ? MDB_NEXT_DUP : MDB_SET)) { while (!rocursor.get(key, data, count ? MDB_NEXT_DUP : MDB_SET)) {
unsigned int id = data.get<unsigned int>(); unsigned int id = data.get<unsigned int>();
cout<<"Got something: id="<<id<<endl; cout << "Got something: id=" << id << endl;
MDBOutVal record; MDBOutVal record;
if(!rotxn->get(records, data, record)) { if (!rotxn->get(records, data, record)) {
Record test; Record test;
stringstream istr{record.get<string>()}; stringstream istr{ record.get<string>() };
boost::archive::binary_iarchive oi(istr,boost::archive::no_header ); boost::archive::binary_iarchive oi(istr, boost::archive::no_header);
oi >> test; oi >> test;
cout <<"Record: "<<test.name<<" "<<test.type <<" " <<test.ttl<<" "<<test.content<<endl; cout << "Record: " << test.name << " " << test.type << " " << test.ttl << " " << test.content << endl;
} } else {
else { cout << "Did not find anything for id " << id << endl;
cout<<"Did not find anything for id "<<id<<endl;
} }
++count; ++count;
} }
} }

View File

@ -5,86 +5,77 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
template <typename First, typename Second> template <typename First, typename Second> struct Pair {
struct Pair {
First first; First first;
Second second; Second second;
}; };
int main(int argc, char**) int main(int argc, char **)
{ {
auto env = getMDBEnv("resize", MDB_NOSUBDIR | MDB_NOSYNC, 0600); auto env = getMDBEnv("resize", MDB_NOSUBDIR | MDB_NOSYNC, 0600);
auto main = env->openDB("ahu", MDB_CREATE ); auto main = env->openDB("ahu", MDB_CREATE);
MDBInVal key("counter"); MDBInVal key("counter");
auto rwtxn = env->getRWTransaction(); auto rwtxn = env->getRWTransaction();
rwtxn->put(main, "counter", "1234"); rwtxn->put(main, "counter", "1234");
rwtxn->put(main, MDBInVal::fromStruct(Pair<int, int>{12,13}), "hoi dan 12,13"); rwtxn->put(main, MDBInVal::fromStruct(Pair<int, int>{ 12, 13 }), "hoi dan 12,13");
rwtxn->put(main, MDBInVal::fromStruct(Pair<int, int>{14,15}),
MDBInVal::fromStruct(Pair<int, int>{20,23}));
rwtxn->put(main, MDBInVal::fromStruct(Pair<int, int>{ 14, 15 }), MDBInVal::fromStruct(Pair<int, int>{ 20, 23 }));
MDBOutVal out; MDBOutVal out;
if(!rwtxn->get(main, MDBInVal::fromStruct(Pair<int, int>{12,13}), out)) if (!rwtxn->get(main, MDBInVal::fromStruct(Pair<int, int>{ 12, 13 }), out))
cout << "Got: " << out.get<string_view>() << endl; cout << "Got: " << out.get<string_view>() << endl;
else else
cout << "Got nothing!1"<<endl; cout << "Got nothing!1" << endl;
if(!rwtxn->get(main, MDBInVal::fromStruct(Pair<int, int>{14,15}), out)) { if (!rwtxn->get(main, MDBInVal::fromStruct(Pair<int, int>{ 14, 15 }), out)) {
auto res = out.get_struct<Pair<int,int>>(); auto res = out.get_struct<Pair<int, int>>();
cout << "Got: " << res.first<<", "<<res.second << endl; cout << "Got: " << res.first << ", " << res.second << endl;
} } else
else cout << "Got nothing!1" << endl;
cout << "Got nothing!1"<<endl;
rwtxn->put(main, 12.12, 7.3); rwtxn->put(main, 12.12, 7.3);
if(!rwtxn->get(main, 12.12, out)) { if (!rwtxn->get(main, 12.12, out)) {
cout<<"Got: "<< out.get<double>() <<endl; cout << "Got: " << out.get<double>() << endl;
} } else
else cout << "Got nothing!1" << endl;
cout << "Got nothing!1"<<endl;
rwtxn->commit(); rwtxn->commit();
return 0; return 0;
if(argc==1) { if (argc == 1) {
for(;;) { for (;;) {
auto rotxn = env->getROTransaction(); auto rotxn = env->getROTransaction();
MDBOutVal data; MDBOutVal data;
if(!rotxn->get(main, key, data)) { if (!rotxn->get(main, key, data)) {
cout<<"Counter is "<<data.get<unsigned int>() << endl; cout << "Counter is " << data.get<unsigned int>() << endl;
cout <<data.get<string>() << endl; cout << data.get<string>() << endl;
cout<<data.get<string_view>() << endl; cout << data.get<string_view>() << endl;
struct Bert struct Bert {
{ uint16_t x, y;
uint16_t x,y;
}; };
auto b = data.get_struct<Bert>(); auto b = data.get_struct<Bert>();
cout<<b.x<<" "<<b.y<<endl; cout << b.x << " " << b.y << endl;
cout<<data.get<unsigned long>() << endl; cout << data.get<unsigned long>() << endl;
} } else
else cout << "Didn't find it" << endl;
cout<<"Didn't find it"<<endl;
exit(1); exit(1);
} }
} } else {
else { size_t size = 1ULL * 4096 * 244140ULL;
size_t size = 1ULL*4096*244140ULL; for (unsigned int n = 0;; ++n) {
for(unsigned int n=0;;++n) { if (!(n % 16384)) {
if(!(n%16384)) {
size += 16384; size += 16384;
if(int rc=mdb_env_set_mapsize(*env.get(), size)) if (int rc = mdb_env_set_mapsize(*env.get(), size))
throw std::runtime_error("Resizing: "+string(mdb_strerror(rc))); throw std::runtime_error("Resizing: " + string(mdb_strerror(rc)));
cout<<"Did resize"<<endl; cout << "Did resize" << endl;
} }
auto txn = env->getRWTransaction(); auto txn = env->getRWTransaction();
txn->put(main, key, MDBInVal(n)); txn->put(main, key, MDBInVal(n));
for(unsigned int k=0; k < 100; ++k) for (unsigned int k = 0; k < 100; ++k)
txn->put(main, MDBInVal(n+1000*k), MDBInVal(n+1000*k)); txn->put(main, MDBInVal(n + 1000 * k), MDBInVal(n + 1000 * k));
txn->commit(); txn->commit();
} }
} }

View File

@ -5,14 +5,14 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
struct MDBVal struct MDBVal {
{ MDBVal(unsigned int v)
MDBVal(unsigned int v) : d_v(v) : d_v(v)
{ {
d_mdbval.mv_size = sizeof(d_v); d_mdbval.mv_size = sizeof(d_v);
d_mdbval.mv_data = &d_v; d_mdbval.mv_data = &d_v;
} }
operator const MDB_val&() operator const MDB_val &()
{ {
return d_mdbval; return d_mdbval;
} }
@ -20,39 +20,42 @@ struct MDBVal
MDB_val d_mdbval; MDB_val d_mdbval;
}; };
int main(int argc, char **argv)
int main(int argc, char** argv)
{ {
auto env = getMDBEnv("./database", MDB_NOSUBDIR, 0600); auto env = getMDBEnv("./database", MDB_NOSUBDIR, 0600);
auto dbi = env->openDB(std::string_view(), MDB_CREATE | MDB_INTEGERKEY); auto dbi = env->openDB(std::string_view(), MDB_CREATE | MDB_INTEGERKEY);
auto txn = env->getRWTransaction(); auto txn = env->getRWTransaction();
unsigned int limit=20; unsigned int limit = 20;
if(argc > 1) if (argc > 1)
limit = CppUtilities::stringToNumber<unsigned int>(argv[1]); limit = CppUtilities::stringToNumber<unsigned int>(argv[1]);
cout<<"Counting records.. "; cout.flush(); cout << "Counting records.. ";
cout.flush();
auto cursor = txn->getCursor(dbi); auto cursor = txn->getCursor(dbi);
MDBOutVal key, data; MDBOutVal key, data;
int count=0; int count = 0;
while(!cursor.get(key, data, count ? MDB_NEXT : MDB_FIRST)) { while (!cursor.get(key, data, count ? MDB_NEXT : MDB_FIRST)) {
auto d = data.get<unsigned long>(); auto d = data.get<unsigned long>();
if(d==17) if (d == 17)
cout <<"Got 17!"<<endl; cout << "Got 17!" << endl;
count++; count++;
} }
cout<<"Have "<<count<<"!"<<endl; cout << "Have " << count << "!" << endl;
cout<<"Clearing records.. "; cout.flush(); cout << "Clearing records.. ";
cout.flush();
mdb_drop(*txn, dbi, 0); // clear records mdb_drop(*txn, dbi, 0); // clear records
cout<<"Done!"<<endl; cout << "Done!" << endl;
cout << "Adding "<<limit<<" values .. "; cout.flush(); cout << "Adding " << limit << " values .. ";
for(unsigned long n = 0 ; n < limit; ++n) { cout.flush();
for (unsigned long n = 0; n < limit; ++n) {
txn->put(dbi, n, n, MDB_APPEND); txn->put(dbi, n, n, MDB_APPEND);
} }
cout <<"Done!"<<endl; cout << "Done!" << endl;
cout <<"Calling commit.. "; cout.flush(); cout << "Calling commit.. ";
cout.flush();
txn->commit(); txn->commit();
cout<<"Done!"<<endl; cout << "Done!" << endl;
} }

View File

@ -10,47 +10,41 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
struct DNSResourceRecord struct DNSResourceRecord {
{
string qname; // index string qname; // index
uint16_t qtype{0}; uint16_t qtype{ 0 };
uint32_t domain_id{0}; // index uint32_t domain_id{ 0 }; // index
string content; string content;
uint32_t ttl{0}; uint32_t ttl{ 0 };
string ordername; // index string ordername; // index
bool auth{true}; bool auth{ true };
}; };
struct DomainInfo struct DomainInfo {
{
string qname; string qname;
string master; string master;
}; };
template<class Archive> template <class Archive> void serialize(Archive &ar, DomainInfo &g, const unsigned int version)
void serialize(Archive & ar, DomainInfo& g, const unsigned int version)
{ {
CPP_UTILITIES_UNUSED(version) CPP_UTILITIES_UNUSED(version)
ar & g.qname & g.master; ar &g.qname &g.master;
} }
template<class Archive> template <class Archive> void serialize(Archive &ar, DNSResourceRecord &g, const unsigned int version)
void serialize(Archive & ar, DNSResourceRecord& g, const unsigned int version)
{ {
CPP_UTILITIES_UNUSED(version) CPP_UTILITIES_UNUSED(version)
ar & g.qtype; ar &g.qtype;
ar & g.qname; ar &g.qname;
ar & g.content; ar &g.content;
ar & g.ttl; ar &g.ttl;
ar & g.domain_id; ar &g.domain_id;
ar & g.ordername; ar &g.ordername;
ar & g.auth; ar &g.auth;
} }
struct compound {
struct compound std::string operator()(const DNSResourceRecord &rr)
{
std::string operator()(const DNSResourceRecord& rr)
{ {
std::string ret; std::string ret;
uint32_t id = htonl(rr.domain_id); uint32_t id = htonl(rr.domain_id);
@ -62,168 +56,181 @@ struct compound
int main() int main()
{ {
TypedDBI<DNSResourceRecord, TypedDBI<DNSResourceRecord, index_on<DNSResourceRecord, string, &DNSResourceRecord::qname>,
index_on<DNSResourceRecord, string, &DNSResourceRecord::qname>, index_on<DNSResourceRecord, uint32_t, &DNSResourceRecord::domain_id>, index_on_function<DNSResourceRecord, string, compound>>
index_on<DNSResourceRecord, uint32_t, &DNSResourceRecord::domain_id>, tdbi(getMDBEnv("./typed.lmdb", MDB_NOSUBDIR, 0600), "records");
index_on_function<DNSResourceRecord, string, compound>
> tdbi(getMDBEnv("./typed.lmdb", MDB_NOSUBDIR, 0600), "records");
TypedDBI<DomainInfo,
index_on<DomainInfo, string, &DomainInfo::qname>
> tdomains(tdbi.getEnv(), "domains");
TypedDBI<DomainInfo, index_on<DomainInfo, string, &DomainInfo::qname>> tdomains(tdbi.getEnv(), "domains");
{ {
auto rotxn = tdbi.getROTransaction(); auto rotxn = tdbi.getROTransaction();
DNSResourceRecord rr0; DNSResourceRecord rr0;
if(rotxn.get(2, rr0)) { if (rotxn.get(2, rr0)) {
cout << "id 2, found "<<rr0.qname<<endl; cout << "id 2, found " << rr0.qname << endl;
} else {
cout << "Did not find id 2" << endl;
} }
else { cout << "Iterating over name 'powerdns.com': " << endl;
cout <<"Did not find id 2" << endl;
}
cout<<"Iterating over name 'powerdns.com': "<<endl;
auto range = rotxn.equal_range<0>("powerdns.com"); auto range = rotxn.equal_range<0>("powerdns.com");
for(auto iter = std::move(range.first); iter != range.second; ++iter) for (auto iter = std::move(range.first); iter != range.second; ++iter) {
{ cout << iter->qname << " " << iter->qtype << " " << iter->content << endl;
cout << iter->qname << " " << iter->qtype << " " <<iter->content <<endl;
} }
cout<<"Currently have "<< rotxn.size()<< " entries"<<endl; cout << "Currently have " << rotxn.size() << " entries" << endl;
cout<<" " << rotxn.size<0>() << " " << rotxn.size<1>() << " " << rotxn.size<2>() << endl; cout << " " << rotxn.size<0>() << " " << rotxn.size<1>() << " " << rotxn.size<2>() << endl;
cout<<" " << rotxn.cardinality<0>() << endl; cout << " " << rotxn.cardinality<0>() << endl;
cout<<" " << rotxn.cardinality<1>() << endl; cout << " " << rotxn.cardinality<1>() << endl;
cout<<" " << rotxn.cardinality<2>() << endl; cout << " " << rotxn.cardinality<2>() << endl;
} }
auto txn = tdbi.getRWTransaction(); auto txn = tdbi.getRWTransaction();
auto domtxn = tdomains.getRWTransaction(txn.getTransactionHandle()); auto domtxn = tdomains.getRWTransaction(txn.getTransactionHandle());
cout << domtxn.size()<<" domains in table"<<endl; cout << domtxn.size() << " domains in table" << endl;
txn.clear(); txn.clear();
domtxn.clear(); domtxn.clear();
cout<<"Currently have "<< txn.size()<< " entries after clear"<<endl; 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;
DomainInfo di{"powerdns.com", "ns1.powerdns.com"}; DomainInfo di{ "powerdns.com", "ns1.powerdns.com" };
domtxn.put(di, 11); domtxn.put(di, 11);
DNSResourceRecord rr; DNSResourceRecord rr;
rr.domain_id=11; 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.put(rr); auto id = txn.put(rr);
cout<<"Puted as id "<<id<<endl; cout << "Puted 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.put(rr); id = txn.put(rr);
cout<<"Puted as id "<<id<<endl; cout << "Puted as id " << id << endl;
rr.qtype = 2; rr.content = "ns1.powerdns.com"; rr.ordername = "ns1"; rr.qtype = 2;
rr.content = "ns1.powerdns.com";
rr.ordername = "ns1";
id = txn.put(rr); id = txn.put(rr);
cout<<"Puted as id "<<id<<endl; cout << "Puted as id " << id << endl;
rr.content = "ns2.powerdns.com"; rr.ordername = "ns2"; id = txn.put(rr); rr.content = "ns2.powerdns.com";
cout<<"Puted as id "<<id<<endl; rr.ordername = "ns2";
id = txn.put(rr);
cout << "Puted as id " << id << endl;
DomainInfo di2{"ds9a.nl", "ns1.powerdns.com"}; DomainInfo di2{ "ds9a.nl", "ns1.powerdns.com" };
domtxn.put(di, 10); domtxn.put(di, 10);
rr.qname = "www.ds9a.nl";
rr.qname = "www.ds9a.nl"; rr.domain_id = 10; rr.content = "1.2.3.4"; rr.qtype = 1; rr.domain_id = 10;
rr.ordername="www"; rr.content = "1.2.3.4";
rr.qtype = 1;
rr.ordername = "www";
txn.put(rr); txn.put(rr);
rr.qname = "ds9a.nl"; rr.content = "ns1.ds9a.nl bert.ds9a.nl 1"; rr.qtype = 6; rr.qname = "ds9a.nl";
rr.ordername=""; rr.content = "ns1.ds9a.nl bert.ds9a.nl 1";
rr.qtype = 6;
rr.ordername = "";
txn.put(rr); txn.put(rr);
rr.qname = "ds9a.nl"; rr.content = "25 ns1.ds9a.nl"; rr.qtype = 15; rr.qname = "ds9a.nl";
rr.content = "25 ns1.ds9a.nl";
rr.qtype = 15;
txn.put(rr); txn.put(rr);
rr.qname = "ns1.ds9a.nl"; rr.content = "1.2.3.4"; rr.qtype = 1; rr.qname = "ns1.ds9a.nl";
rr.ordername="ns1"; rr.content = "1.2.3.4";
rr.qtype = 1;
rr.ordername = "ns1";
txn.put(rr); txn.put(rr);
rr.qname = "ns1.ds9a.nl"; rr.content = "::1"; rr.qtype = 26; rr.qname = "ns1.ds9a.nl";
rr.content = "::1";
rr.qtype = 26;
txn.put(rr); txn.put(rr);
rr.qname = "ns2.ds9a.nl"; rr.content = "1.2.3.4"; rr.qtype = 1; rr.qname = "ns2.ds9a.nl";
rr.ordername="ns2"; rr.content = "1.2.3.4";
rr.qtype = 1;
rr.ordername = "ns2";
txn.put(rr); txn.put(rr);
rr.qname = "ns2.ds9a.nl"; rr.content = "::1"; rr.qtype = 26; rr.qname = "ns2.ds9a.nl";
rr.content = "::1";
rr.qtype = 26;
txn.put(rr); txn.put(rr);
DNSResourceRecord rr2; DNSResourceRecord rr2;
id = txn.get<0>("www.powerdns.com", rr2); id = txn.get<0>("www.powerdns.com", rr2);
cout<<"Retrieved id "<< id <<", content: "<<rr2.content<<endl; cout << "Retrieved id " << id << ", content: " << rr2.content << endl;
id = txn.get<0>("powerdns.com", rr2); id = txn.get<0>("powerdns.com", rr2);
cout<<"Retrieved id "<< id <<", content: "<<rr2.content<<endl; cout << "Retrieved id " << id << ", content: " << rr2.content << endl;
DNSResourceRecord rr3; DNSResourceRecord rr3;
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 everything, ordered by name!" << endl;
cout<<"Going to iterate over everything, ordered by name!"<<endl; for (auto iter = txn.begin<0>(); iter != txn.end(); ++iter) {
for(auto iter = txn.begin<0>(); iter != txn.end(); ++iter) { cout << iter.getID() << ": " << iter->qname << " " << iter->qtype << " " << iter->content << endl;
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl;
} }
cout<<"Going to iterate over everything, ordered by domain_id!"<<endl; cout << "Going to iterate over everything, ordered by domain_id!" << endl;
for(auto iter = txn.begin<1>(); iter != txn.end(); ++iter) { for (auto iter = txn.begin<1>(); iter != txn.end(); ++iter) {
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl; 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) { for (auto iter = txn.begin(); iter != txn.end(); ++iter) {
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<endl; cout << iter.getID() << ": " << iter->qname << " " << iter->qtype << " " << iter->content << endl;
} }
cout<<"Going to iterate over everything, ordered by compound index!"<<endl; cout << "Going to iterate over everything, ordered by compound index!" << endl;
for(auto iter = txn.begin<2>(); iter != txn.end(); ++iter) { for (auto iter = txn.begin<2>(); iter != txn.end(); ++iter) {
cout << iter.getID()<<": "<<iter->qname << " " << iter->qtype << " " << iter->content <<" # "<<iter->ordername << endl; cout << iter.getID() << ": " << iter->qname << " " << iter->qtype << " " << iter->content << " # " << iter->ordername << endl;
} }
compound c; compound c;
rr3.ordername = "vvv"; rr3.ordername = "vvv";
rr3.domain_id = 10; rr3.domain_id = 10;
auto iter = txn.lower_bound<2>(c(rr3)); auto iter = txn.lower_bound<2>(c(rr3));
cout <<"Found for '"<<rr3.ordername<<"' using compound index: "<<iter->qname<< " # '" <<iter->ordername<< "'"<<endl; cout << "Found for '" << rr3.ordername << "' using compound index: " << iter->qname << " # '" << iter->ordername << "'" << endl;
for(int n =0 ; n < 4; ++n) { for (int n = 0; n < 4; ++n) {
--iter; --iter;
cout <<"Found PREV using compound index: "<<iter->qname<< " # '" <<iter->ordername<<"'"<<endl; cout << "Found PREV using compound index: " << iter->qname << " # '" << iter->ordername << "'" << endl;
} }
cout<<"Going to iterate over the name powerdns.com!"<<endl; cout << "Going to iterate over the name powerdns.com!" << endl;
for(auto iter2 = txn.equal_range<0>("powerdns.com"); iter2.first != iter2.second; ++iter2.first) { for (auto iter2 = txn.equal_range<0>("powerdns.com"); iter2.first != iter2.second; ++iter2.first) {
cout << iter2.first.getID()<<": "<<iter2.first->qname << " " << iter2.first->qtype << " " << iter2.first->content <<endl; cout << iter2.first.getID() << ": " << iter2.first->qname << " " << iter2.first->qtype << " " << iter2.first->content << endl;
} }
cout<<"Done iterating"<<endl; cout << "Done iterating" << endl;
cout<<"Going to iterate over the zone ds9a.nl!"<<endl; cout << "Going to iterate over the zone ds9a.nl!" << endl;
for(auto iter2 = txn.find<1>(10); iter2 != txn.end(); ++iter2) { for (auto iter2 = txn.find<1>(10); iter2 != txn.end(); ++iter2) {
cout << iter2.getID()<<": "<<iter2->qname << " " << iter2->qtype << " " << iter2->content <<endl; cout << iter2.getID() << ": " << iter2->qname << " " << iter2->qtype << " " << iter2->content << endl;
} }
cout<<"Done iterating"<<endl; cout << "Done iterating" << endl;
DNSResourceRecord change; DNSResourceRecord change;
txn.get(1, change); txn.get(1, change);
cout<<"1.auth: "<<change.auth << endl; cout << "1.auth: " << change.auth << endl;
txn.modify(1, [](DNSResourceRecord& record) { txn.modify(1, [](DNSResourceRecord &record) { record.auth = false; });
record.auth = false;
});
txn.get(1, change); txn.get(1, change);
cout<<"1.auth: "<<change.auth << endl; cout << "1.auth: " << change.auth << endl;
txn.del(1); txn.del(1);
// DNSResourceRecord rr4; // DNSResourceRecord rr4;

View File

@ -7,26 +7,25 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
void countDB(MDBEnv& env, MDBROTransaction& txn, const std::string& dbname) void countDB(MDBEnv &env, MDBROTransaction &txn, const std::string &dbname)
{ {
CPP_UTILITIES_UNUSED(env) CPP_UTILITIES_UNUSED(env)
auto db = txn->openDB(dbname, 0); auto db = txn->openDB(dbname, 0);
auto cursor = txn->getCursor(db); auto cursor = txn->getCursor(db);
uint32_t count = 0; uint32_t count = 0;
MDBOutVal key, val; MDBOutVal key, val;
while(!cursor.get(key, val, count ? MDB_NEXT : MDB_FIRST)) { while (!cursor.get(key, val, count ? MDB_NEXT : MDB_FIRST)) {
cout << key.get<string>(); cout << key.get<string>();
if(key.d_mdbval.mv_size == 4) if (key.d_mdbval.mv_size == 4)
cout << " " << key.get<uint32_t>(); cout << " " << key.get<uint32_t>();
cout<<": " << val.get<std::string>(); cout << ": " << val.get<std::string>();
cout << "\n"; cout << "\n";
++count; ++count;
} }
cout <<count<<endl; cout << count << endl;
} }
int main(int argc, char** argv) int main(int argc, char **argv)
{ {
MDBEnv env(argc >= 2 ? argv[1] : "./database", MDB_RDONLY | MDB_NOSUBDIR, 0600); MDBEnv env(argc >= 2 ? argv[1] : "./database", MDB_RDONLY | MDB_NOSUBDIR, 0600);
auto main = env.openDB("", 0); auto main = env.openDB("", 0);
@ -35,13 +34,11 @@ int main(int argc, char** argv)
auto cursor = txn->getCursor(main); auto cursor = txn->getCursor(main);
MDBOutVal key, val; MDBOutVal key, val;
if(cursor.get(key, val, MDB_FIRST)) { if (cursor.get(key, val, MDB_FIRST)) {
cout << "Database is empty" <<endl; cout << "Database is empty" << endl;
} }
do { do {
cout << key.get<string>() << endl; cout << key.get<string>() << endl;
countDB(env, txn, key.get<string>()); countDB(env, txn, key.get<string>());
} while(!cursor.get(key, val, MDB_NEXT)); } while (!cursor.get(key, val, MDB_NEXT));
} }

View File

@ -10,7 +10,8 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
TEST_CASE("Most basic tests", "[mostbasic]") { TEST_CASE("Most basic tests", "[mostbasic]")
{
unlink("./tests"); unlink("./tests");
MDBEnv env("./tests", MDB_NOSUBDIR, 0600); MDBEnv env("./tests", MDB_NOSUBDIR, 0600);
@ -33,7 +34,8 @@ TEST_CASE("Most basic tests", "[mostbasic]") {
REQUIRE(rotxn->get(main, "lmdb", out) == MDB_NOTFOUND); REQUIRE(rotxn->get(main, "lmdb", out) == MDB_NOTFOUND);
} }
TEST_CASE("Range tests", "[range]") { TEST_CASE("Range tests", "[range]")
{
unlink("./tests"); unlink("./tests");
MDBEnv env("./tests", MDB_NOSUBDIR, 0600); MDBEnv env("./tests", MDB_NOSUBDIR, 0600);
@ -92,7 +94,6 @@ TEST_CASE("Range tests", "[range]") {
REQUIRE(cursor.lower_bound("kees", key, val) == MDB_NOTFOUND); REQUIRE(cursor.lower_bound("kees", key, val) == MDB_NOTFOUND);
} }
} }
TEST_CASE("moving transactions") TEST_CASE("moving transactions")
@ -149,7 +150,7 @@ TEST_CASE("transaction inheritance and moving")
// aborting by default) // aborting by default)
} }
CHECK(!const_cast<const MDBRWCursor&>(cursor)); CHECK(!const_cast<const MDBRWCursor &>(cursor));
} }
TEST_CASE("nested RW transactions", "[transactions]") TEST_CASE("nested RW transactions", "[transactions]")
@ -203,7 +204,6 @@ TEST_CASE("nested RW transactions", "[transactions]")
CHECK(main_txn->get(main, "bertt", dummy) == MDB_NOTFOUND); CHECK(main_txn->get(main, "bertt", dummy) == MDB_NOTFOUND);
} }
TEST_CASE("nesting RW -> RO", "[transactions]") TEST_CASE("nesting RW -> RO", "[transactions]")
{ {
unlink("./tests"); unlink("./tests");
@ -289,10 +289,7 @@ TEST_CASE("try to nest twice", "[transactions]")
sub_txn->del(main, "berthubert", "lmdb"); sub_txn->del(main, "berthubert", "lmdb");
CHECK(sub_txn->get(main, "berthubert", dummy) == MDB_NOTFOUND); CHECK(sub_txn->get(main, "berthubert", dummy) == MDB_NOTFOUND);
CHECK_THROWS_AS( CHECK_THROWS_AS(main_txn->getRWTransaction(), std::runtime_error);
main_txn->getRWTransaction(),
std::runtime_error
);
} }
} }

View File

@ -13,36 +13,33 @@
using namespace std; using namespace std;
using namespace LMDBSafe; using namespace LMDBSafe;
struct Member struct Member {
{
std::string firstName; std::string firstName;
std::string lastName; std::string lastName;
time_t enrolled; time_t enrolled;
}; };
template<class Archive> template <class Archive> void serialize(Archive &ar, Member &g, const unsigned int version)
void serialize(Archive & ar, Member& g, const unsigned int version)
{ {
CPP_UTILITIES_UNUSED(version) CPP_UTILITIES_UNUSED(version)
ar & g.firstName & g.lastName & g.enrolled; ar &g.firstName &g.lastName &g.enrolled;
} }
TEST_CASE("Basic typed tests", "[basictyped]") { TEST_CASE("Basic typed tests", "[basictyped]")
{
unlink("./tests-typed"); unlink("./tests-typed");
typedef TypedDBI<Member, typedef TypedDBI<Member, index_on<Member, string, &Member::firstName>, index_on<Member, string, &Member::lastName>,
index_on<Member, string, &Member::firstName>, index_on<Member, time_t, &Member::enrolled>>
index_on<Member, string, &Member::lastName>, tmembers_t;
index_on<Member, time_t, &Member::enrolled>
> tmembers_t;
auto tmembers = tmembers_t(getMDBEnv("./tests-typed", MDB_CREATE | MDB_NOSUBDIR, 0600), "members"); auto tmembers = tmembers_t(getMDBEnv("./tests-typed", MDB_CREATE | MDB_NOSUBDIR, 0600), "members");
REQUIRE(1); REQUIRE(1);
auto txn = tmembers.getRWTransaction(); auto txn = tmembers.getRWTransaction();
Member m{"bert", "hubert"}; Member m{ "bert", "hubert" };
txn.put(m); txn.put(m);
m.firstName="bertus"; m.firstName = "bertus";
m.lastName = "testperson"; m.lastName = "testperson";
m.enrolled = time(0); m.enrolled = time(0);
txn.put(m); txn.put(m);
@ -51,19 +48,19 @@ TEST_CASE("Basic typed tests", "[basictyped]") {
txn.put(m); txn.put(m);
Member out; Member out;
REQUIRE(txn.get(1,out)); REQUIRE(txn.get(1, out));
REQUIRE(out.firstName == "bert"); REQUIRE(out.firstName == "bert");
REQUIRE(txn.get(2,out)); REQUIRE(txn.get(2, out));
REQUIRE(out.lastName == "testperson"); REQUIRE(out.lastName == "testperson");
REQUIRE(!txn.get(4,out)); REQUIRE(!txn.get(4, out));
auto range = txn.prefix_range<0>("bert"); auto range = txn.prefix_range<0>("bert");
vector<std::string> names; vector<std::string> names;
for(auto& iter = range.first; iter != range.second; ++iter) { for (auto &iter = range.first; iter != range.second; ++iter) {
names.push_back(iter->firstName); names.push_back(iter->firstName);
} }
REQUIRE(names == vector<std::string>{"bert", "bertus"}); REQUIRE(names == vector<std::string>{ "bert", "bertus" });
auto range2 = txn.prefix_range<0>("nosuchperson"); auto range2 = txn.prefix_range<0>("nosuchperson");
REQUIRE(!(range2.first == range2.second)); REQUIRE(!(range2.first == range2.second));