diff --git a/cxx/db.cpp b/cxx/db.cpp index 31c6d1066c6..5de180b3c33 100644 --- a/cxx/db.cpp +++ b/cxx/db.cpp @@ -3,6 +3,8 @@ #include #include +#define do_maybe_error(errno) + Db::Db(DbEnv *env, u_int32_t flags) : the_Env(env) { @@ -13,7 +15,9 @@ Db::Db(DbEnv *env, u_int32_t flags) DB *tmp_db; int ret = db_create(&tmp_db, the_Env->get_DB_ENV(), flags & !(DB_CXX_NO_EXCEPTIONS)); if (ret!=0) { - assert(0); // make an error + the_Env->maybe_throw_error(ret); + // Otherwise cannot do much + return; } the_db = tmp_db; tmp_db->api_internal = this; @@ -33,7 +37,7 @@ Db::~Db() { int Db::close (u_int32_t flags) { if (!the_db) { - return EINVAL; + return the_Env->maybe_throw_error(EINVAL); } the_db->api_internal = 0; @@ -43,35 +47,35 @@ int Db::close (u_int32_t flags) { // Do we need to clean up "private environments"? // What about cursors? They should be cleaned up already, but who did it? - return ret; + return the_Env->maybe_throw_error(ret); } int Db::open(DbTxn *txn, const char *filename, const char *subname, DBTYPE typ, u_int32_t flags, int mode) { int ret = the_db->open(the_db, txn->get_DB_TXN(), filename, subname, typ, flags, mode); - return ret; + return the_Env->maybe_throw_error(ret); } int Db::put(DbTxn *txn, Dbt *key, Dbt *data, u_int32_t flags) { int ret = the_db->put(the_db, txn->get_DB_TXN(), key->get_DBT(), data->get_DBT(), flags); - return ret; + return the_Env->maybe_throw_error(ret); } int Db::cursor(DbTxn *txn, Dbc **cursorp, u_int32_t flags) { int ret = the_db->cursor(the_db, txn->get_DB_TXN(), (DBC**)cursorp, flags); - return ret; + return the_Env->maybe_throw_error(ret); } int Db::set_pagesize(u_int32_t size) { int ret = the_db->set_pagesize(the_db, size); - return ret; + return the_Env->maybe_throw_error(ret); } int Db::remove(const char *file, const char *database, u_int32_t flags) { int ret = the_db->remove(the_db, file, database, flags); - return ret; + return the_Env->maybe_throw_error(ret); } int Db::set_bt_compare(bt_compare_fcn_type bt_compare_fcn) { int ret = the_db->set_bt_compare(the_db, bt_compare_fcn); - return ret; + return the_Env->maybe_throw_error(ret); } diff --git a/cxx/dbenv.cpp b/cxx/dbenv.cpp index c27f4c9d996..ec83c96ef44 100644 --- a/cxx/dbenv.cpp +++ b/cxx/dbenv.cpp @@ -1,13 +1,17 @@ #include #include -DbEnv::DbEnv (u_int32_t flags) { +DbEnv::DbEnv (u_int32_t flags) + : do_no_exceptions((flags&DB_CXX_NO_EXCEPTIONS)!=0) +{ int ret = db_env_create(&the_env, flags & ~DB_CXX_NO_EXCEPTIONS); assert(ret==0); // should do an error. the_env->api1_internal = this; } -DbEnv::DbEnv(DB_ENV *env, u_int32_t flags) { +DbEnv::DbEnv(DB_ENV *env, u_int32_t flags) + : do_no_exceptions((flags&DB_CXX_NO_EXCEPTIONS)!=0) +{ the_env = env; if (env == 0) { DB_ENV *new_env; @@ -21,23 +25,23 @@ DbEnv::DbEnv(DB_ENV *env, u_int32_t flags) { int DbEnv::close(u_int32_t flags) { int ret = the_env->close(the_env, flags); the_env = 0; /* get rid of the env ref, so we don't touch it (even if we failed.) */ - return ret; + return maybe_throw_error(ret); } int DbEnv::open(const char *home, u_int32_t flags, int mode) { int ret = the_env->open(the_env, home, flags, mode); - return ret; + return maybe_throw_error(ret); } int DbEnv::set_cachesize(u_int32_t gbytes, u_int32_t bytes, int ncache) { int ret = the_env->set_cachesize(the_env, gbytes, bytes, ncache); - return ret; + return maybe_throw_error(ret); } #if DB_VERSION_MAJOR<4 || (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<=4) int DbEnv::set_lk_max(u_int32_t flags) { int ret = the_env->set_lk_max(the_env, flags); - return ret; + return maybe_throw_error(ret); } #endif @@ -47,14 +51,22 @@ int DbEnv::txn_begin(DbTxn *parenttxn, DbTxn **txnp, u_int32_t flags) { if (ret==0) { *txnp = new DbTxn(txn); } - return ret; + return maybe_throw_error(ret); } int DbEnv::set_data_dir(const char *dir) { int ret = the_env->set_data_dir(the_env, dir); - return ret; + return maybe_throw_error(ret); } void DbEnv::set_errpfx(const char *errpfx) { the_env->set_errpfx(the_env, errpfx); } + +int DbEnv::maybe_throw_error(int err) { + if (err==0) return 0; + if (do_no_exceptions) return err; + DbException e(err); + e.set_env(the_env); + throw e; +} diff --git a/cxx/exception.cpp b/cxx/exception.cpp new file mode 100644 index 00000000000..4d4f7bbe813 --- /dev/null +++ b/cxx/exception.cpp @@ -0,0 +1,38 @@ +#include +#include + +DbException::~DbException() throw() +{ + if (the_what!=0) { + delete [] the_what; + } +} + +DbException::DbException(int err) + : the_err(err), + the_env(0) +{ + FillTheWhat(); +} + +void DbException::FillTheWhat(void) +{ + if (the_err!=0) { + the_what = strdup(db_strerror(the_err)); + } +} + +int DbException::get_errno() const +{ + return the_err; +} + +const char *DbException::what() const throw() +{ + return the_what; +} + +DbEnv *DbException::get_env() const +{ + return the_env; +} diff --git a/include/db_cxx.h b/include/db_cxx.h index 853359c59ce..3bac879b838 100644 --- a/include/db_cxx.h +++ b/include/db_cxx.h @@ -1,4 +1,5 @@ #include +#include #include #ident "Copyright (c) 2007 Tokutek Inc. All rights reserved." @@ -100,9 +101,11 @@ class DbEnv { void set_errpfx(const char *errpfx); private: + int do_no_exceptions; DB_ENV *the_env; - DbEnv(DB_ENV *, u_int32_t flags); + DbEnv(DB_ENV *, u_int32_t /*flags*/); + int maybe_throw_error(int /*err*/); }; @@ -129,3 +132,20 @@ class Dbc : protected DBC }; +class DbException : public std::exception +{ + friend class DbEnv; + public: + ~DbException() throw(); + DbException(int err); + int get_errno() const; + const char *what() const throw(); + DbEnv *get_env() const; + private: + char *the_what; + int the_err; + DbEnv *the_env; + void FillTheWhat(void); + void set_env(DB_ENV *); +}; +