unify RO and RW cursor operations, move serFromString to a view

This commit is contained in:
bert hubert 2019-01-09 09:58:04 +01:00
parent 7dac111b02
commit bdcd9150a9
2 changed files with 82 additions and 78 deletions

View File

@ -294,35 +294,12 @@ public:
"If the parent transaction commits, the cursor must not be used again." "If the parent transaction commits, the cursor must not be used again."
*/ */
class MDBROCursor template<class Transaction>
class MDBGenCursor
{ {
public: public:
MDBROCursor(MDBROTransaction* parent, const MDB_dbi& dbi) : d_parent(parent) MDBGenCursor(Transaction *t) : d_parent(t)
{ {}
int rc= mdb_cursor_open(d_parent->d_txn, dbi, &d_cursor);
if(rc) {
throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc)));
}
}
MDBROCursor(MDBROCursor&& rhs)
{
d_cursor = rhs.d_cursor;
rhs.d_cursor=0;
}
void close()
{
mdb_cursor_close(d_cursor);
d_cursor=0;
}
~MDBROCursor()
{
if(d_cursor)
mdb_cursor_close(d_cursor);
}
int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
{ {
int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op); int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
@ -339,7 +316,7 @@ public:
throw std::runtime_error("Unable to find from cursor: " + std::string(mdb_strerror(rc))); throw std::runtime_error("Unable to find from cursor: " + std::string(mdb_strerror(rc)));
return rc; return rc;
} }
int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
{ {
key.d_mdbval = in.d_mdbval; key.d_mdbval = in.d_mdbval;
@ -350,16 +327,78 @@ public:
return rc; return rc;
} }
int nextprev(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
{
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, op);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to prevnext from cursor: " + std::string(mdb_strerror(rc)));
return rc;
}
int next(MDBOutVal& key, MDBOutVal& data) int next(MDBOutVal& key, MDBOutVal& data)
{ {
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_NEXT); return nextprev(key, data, MDB_NEXT);
}
int prev(MDBOutVal& key, MDBOutVal& data)
{
return nextprev(key, data, MDB_PREV);
}
int currentlast(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
{
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, op);
if(rc && rc != MDB_NOTFOUND) if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to next from cursor: " + std::string(mdb_strerror(rc))); throw std::runtime_error("Unable to next from cursor: " + std::string(mdb_strerror(rc)));
return rc; return rc;
} }
int current(MDBOutVal& key, MDBOutVal& data)
{
return currentlast(key, data, MDB_GET_CURRENT);
}
int last(MDBOutVal& key, MDBOutVal& data)
{
return currentlast(key, data, MDB_LAST);
}
operator MDB_cursor*&()
{
return d_cursor;
}
MDB_cursor* d_cursor; MDB_cursor* d_cursor;
MDBROTransaction* d_parent; Transaction* d_parent;
};
class MDBROCursor : public MDBGenCursor<MDBROTransaction>
{
public:
MDBROCursor(MDBROTransaction* parent, const MDB_dbi& dbi) : MDBGenCursor<MDBROTransaction>(parent)
{
int rc= mdb_cursor_open(d_parent->d_txn, dbi, &d_cursor);
if(rc) {
throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc)));
}
}
MDBROCursor(MDBROCursor&& rhs) : MDBGenCursor<MDBROTransaction>(rhs.d_parent)
{
rhs.d_cursor=0;
}
void close()
{
mdb_cursor_close(d_cursor);
d_cursor=0;
}
~MDBROCursor()
{
if(d_cursor)
mdb_cursor_close(d_cursor);
}
}; };
class MDBRWCursor; class MDBRWCursor;
@ -510,10 +549,10 @@ public:
/* "A cursor in a write-transaction can be closed before its transaction ends, and will otherwise be closed when its transaction ends" /* "A cursor in a write-transaction can be closed before its transaction ends, and will otherwise be closed when its transaction ends"
This is a problem for us since it may means we are closing the cursor twice, which is bad This is a problem for us since it may means we are closing the cursor twice, which is bad
*/ */
class MDBRWCursor class MDBRWCursor : public MDBGenCursor<MDBRWTransaction>
{ {
public: public:
MDBRWCursor(MDBRWTransaction* parent, const MDB_dbi& dbi) : d_parent(parent) MDBRWCursor(MDBRWTransaction* parent, const MDB_dbi& dbi) : MDBGenCursor<MDBRWTransaction>(parent)
{ {
int rc= mdb_cursor_open(d_parent->d_txn, dbi, &d_cursor); int rc= mdb_cursor_open(d_parent->d_txn, dbi, &d_cursor);
if(rc) { if(rc) {
@ -521,9 +560,8 @@ public:
} }
d_parent->reportCursor(this); d_parent->reportCursor(this);
} }
MDBRWCursor(MDBRWCursor&& rhs) MDBRWCursor(MDBRWCursor&& rhs) : MDBGenCursor<MDBRWTransaction>(rhs.d_parent)
{ {
d_parent = rhs.d_parent;
d_cursor = rhs.d_cursor; d_cursor = rhs.d_cursor;
rhs.d_cursor=0; rhs.d_cursor=0;
d_parent->reportCursorMove(&rhs, this); d_parent->reportCursorMove(&rhs, this);
@ -543,12 +581,14 @@ public:
d_parent->unreportCursor(this); d_parent->unreportCursor(this);
} }
int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
void put(const MDBOutVal& key, const MDBInVal& data)
{ {
int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op); int rc = mdb_cursor_put(d_cursor,
if(rc && rc != MDB_NOTFOUND) const_cast<MDB_val*>(&key.d_mdbval),
throw std::runtime_error("mdb_cursor_get: " + std::string(mdb_strerror(rc))); const_cast<MDB_val*>(&data.d_mdbval), MDB_CURRENT);
return rc; if(rc)
throw std::runtime_error("mdb_cursor_put: " + std::string(mdb_strerror(rc)));
} }
@ -560,45 +600,9 @@ public:
const_cast<MDB_val*>(&data.d_mdbval), flags); const_cast<MDB_val*>(&data.d_mdbval), flags);
} }
int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
{
key.d_mdbval = in.d_mdbval;
int rc=mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to find from cursor: " + std::string(mdb_strerror(rc)));
return rc;
}
int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
{
key.d_mdbval = in.d_mdbval;
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET_RANGE);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to lower_bound from cursor: " + std::string(mdb_strerror(rc)));
return rc;
}
int next(MDBOutVal& key, MDBOutVal& data)
{
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_NEXT);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to next from cursor: " + std::string(mdb_strerror(rc)));
return rc;
}
int del(int flags=0) int del(int flags=0)
{ {
return mdb_cursor_del(d_cursor, flags); return mdb_cursor_del(d_cursor, flags);
} }
operator MDB_cursor*&()
{
return d_cursor;
}
MDB_cursor* d_cursor;
MDBRWTransaction* d_parent;
}; };

View File

@ -51,11 +51,11 @@ std::string serToString(const T& t)
} }
template<typename T> template<typename T>
void serFromString(const std::string& str, T& ret) void serFromString(const string_view& str, T& ret)
{ {
ret = T(); ret = T();
boost::iostreams::array_source source(str.c_str(), str.size()); boost::iostreams::array_source source(&str[0], str.size());
boost::iostreams::stream<boost::iostreams::array_source> stream(source); boost::iostreams::stream<boost::iostreams::array_source> stream(source);
boost::archive::binary_iarchive in_archive(stream, boost::archive::no_header|boost::archive::no_codecvt); boost::archive::binary_iarchive in_archive(stream, boost::archive::no_header|boost::archive::no_codecvt);
in_archive >> ret; in_archive >> ret;