wip
This commit is contained in:
parent
9eafb01508
commit
e664945846
6
Makefile
6
Makefile
|
@ -1,8 +1,8 @@
|
|||
|
||||
#LIBS=lmdb-0.9.21/libraries/liblmdb/liblmdb.a
|
||||
#INCLUDES=-Ilmdb-0.9.21/libraries/liblmdb/liblmdb
|
||||
LIBS=lmdb-LMDB_0.9.22/libraries/liblmdb/liblmdb.a
|
||||
INCLUDES=-Ilmdb-LMDB_0.9.22/libraries/liblmdb
|
||||
|
||||
LIBS=-llmdb
|
||||
#LIBS=-llmdb
|
||||
CXXFLAGS:=-std=gnu++11 -Wall -O2 -MMD -MP -ggdb -pthread $(INCLUDES)
|
||||
CFLAGS:= -Wall -O2 -MMD -MP -ggdb
|
||||
|
||||
|
|
62
lmdb-safe.cc
62
lmdb-safe.cc
|
@ -1,4 +1,66 @@
|
|||
#include "lmdb-safe.hh"
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int mode, int flags)
|
||||
{
|
||||
struct Value
|
||||
{
|
||||
weak_ptr<MDBEnv> wp;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static std::map<tuple<dev_t, ino_t>, Value> s_envs;
|
||||
static std::mutex mut;
|
||||
|
||||
struct stat statbuf;
|
||||
if(stat(fname, &statbuf)) {
|
||||
if(errno != ENOENT)
|
||||
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
|
||||
else {
|
||||
std::lock_guard<std::mutex> l(mut);
|
||||
cout<<"Making a fresh one, file did not exist yet"<<endl;
|
||||
auto fresh = std::make_shared<MDBEnv>(fname, mode, flags);
|
||||
if(stat(fname, &statbuf))
|
||||
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
|
||||
auto key = std::tie(statbuf.st_dev, statbuf.st_ino);
|
||||
s_envs[key] = {fresh, flags};
|
||||
return fresh;
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> l(mut);
|
||||
auto key = std::tie(statbuf.st_dev, statbuf.st_ino);
|
||||
auto iter = s_envs.find(key);
|
||||
if(iter != s_envs.end()) {
|
||||
cout<<"Found something!"<<endl;
|
||||
|
||||
auto sp = iter->second.wp.lock();
|
||||
if(sp) {
|
||||
if(iter->second.flags != flags)
|
||||
throw std::runtime_error("Can't open mdb with differing flags");
|
||||
|
||||
cout<<"It was live!"<<endl;
|
||||
return sp;
|
||||
}
|
||||
else {
|
||||
cout<<"It was dead already"<<endl;
|
||||
s_envs.erase(iter); // useful if make_shared fails
|
||||
}
|
||||
}
|
||||
else
|
||||
cout<<"Found nothing"<<endl;
|
||||
cout<<"Making a fresh one"<<endl;
|
||||
auto fresh = std::make_shared<MDBEnv>(fname, mode, flags);
|
||||
s_envs[key] = {fresh, flags};
|
||||
|
||||
return fresh;
|
||||
}
|
||||
|
||||
|
||||
MDBDbi MDBEnv::openDB(const char* dbname, int flags)
|
||||
{
|
||||
|
|
33
lmdb-safe.hh
33
lmdb-safe.hh
|
@ -2,6 +2,9 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -69,6 +72,9 @@ public:
|
|||
class MDBRWTransaction;
|
||||
class MDBROTransaction;
|
||||
|
||||
|
||||
|
||||
|
||||
class MDBEnv
|
||||
{
|
||||
public:
|
||||
|
@ -111,10 +117,13 @@ Various other options may also need to be set before opening the handle, e.g. md
|
|||
return d_env;
|
||||
}
|
||||
MDB_env* d_env;
|
||||
bool d_transactionOut{false};
|
||||
std::map<std::thread::id, int> d_RWtransactionsOut;
|
||||
std::map<std::thread::id, int> d_ROtransactionsOut;
|
||||
|
||||
};
|
||||
|
||||
std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int mode, int flags);
|
||||
|
||||
class MDBROCursor;
|
||||
|
||||
class MDBROTransaction
|
||||
|
@ -122,7 +131,7 @@ class MDBROTransaction
|
|||
public:
|
||||
explicit MDBROTransaction(MDBEnv* parent, int flags=0) : d_parent(parent)
|
||||
{
|
||||
if(d_parent->d_transactionOut)
|
||||
if(d_parent->d_RWtransactionsOut[std::this_thread::get_id()])
|
||||
throw std::runtime_error("Duplicate transaction");
|
||||
|
||||
/*
|
||||
|
@ -130,7 +139,9 @@ public:
|
|||
|
||||
if(mdb_txn_begin(d_parent->d_env, 0, MDB_RDONLY | flags, &d_txn))
|
||||
throw std::runtime_error("Unable to start RO transaction");
|
||||
++d_parent->d_ROtransactionsOut[std::this_thread::get_id()];
|
||||
}
|
||||
|
||||
|
||||
MDBROTransaction(MDBROTransaction&& rhs)
|
||||
{
|
||||
|
@ -144,14 +155,14 @@ public:
|
|||
{
|
||||
// this does not free cursors
|
||||
mdb_txn_reset(d_txn);
|
||||
d_parent->d_transactionOut=false;
|
||||
--d_parent->d_ROtransactionsOut[std::this_thread::get_id()];
|
||||
}
|
||||
|
||||
void renew()
|
||||
{
|
||||
if(d_parent->d_transactionOut)
|
||||
if(d_parent->d_RWtransactionsOut[std::this_thread::get_id()])
|
||||
throw std::runtime_error("Duplicate transaction");
|
||||
d_parent->d_transactionOut=1;
|
||||
d_parent->d_ROtransactionsOut[std::this_thread::get_id()]++;
|
||||
if(mdb_txn_renew(d_txn))
|
||||
throw std::runtime_error("Renewing transaction");
|
||||
}
|
||||
|
@ -173,7 +184,7 @@ public:
|
|||
~MDBROTransaction()
|
||||
{
|
||||
if(d_txn) {
|
||||
d_parent->d_transactionOut=false;
|
||||
--d_parent->d_ROtransactionsOut[std::this_thread::get_id()];
|
||||
mdb_txn_commit(d_txn); // this appears to work better than abort for r/o database opening
|
||||
}
|
||||
}
|
||||
|
@ -239,9 +250,9 @@ class MDBRWTransaction
|
|||
public:
|
||||
explicit MDBRWTransaction(MDBEnv* parent, int flags=0) : d_parent(parent)
|
||||
{
|
||||
if(d_parent->d_transactionOut)
|
||||
if(d_parent->d_ROtransactionsOut[std::this_thread::get_id()] || d_parent->d_RWtransactionsOut[std::this_thread::get_id()])
|
||||
throw std::runtime_error("Duplicate transaction");
|
||||
d_parent->d_transactionOut = true;
|
||||
++d_parent->d_RWtransactionsOut[std::this_thread::get_id()];
|
||||
if(int rc=mdb_txn_begin(d_parent->d_env, 0, flags, &d_txn))
|
||||
throw std::runtime_error("Unable to start RW transaction: "+std::string(mdb_strerror(rc)));
|
||||
}
|
||||
|
@ -270,7 +281,7 @@ public:
|
|||
~MDBRWTransaction()
|
||||
{
|
||||
if(d_txn) {
|
||||
d_parent->d_transactionOut=false;
|
||||
--d_parent->d_RWtransactionsOut[std::this_thread::get_id()];
|
||||
closeCursors();
|
||||
mdb_txn_abort(d_txn);
|
||||
}
|
||||
|
@ -283,7 +294,7 @@ public:
|
|||
if(mdb_txn_commit(d_txn)) {
|
||||
throw std::runtime_error("committing");
|
||||
}
|
||||
d_parent->d_transactionOut=false;
|
||||
--d_parent->d_RWtransactionsOut[std::this_thread::get_id()];
|
||||
|
||||
d_txn=0;
|
||||
}
|
||||
|
@ -293,7 +304,7 @@ public:
|
|||
closeCursors();
|
||||
mdb_txn_abort(d_txn);
|
||||
d_txn = 0;
|
||||
d_parent->d_transactionOut=false;
|
||||
--d_parent->d_RWtransactionsOut[std::this_thread::get_id()];
|
||||
}
|
||||
|
||||
void put(MDB_dbi dbi, const MDB_val& key, const MDB_val& val, int flags)
|
||||
|
|
40
lmdb-test.cc
40
lmdb-test.cc
|
@ -3,17 +3,29 @@
|
|||
#include <string.h>
|
||||
#include "lmdb-safe.hh"
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
static void closeTest()
|
||||
{
|
||||
MDBEnv env("./database", MDB_RDONLY, 0600);
|
||||
int c= MDB_CREATE;
|
||||
MDBDbi dbi = env.openDB("ahu", c);
|
||||
MDBDbi main = env.openDB(0, c);
|
||||
MDBDbi hyc = env.openDB("hyc2", c);
|
||||
auto env = getMDBEnv("./database", 0, 0600);
|
||||
|
||||
int c = MDB_CREATE;
|
||||
MDBDbi dbi = env->openDB("ahu", c);
|
||||
MDBDbi main = env->openDB(0, c);
|
||||
MDBDbi hyc = env->openDB("hyc", c);
|
||||
|
||||
auto txn = env.getROTransaction();
|
||||
auto cursor = txn.getCursor(dbi);
|
||||
auto txn = env->getROTransaction();
|
||||
for(auto& d : {&main, &dbi, &hyc}) {
|
||||
auto rocursor = txn.getCursor(*d);
|
||||
MDB_val key{0,0}, data{0,0};
|
||||
if(rocursor.get(key, data, MDB_FIRST))
|
||||
continue;
|
||||
int count=0;
|
||||
do {
|
||||
count++;
|
||||
}while(!rocursor.get(key, data, MDB_NEXT));
|
||||
cout<<"Have "<<count<<" entries"<<endl;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -21,18 +33,18 @@ static void closeTest()
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
cout<<std::this_thread::get_id()<<endl;
|
||||
closeTest();
|
||||
return 0;
|
||||
MDBEnv env("./database", 0, 0600);
|
||||
auto env = getMDBEnv("./database", 0, 0600);
|
||||
|
||||
MDB_stat stat;
|
||||
mdb_env_stat(env, &stat);
|
||||
mdb_env_stat(*env.get(), &stat);
|
||||
cout << stat.ms_entries<< " entries in database"<<endl;
|
||||
|
||||
MDBDbi dbi = env.openDB("ahu", MDB_CREATE);
|
||||
MDBDbi dbi = env->openDB("ahu", MDB_CREATE);
|
||||
|
||||
{
|
||||
MDBROTransaction rotxn = env.getROTransaction();
|
||||
MDBROTransaction rotxn = env->getROTransaction();
|
||||
|
||||
{
|
||||
auto rocursor = rotxn.getCursor(dbi);
|
||||
|
@ -68,7 +80,7 @@ int main(int argc, char** argv)
|
|||
|
||||
}
|
||||
|
||||
auto txn = env.getRWTransaction();
|
||||
auto txn = env->getRWTransaction();
|
||||
|
||||
auto cursor = txn.getCursor(dbi);
|
||||
|
||||
|
@ -87,7 +99,7 @@ int main(int argc, char** argv)
|
|||
cout<<"Done deleting, committing"<<endl;
|
||||
txn.commit();
|
||||
cout<<"Done with commit"<<endl;
|
||||
txn = env.getRWTransaction();
|
||||
txn = env->getRWTransaction();
|
||||
|
||||
start=time(0);
|
||||
ofstream plot("plot");
|
||||
|
|
Loading…
Reference in New Issue