Use distinct exception class and unify format of error messages
* Avoid manual code for making error message * Use `const` for the return code variable where possible * Unify formatting of error messages
This commit is contained in:
parent
a002cdecdf
commit
3bafada5cc
63
lmdb-safe.cc
63
lmdb-safe.cc
|
@ -12,19 +12,13 @@ using namespace std;
|
|||
|
||||
namespace LMDBSafe {
|
||||
|
||||
static string MDBError(int rc)
|
||||
{
|
||||
return mdb_strerror(rc);
|
||||
}
|
||||
|
||||
MDBDbi::MDBDbi(MDB_env* env, MDB_txn* txn, const string_view dbname, unsigned int flags)
|
||||
{
|
||||
(void)env;
|
||||
// A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
|
||||
|
||||
int rc = mdb_dbi_open(txn, dbname.empty() ? 0 : &dbname[0], flags, &d_dbi);
|
||||
if(rc)
|
||||
throw std::runtime_error("Unable to open named database: " + MDBError(rc));
|
||||
if(const auto rc = mdb_dbi_open(txn, dbname.empty() ? 0 : &dbname[0], flags, &d_dbi))
|
||||
throw LMDBError("Unable to open named database: ", rc);
|
||||
|
||||
// Database names are keys in the unnamed database, and may be read but not written.
|
||||
}
|
||||
|
@ -33,18 +27,18 @@ MDBEnv::MDBEnv(const char* fname, unsigned int flags, mdb_mode_t mode, MDB_dbi m
|
|||
{
|
||||
mdb_env_create(&d_env);
|
||||
if(const auto rc = mdb_env_set_mapsize(d_env, 16ULL * 4096 * 244140ULL)) { // 4GB
|
||||
throw std::runtime_error("setting map size: " + MDBError(rc));
|
||||
throw LMDBError("Setting map size: ", rc);
|
||||
}
|
||||
// Various other options may also need to be set before opening the handle, e.g. mdb_env_set_mapsize(), mdb_env_set_maxreaders(), mdb_env_set_maxdbs(),
|
||||
if (const auto rc = mdb_env_set_maxdbs(d_env, maxDBs)) {
|
||||
throw std::runtime_error("setting maxdbs: " + MDBError(rc));
|
||||
throw LMDBError("Setting maxdbs: ", rc);
|
||||
}
|
||||
|
||||
// we need MDB_NOTLS since we rely on its semantics
|
||||
if(int rc=mdb_env_open(d_env, fname, flags | MDB_NOTLS, mode)) {
|
||||
if(const auto rc = mdb_env_open(d_env, fname, flags | MDB_NOTLS, mode)) {
|
||||
// If this function fails, mdb_env_close() must be called to discard the MDB_env handle.
|
||||
mdb_env_close(d_env);
|
||||
throw std::runtime_error("Unable to open database file "+std::string(fname)+": " + MDBError(rc));
|
||||
throw LMDBError("Unable to open database file " + std::string(fname) + ": ", rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,12 +92,12 @@ std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, unsigned int flags, mdb_mod
|
|||
struct stat statbuf;
|
||||
if(stat(fname, &statbuf)) {
|
||||
if(errno != ENOENT)
|
||||
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
|
||||
throw LMDBError("Unable to stat prospective mdb database: " + string(strerror(errno)));
|
||||
else {
|
||||
std::lock_guard<std::mutex> l(mut);
|
||||
auto fresh = std::make_shared<MDBEnv>(fname, flags, mode, maxDBs);
|
||||
if(stat(fname, &statbuf))
|
||||
throw std::runtime_error("Unable to stat prospective mdb database: "+string(strerror(errno)));
|
||||
throw LMDBError("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;
|
||||
|
@ -117,7 +111,7 @@ std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, unsigned int flags, mdb_mod
|
|||
auto sp = iter->second.wp.lock();
|
||||
if(sp) {
|
||||
if(iter->second.flags != flags)
|
||||
throw std::runtime_error("Can't open mdb with differing flags");
|
||||
throw LMDBError("Can't open mdb with differing flags");
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
@ -168,7 +162,7 @@ MDB_txn *MDBRWTransactionImpl::openRWTransaction(MDBEnv *env, MDB_txn *parent, u
|
|||
{
|
||||
MDB_txn *result;
|
||||
if(env->getRWTX())
|
||||
throw std::runtime_error("Duplicate RW transaction");
|
||||
throw LMDBError("Duplicate RW transaction");
|
||||
|
||||
for(int tries =0 ; tries < 3; ++tries) { // it might happen twice, who knows
|
||||
if(int rc=mdb_txn_begin(env->d_env, parent, flags, &result)) {
|
||||
|
@ -178,7 +172,7 @@ MDB_txn *MDBRWTransactionImpl::openRWTransaction(MDBEnv *env, MDB_txn *parent, u
|
|||
mdb_env_set_mapsize(env->d_env, 0);
|
||||
continue;
|
||||
}
|
||||
throw std::runtime_error("Unable to start RW transaction: "+std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Unable to start RW transaction: ", rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -203,8 +197,8 @@ void MDBRWTransactionImpl::commit()
|
|||
return;
|
||||
}
|
||||
|
||||
if(int rc = mdb_txn_commit(d_txn)) {
|
||||
throw std::runtime_error("committing: " + std::string(mdb_strerror(rc)));
|
||||
if(const auto rc = mdb_txn_commit(d_txn)) {
|
||||
throw LMDBError("Committing transaction: ", rc);
|
||||
}
|
||||
environment().decRWTX();
|
||||
d_txn = nullptr;
|
||||
|
@ -234,21 +228,20 @@ MDBROTransactionImpl::MDBROTransactionImpl(MDBEnv *parent, MDB_txn *txn):
|
|||
MDB_txn *MDBROTransactionImpl::openROTransaction(MDBEnv *env, MDB_txn *parent, unsigned int flags)
|
||||
{
|
||||
if(env->getRWTX())
|
||||
throw std::runtime_error("Duplicate RO transaction");
|
||||
throw LMDBError("Duplicate RO transaction");
|
||||
|
||||
/*
|
||||
A transaction and its cursors must only be used by a single thread, and a thread may only have a single transaction at a time. If MDB_NOTLS is in use, this does not apply to read-only transactions. */
|
||||
MDB_txn *result = nullptr;
|
||||
for(int tries =0 ; tries < 3; ++tries) { // it might happen twice, who knows
|
||||
if(int rc=mdb_txn_begin(env->d_env, parent, MDB_RDONLY | flags, &result)) {
|
||||
for(int tries = 0; tries < 3; ++tries) { // it might happen twice, who knows
|
||||
if(const auto rc = mdb_txn_begin(env->d_env, parent, MDB_RDONLY | flags, &result)) {
|
||||
if(rc == MDB_MAP_RESIZED && tries < 2) {
|
||||
// "If the mapsize is increased by another process (..) mdb_txn_begin() will return MDB_MAP_RESIZED.
|
||||
// call mdb_env_set_mapsize with a size of zero to adopt the new size."
|
||||
mdb_env_set_mapsize(env->d_env, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unable to start RO transaction: "+string(mdb_strerror(rc)));
|
||||
throw LMDBError("Unable to start RO transaction: ", rc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -297,7 +290,7 @@ void MDBROTransactionImpl::commit()
|
|||
if (d_txn) {
|
||||
d_parent->decROTX();
|
||||
if (const auto rc = mdb_txn_commit(d_txn)) { // this appears to work better than abort for r/o database opening
|
||||
throw std::runtime_error("Error comitting transaction: " + MDBError(rc));
|
||||
throw LMDBError("Error comitting transaction: ", rc);
|
||||
}
|
||||
d_txn = nullptr;
|
||||
}
|
||||
|
@ -307,17 +300,16 @@ void MDBROTransactionImpl::commit()
|
|||
|
||||
void MDBRWTransactionImpl::clear(MDB_dbi dbi)
|
||||
{
|
||||
if(int rc = mdb_drop(d_txn, dbi, 0)) {
|
||||
throw runtime_error("Error clearing database: " + MDBError(rc));
|
||||
if(const auto rc = mdb_drop(d_txn, dbi, 0)) {
|
||||
throw LMDBError("Error clearing database: ", rc);
|
||||
}
|
||||
}
|
||||
|
||||
MDBRWCursor MDBRWTransactionImpl::getRWCursor(const MDBDbi& dbi)
|
||||
{
|
||||
MDB_cursor *cursor;
|
||||
int rc= mdb_cursor_open(d_txn, dbi, &cursor);
|
||||
if(rc) {
|
||||
throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc)));
|
||||
MDB_cursor *cursor;;
|
||||
if(const auto rc = mdb_cursor_open(d_txn, dbi, &cursor)) {
|
||||
throw LMDBError("Error creating RO cursor: ", rc);
|
||||
}
|
||||
return MDBRWCursor(d_rw_cursors, cursor);
|
||||
}
|
||||
|
@ -330,8 +322,8 @@ MDBRWCursor MDBRWTransactionImpl::getCursor(const MDBDbi &dbi)
|
|||
MDBRWTransaction MDBRWTransactionImpl::getRWTransaction()
|
||||
{
|
||||
MDB_txn *txn;
|
||||
if (int rc = mdb_txn_begin(environment(), *this, 0, &txn)) {
|
||||
throw std::runtime_error(std::string("failed to start child transaction: ")+mdb_strerror(rc));
|
||||
if (const auto rc = mdb_txn_begin(environment(), *this, 0, &txn)) {
|
||||
throw LMDBError("Failed to start child transaction: ", rc);
|
||||
}
|
||||
// we need to increase the counter here because commit/abort on the child transaction will decrease it
|
||||
environment().incRWTX();
|
||||
|
@ -370,9 +362,8 @@ MDBROCursor MDBROTransactionImpl::getCursor(const MDBDbi& dbi)
|
|||
MDBROCursor MDBROTransactionImpl::getROCursor(const MDBDbi &dbi)
|
||||
{
|
||||
MDB_cursor *cursor;
|
||||
int rc= mdb_cursor_open(d_txn, dbi, &cursor);
|
||||
if(rc) {
|
||||
throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc)));
|
||||
if(const auto rc = mdb_cursor_open(d_txn, dbi, &cursor)) {
|
||||
throw LMDBError("Error creating RO cursor: ", rc);
|
||||
}
|
||||
return MDBROCursor(d_cursors, cursor);
|
||||
}
|
||||
|
|
83
lmdb-safe.hh
83
lmdb-safe.hh
|
@ -14,6 +14,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
/*!
|
||||
* \brief The LMDBSafe namespace contains all classes/types contained by the lmdb-safe and
|
||||
|
@ -40,6 +41,20 @@ using string_view = boost::string_ref;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
class LMDBError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit LMDBError(const std::string &error) noexcept
|
||||
: std::runtime_error(error)
|
||||
{
|
||||
}
|
||||
|
||||
explicit LMDBError(const std::string &context, int error) noexcept
|
||||
: std::runtime_error(context + mdb_strerror(error))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The MDBDbi class is our only 'value type' object as 1) a dbi is actually an integer
|
||||
* and 2) per LMDB documentation, we never close it.
|
||||
|
@ -121,7 +136,7 @@ struct MDBOutVal
|
|||
{
|
||||
T ret;
|
||||
if(d_mdbval.mv_size != sizeof(T))
|
||||
throw std::runtime_error("MDB data has wrong length for type");
|
||||
throw LMDBError("MDB data has wrong length for type");
|
||||
|
||||
memcpy(&ret, d_mdbval.mv_data, sizeof(T));
|
||||
return ret;
|
||||
|
@ -136,7 +151,7 @@ struct MDBOutVal
|
|||
{
|
||||
T ret;
|
||||
if(d_mdbval.mv_size != sizeof(T))
|
||||
throw std::runtime_error("MDB data has wrong length for type");
|
||||
throw LMDBError("MDB data has wrong length for type");
|
||||
|
||||
memcpy(&ret, d_mdbval.mv_data, sizeof(T));
|
||||
return ret;
|
||||
|
@ -146,7 +161,7 @@ struct MDBOutVal
|
|||
const T* get_struct_ptr() const
|
||||
{
|
||||
if(d_mdbval.mv_size != sizeof(T))
|
||||
throw std::runtime_error("MDB data has wrong length for type");
|
||||
throw LMDBError("MDB data has wrong length for type");
|
||||
|
||||
return reinterpret_cast<const T*>(d_mdbval.mv_data);
|
||||
}
|
||||
|
@ -261,12 +276,12 @@ public:
|
|||
int get(MDB_dbi dbi, const MDBInVal& key, MDBOutVal& val)
|
||||
{
|
||||
if(!d_txn)
|
||||
throw std::runtime_error("Attempt to use a closed RO transaction for get");
|
||||
throw LMDBError("Attempt to use a closed RO transaction for get");
|
||||
|
||||
int rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const auto rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const_cast<MDB_val*>(&val.d_mdbval));
|
||||
if(rc && rc != MDB_NOTFOUND)
|
||||
throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Getting data: ", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -383,18 +398,18 @@ public:
|
|||
public:
|
||||
int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
|
||||
{
|
||||
int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
|
||||
const auto rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
|
||||
if(rc && rc != MDB_NOTFOUND)
|
||||
throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Unable to get from cursor: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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);
|
||||
const auto 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)));
|
||||
throw LMDBError("Unable to find from cursor: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -402,18 +417,18 @@ public:
|
|||
{
|
||||
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);
|
||||
const auto 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)));
|
||||
throw LMDBError("Unable to lower_bound from cursor: ", 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);
|
||||
const auto 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)));
|
||||
throw LMDBError("Unable to prevnext from cursor: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -429,9 +444,9 @@ public:
|
|||
|
||||
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);
|
||||
const auto 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 next from cursor: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Unable to next from cursor: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -526,30 +541,27 @@ public:
|
|||
void put(MDB_dbi dbi, const MDBInVal& key, const MDBInVal& val, unsigned int flags=0)
|
||||
{
|
||||
if(!d_txn)
|
||||
throw std::runtime_error("Attempt to use a closed RW transaction for put");
|
||||
int rc;
|
||||
if((rc=mdb_put(d_txn, dbi,
|
||||
throw LMDBError("Attempt to use a closed RW transaction for put");
|
||||
if(const auto rc = mdb_put(d_txn, dbi,
|
||||
const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const_cast<MDB_val*>(&val.d_mdbval), flags)))
|
||||
throw std::runtime_error("putting data: " + std::string(mdb_strerror(rc)));
|
||||
const_cast<MDB_val*>(&val.d_mdbval), flags))
|
||||
throw LMDBError("Putting data: ", rc);
|
||||
}
|
||||
|
||||
|
||||
int del(MDBDbi& dbi, const MDBInVal& key, const MDBInVal& val)
|
||||
{
|
||||
int rc;
|
||||
rc=mdb_del(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval), const_cast<MDB_val*>(&val.d_mdbval));
|
||||
const auto rc = mdb_del(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval), const_cast<MDB_val*>(&val.d_mdbval));
|
||||
if(rc && rc != MDB_NOTFOUND)
|
||||
throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Deleting data: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int del(MDBDbi& dbi, const MDBInVal& key)
|
||||
{
|
||||
int rc;
|
||||
rc=mdb_del(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval), 0);
|
||||
const auto rc = mdb_del(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval), 0);
|
||||
if(rc && rc != MDB_NOTFOUND)
|
||||
throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Deleting data: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -557,19 +569,19 @@ public:
|
|||
int get(MDBDbi& dbi, const MDBInVal& key, MDBOutVal& val)
|
||||
{
|
||||
if(!d_txn)
|
||||
throw std::runtime_error("Attempt to use a closed RW transaction for get");
|
||||
throw LMDBError("Attempt to use a closed RW transaction for get");
|
||||
|
||||
int rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const auto rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const_cast<MDB_val*>(&val.d_mdbval));
|
||||
if(rc && rc != MDB_NOTFOUND)
|
||||
throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Getting data: ", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int get(MDBDbi& dbi, const MDBInVal& key, string_view& val)
|
||||
{
|
||||
MDBOutVal out;
|
||||
int rc = get(dbi, key, out);
|
||||
const auto rc = get(dbi, key, out);
|
||||
if(!rc)
|
||||
val = out.get<string_view>();
|
||||
return rc;
|
||||
|
@ -607,11 +619,10 @@ public:
|
|||
|
||||
void put(const MDBOutVal& key, const MDBInVal& data)
|
||||
{
|
||||
int rc = mdb_cursor_put(*this,
|
||||
const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const_cast<MDB_val*>(&data.d_mdbval), MDB_CURRENT);
|
||||
if(rc)
|
||||
throw std::runtime_error("mdb_cursor_put: " + std::string(mdb_strerror(rc)));
|
||||
if(const auto rc = mdb_cursor_put(*this,
|
||||
const_cast<MDB_val*>(&key.d_mdbval),
|
||||
const_cast<MDB_val*>(&data.d_mdbval), MDB_CURRENT))
|
||||
throw LMDBError("Putting data via mdb_cursor_put: ", rc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -69,8 +69,8 @@ struct LMDBIndexOps
|
|||
|
||||
void del(MDBRWTransaction& txn, const Class& t, uint32_t id)
|
||||
{
|
||||
if(int rc = txn->del(d_idx, keyConv(d_parent->getMember(t)), id)) {
|
||||
throw std::runtime_error("Error deleting from index: " + std::string(mdb_strerror(rc)));
|
||||
if(const auto rc = txn->del(d_idx, keyConv(d_parent->getMember(t)), id)) {
|
||||
throw LMDBError("Error deleting from index: ", rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ public:
|
|||
|
||||
if(d_on_index) {
|
||||
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data))
|
||||
throw std::runtime_error("Missing id in constructor");
|
||||
throw LMDBError("Missing id in constructor");
|
||||
serFromString(d_data.get<std::string>(), d_t);
|
||||
}
|
||||
else
|
||||
|
@ -284,7 +284,7 @@ public:
|
|||
|
||||
if(d_on_index) {
|
||||
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data))
|
||||
throw std::runtime_error("Missing id in constructor");
|
||||
throw LMDBError("Missing id in constructor");
|
||||
serFromString(d_data.get<std::string>(), d_t);
|
||||
}
|
||||
else
|
||||
|
@ -327,14 +327,13 @@ public:
|
|||
iter_t& genoperator(MDB_cursor_op dupop, MDB_cursor_op op)
|
||||
{
|
||||
MDBOutVal data;
|
||||
int rc;
|
||||
next:;
|
||||
rc = d_cursor.get(d_key, d_id, d_one_key ? dupop : op);
|
||||
const auto rc = d_cursor.get(d_key, d_id, d_one_key ? dupop : op);
|
||||
if(rc == MDB_NOTFOUND) {
|
||||
d_end = true;
|
||||
}
|
||||
else if(rc) {
|
||||
throw std::runtime_error("in genoperator, " + std::string(mdb_strerror(rc)));
|
||||
throw LMDBError("Unable to get in genoperator: ", rc);
|
||||
}
|
||||
else if(!d_prefix.empty() && d_key.get<std::string>().rfind(d_prefix, 0)!=0) {
|
||||
d_end = true;
|
||||
|
@ -342,7 +341,7 @@ public:
|
|||
else {
|
||||
if(d_on_index) {
|
||||
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, data))
|
||||
throw std::runtime_error("Missing id field");
|
||||
throw LMDBError("Missing id field in genoperator");
|
||||
if(filter && !filter(data))
|
||||
goto next;
|
||||
|
||||
|
@ -591,7 +590,7 @@ public:
|
|||
{
|
||||
T t;
|
||||
if(!this->get(id, t))
|
||||
throw std::runtime_error("Could not modify id "+std::to_string(id));
|
||||
throw LMDBError("Could not modify id " + std::to_string(id));
|
||||
func(t);
|
||||
|
||||
del(id); // this is the lazy way. We could test for changed index fields
|
||||
|
|
Loading…
Reference in New Issue