This commit is contained in:
bert hubert 2018-12-07 18:17:03 +01:00
parent 9eafb01508
commit e664945846
4 changed files with 113 additions and 28 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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)

View File

@ -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");