From 34f8c2188c115bc4928775e191b56e0ad4a07a0e Mon Sep 17 00:00:00 2001 From: bert hubert Date: Mon, 10 Dec 2018 17:42:25 +0100 Subject: [PATCH] better docs --- README.md | 72 ++++++++++++++++++++++++++++++++++++++++++++---- lmdb-safe.hh | 8 ++++++ multi-example.cc | 9 ++---- scale-example.cc | 7 +++-- 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 69eed4f..34956dc 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ MDB handles are all available should you want to use functionality we did not (yet) cater for. # Status -Very early. If using this tiny library, be aware things might change +Fresh. If using this tiny library, be aware things might change rapidly. To use, add `lmdb-safe.cc` and `lmdb-safe.hh` to your project. # Philosophy @@ -110,6 +110,67 @@ available for other threads and processes. A slightly expanded version of this code can be found in [basic-example.cc](basic-example.cc). +# Input and output of values +The basic data unit of LMDB is `MDB_val` which describes a slab of memory. +Within LMDB, `MDB_val` is used for both input and output. For safety +purposes, in this library we split this up into `MDBInValue` and +`MDBOutValue`. Once split, we can add some very convenient semantics to these +classes. + +For example, to store `double` values for 64 bit IDs: + +``` + auto txn = env->getRWTransaction(); + uint64_t id=12345678901; + double score=3.14159; + txn.put(dbi, id, score); + txn.commit(); +``` + +Behind the scenes, the `id` and `score` values are wrapped by `MDBInVal` +which converts these values into byte strings. To retrieve thise values +works similary: + +``` + auto txn = env->getRWTransaction(); + uint64_t id=12345678901; + MDBOutValue val; + + txn.get(dbi, id, val); + + cout << "Score: " << val.get() << "\n"; +``` + +Note that on retrieval, we have to specify the type of the value stored. +This allows the conversion back from a byte string into the native type. +`MDBOutValue` also tests if the length of the data matches the type. + +## Details +The automatic conversion to and from the `MDBVal`s is implemented strictly +for: + + * Integer and floating point types + * std::string + * std::string_view + +However, if you explicitly ask for it, it is also possible to serialize +`struct`s: + +``` +struct Coordinate +{ + double x,y; +}; + +C c{12.0, 13.0}; + +txn.put(dbi, MDBInVal::fromStruct(c), 12.0); + +MDBOutVal res; +txn.get(dbi, MDBInVal::fromStruct(c), res); + +auto c1 = res.get_struct(); +``` # Cursors, transactions This example shows how to use cursors and how to mix `lmdb-safe` with direct @@ -127,7 +188,7 @@ This is the usual opening sequence. ``` auto cursor=txn.getCursor(dbi); - MDB_val key, data; + MDBOutVal key, data; int count=0; cout<<"Counting records.. "; cout.flush(); while(!cursor.get(key, data, count ? MDB_NEXT : MDB_FIRST)) { @@ -157,7 +218,7 @@ native `mdb_drop` function which we did not wrap. This is possible because ``` cout << "Adding "<(&key.d_mdbval), &data.d_mdbval, MDB_SET); + } + + int put(const MDBOutVal& key, const MDBOutVal& data, int flags=0) { return mdb_cursor_put(d_cursor, diff --git a/multi-example.cc b/multi-example.cc index 2a681ce..d751c91 100644 --- a/multi-example.cc +++ b/multi-example.cc @@ -26,15 +26,10 @@ int main() txn = env->getRWTransaction(); auto cursor = txn.getCursor(dbi); - int count=0; MDBOutVal key, data; - MDBInVal start("lmdb"); - key.d_mdbval = start.d_mdbval; - int rc=0; - while(!(rc=cursor.get(key, data, count ? MDB_NEXT_DUP : MDB_SET))) { - cout << key.get() << " = " << data.get() <() << " = " << data.get() <openDB("huge", MDB_CREATE | MDB_INTEGERKEY); + auto dbi = env->openDB(0, MDB_CREATE | MDB_INTEGERKEY); auto txn = env->getRWTransaction(); unsigned int limit=20000000; @@ -32,6 +32,9 @@ int main(int argc, char** argv) MDBOutVal key, data; int count=0; while(!cursor.get(key, data, count ? MDB_NEXT : MDB_FIRST)) { + auto d = data.get(); + if(d==17) + cout <<"Got 17!"<