diff --git a/lmdb-safe.cc b/lmdb-safe.cc index f2e5194..6b73d1f 100644 --- a/lmdb-safe.cc +++ b/lmdb-safe.cc @@ -147,6 +147,13 @@ MDBDbi MDBEnv::openDB(const char* dbname, int flags) return rwt.openDB(dbname, flags); } +void MDBRWTransaction::clear(MDB_dbi dbi) +{ + if(int rc = mdb_drop(d_txn, dbi, 0)) { + throw runtime_error("Error clearing database: " + MDBError(rc)); + } +} + MDBRWCursor MDBRWTransaction::getCursor(const MDBDbi& dbi) { return MDBRWCursor(this, dbi); diff --git a/lmdb-safe.hh b/lmdb-safe.hh index c290147..4e43d90 100644 --- a/lmdb-safe.hh +++ b/lmdb-safe.hh @@ -271,6 +271,8 @@ public: d_parent->decRWTX(); } + void clear(MDB_dbi dbi); + void put(MDB_dbi dbi, const MDB_val& key, const MDB_val& val, int flags=0) { if(!d_txn) @@ -318,6 +320,11 @@ public: { d_cursors.insert(child); } + void unreportCursor(MDBRWCursor* child) + { + d_cursors.erase(child); + } + void reportCursorMove(MDBRWCursor* from, MDBRWCursor* to) { d_cursors.erase(from); @@ -370,11 +377,15 @@ public: { if(d_cursor) mdb_cursor_close(d_cursor); + d_parent->unreportCursor(this); } int get(MDB_val& key, MDB_val& data, MDB_cursor_op op) { - return mdb_cursor_get(d_cursor, &key, &data, op); + int rc = mdb_cursor_get(d_cursor, &key, &data, op); + if(rc && rc != MDB_NOTFOUND) + throw std::runtime_error("mdb_cursor_get: " + string(mdb_strerror(rc))); + return rc; } int put(MDB_val& key, MDB_val& data, int flags=0) diff --git a/multi-example.cc b/multi-example.cc new file mode 100644 index 0000000..c872795 --- /dev/null +++ b/multi-example.cc @@ -0,0 +1,38 @@ +#include "lmdb-safe.hh" + +int main() +{ + auto env = getMDBEnv("multi", 0, 0600); + auto dbi = env->openDB("qnames", MDB_DUPSORT | MDB_CREATE); + + auto txn = env->getRWTransaction(); + txn.clear(dbi); + + txn.put(dbi, "bdb", "old"); + txn.put(dbi, "lmdb", "hot"); + txn.put(dbi, "lmdb", "fast"); + txn.put(dbi, "lmdb", "zooms"); + txn.put(dbi, "mdb", "old name"); + + std::string_view v1; + if(!txn.get(dbi, "mdb", v1)) { + cout<getRWTransaction(); + auto cursor = txn.getCursor(dbi); + int count=0; + MDB_val key{4, (char*)"lmdb"}; + MDB_val data{0,0}; + int rc=0; + while(!(rc=cursor.get(key, data, count ? MDB_NEXT_DUP : MDB_SET))) { + std::string_view k((char*)key.mv_data, key.mv_size); + std::string_view v((char*)data.mv_data, data.mv_size); + cout << k << " = " << v <