📄 cxx_env.cpp
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997-2002 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: cxx_env.cpp,v 11.88 2002/08/26 22:13:36 mjc Exp $";#endif /* not lint */#include <errno.h>#include <stdio.h> // needed for set_error_stream#include <string.h>#include "db_cxx.h"#include "dbinc/cxx_int.h"#include "db_int.h"#include "dbinc_auto/common_ext.h"#ifdef HAVE_CXX_STDHEADERSusing std::cerr;#endif// Helper macros for simple methods that pass through to the// underlying C method. They may return an error or raise an exception.// These macros expect that input _argspec is an argument// list element (e.g., "char *arg") and that _arglist is the arguments// that should be passed through to the C method (e.g., "(dbenv, arg)")//#define DBENV_METHOD_ERR(_name, _argspec, _arglist, _on_err) \int DbEnv::_name _argspec \{ \ DB_ENV *dbenv = unwrap(this); \ int ret; \ \ if ((ret = dbenv->_name _arglist) != 0) { \ _on_err; \ } \ return (ret); \}#define DBENV_METHOD(_name, _argspec, _arglist) \ DBENV_METHOD_ERR(_name, _argspec, _arglist, \ DB_ERROR("DbEnv::" # _name, ret, error_policy()))#define DBENV_METHOD_QUIET(_name, _argspec, _arglist) \int DbEnv::_name _argspec \{ \ DB_ENV *dbenv = unwrap(this); \ \ return (dbenv->_name _arglist); \}#define DBENV_METHOD_VOID(_name, _argspec, _arglist) \void DbEnv::_name _argspec \{ \ DB_ENV *dbenv = unwrap(this); \ \ dbenv->_name _arglist; \}// This datatype is needed for picky compilers.//extern "C" { typedef void (*db_errcall_fcn_type) (const char *, char *);};// The reason for a static variable is that some structures// (like Dbts) have no connection to any Db or DbEnv, so when// errors occur in their methods, we must have some reasonable// way to determine whether to throw or return errors.//// This variable is taken from flags whenever a DbEnv is constructed.// Normally there is only one DbEnv per program, and even if not,// there is typically a single policy of throwing or returning.//static int last_known_error_policy = ON_ERROR_UNKNOWN;__DB_OSTREAMCLASS *DbEnv::error_stream_ = 0;// These 'glue' function are declared as extern "C" so they will// be compatible with picky compilers that do not allow mixing// of function pointers to 'C' functions with function pointers// to C++ functions.//extern "C"void _feedback_intercept_c(DB_ENV *env, int opcode, int pct){ DbEnv::_feedback_intercept(env, opcode, pct);}extern "C"void _paniccall_intercept_c(DB_ENV *env, int errval){ DbEnv::_paniccall_intercept(env, errval);}extern "C"void _stream_error_function_c(const char *prefix, char *message){ DbEnv::_stream_error_function(prefix, message);}extern "C"int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt, DB_LSN *lsn, db_recops op){ return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));}extern "C"int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl, const DBT *data, int id, u_int32_t flags){ return (DbEnv::_rep_send_intercept(env, cntrl, data, id, flags));}void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct){ if (env == 0) { DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN); return; } DbEnv *cxxenv = (DbEnv *)env->api1_internal; if (cxxenv == 0) { DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN); return; } if (cxxenv->feedback_callback_ == 0) { DB_ERROR("DbEnv::feedback_callback", EINVAL, cxxenv->error_policy()); return; } (*cxxenv->feedback_callback_)(cxxenv, opcode, pct);}void DbEnv::_paniccall_intercept(DB_ENV *env, int errval){ if (env == 0) { DB_ERROR("DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN); } DbEnv *cxxenv = (DbEnv *)env->api1_internal; if (cxxenv == 0) { DB_ERROR("DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN); } if (cxxenv->paniccall_callback_ == 0) { DB_ERROR("DbEnv::paniccall_callback", EINVAL, cxxenv->error_policy()); } (*cxxenv->paniccall_callback_)(cxxenv, errval);}int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt, DB_LSN *lsn, db_recops op){ if (env == 0) { DB_ERROR("DbEnv::app_dispatch_callback", EINVAL, ON_ERROR_UNKNOWN); return (EINVAL); } DbEnv *cxxenv = (DbEnv *)env->api1_internal; if (cxxenv == 0) { DB_ERROR("DbEnv::app_dispatch_callback", EINVAL, ON_ERROR_UNKNOWN); return (EINVAL); } if (cxxenv->app_dispatch_callback_ == 0) { DB_ERROR("DbEnv::app_dispatch_callback", EINVAL, cxxenv->error_policy()); return (EINVAL); } Dbt *cxxdbt = (Dbt *)dbt; DbLsn *cxxlsn = (DbLsn *)lsn; return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));}int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl, const DBT *data, int id, u_int32_t flags){ if (env == 0) { DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN); return (EINVAL); } DbEnv *cxxenv = (DbEnv *)env->api1_internal; if (cxxenv == 0) { DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN); return (EINVAL); } const Dbt *cxxcntrl = (const Dbt *)cntrl; Dbt *cxxdata = (Dbt *)data; return ((*cxxenv->rep_send_callback_)(cxxenv, cxxcntrl, cxxdata, id, flags));}// A truism for the DbEnv object is that there is a valid// DB_ENV handle from the constructor until close().// After the close, the DB_ENV handle is invalid and// no operations are permitted on the DbEnv (other than// destructor). Leaving the DbEnv handle open and not// doing a close is generally considered an error.//// We used to allow DbEnv objects to be closed and reopened.// This implied always keeping a valid DB_ENV object, and// coordinating the open objects between Db/DbEnv turned// out to be overly complicated. Now we do not allow this.DbEnv::DbEnv(u_int32_t flags): imp_(0), construct_error_(0), construct_flags_(flags), app_dispatch_callback_(0), feedback_callback_(0), paniccall_callback_(0), pgin_callback_(0), pgout_callback_(0), rep_send_callback_(0){ if ((construct_error_ = initialize(0)) != 0) DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());}DbEnv::DbEnv(DB_ENV *env, u_int32_t flags): imp_(0), construct_error_(0), construct_flags_(flags), app_dispatch_callback_(0), feedback_callback_(0), paniccall_callback_(0), pgin_callback_(0), pgout_callback_(0), rep_send_callback_(0){ if ((construct_error_ = initialize(env)) != 0) DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());}// If the DB_ENV handle is still open, we close it. This is to make stack// allocation of DbEnv objects easier so that they are cleaned up in the error// path. Note that the C layer catches cases where handles are open in the// environment at close time and reports an error. Applications should call// close explicitly in normal (non-exceptional) cases to check the return// value.//DbEnv::~DbEnv(){ DB_ENV *env = unwrap(this); if (env != NULL) { cleanup(); (void)env->close(env, 0); }}// called by destructors before the DB_ENV is destroyed.void DbEnv::cleanup(){ DB_ENV *env = unwrap(this); if (env != NULL) { env->api1_internal = 0; imp_ = 0; }}int DbEnv::close(u_int32_t flags){ int ret; DB_ENV *env = unwrap(this); // after a close (no matter if success or failure), // the underlying DB_ENV object must not be accessed, // so we clean up in advance. // cleanup(); // It's safe to throw an error after the close, // since our error mechanism does not peer into // the DB* structures. // if ((ret = env->close(env, flags)) != 0) DB_ERROR("DbEnv::close", ret, error_policy()); return (ret);}DBENV_METHOD(dbremove, (DbTxn *txn, const char *name, const char *subdb, u_int32_t flags), (dbenv, unwrap(txn), name, subdb, flags))DBENV_METHOD(dbrename, (DbTxn *txn, const char *name, const char *subdb, const char *newname, u_int32_t flags), (dbenv, unwrap(txn), name, subdb, newname, flags))void DbEnv::err(int error, const char *format, ...){ DB_ENV *env = unwrap(this); DB_REAL_ERR(env, error, 1, 1, format);}// Return a tristate value corresponding to whether we should// throw exceptions on errors:// ON_ERROR_RETURN// ON_ERROR_THROW// ON_ERROR_UNKNOWN//int DbEnv::error_policy(){ if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) { return (ON_ERROR_RETURN); } else { return (ON_ERROR_THROW); }}void DbEnv::errx(const char *format, ...){ DB_ENV *env = unwrap(this); DB_REAL_ERR(env, 0, 0, 1, format);}void *DbEnv::get_app_private() const{ return unwrapConst(this)->app_private;}// used internally during constructor// to associate an existing DB_ENV with this DbEnv,// or create a new one.//int DbEnv::initialize(DB_ENV *env){ int ret; last_known_error_policy = error_policy(); if (env == 0) { // Create a new DB_ENV environment. if ((ret = ::db_env_create(&env, construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0) return (ret); } imp_ = wrap(env); env->api1_internal = this; // for DB_ENV* to DbEnv* conversion return (0);}// lock methodsDBENV_METHOD(lock_detect, (u_int32_t flags, u_int32_t atype, int *aborted), (dbenv, flags, atype, aborted))DBENV_METHOD_ERR(lock_get, (u_int32_t locker, u_int32_t flags, const Dbt *obj, db_lockmode_t lock_mode, DbLock *lock), (dbenv, locker, flags, obj, lock_mode, &lock->lock_), DbEnv::runtime_error_lock_get("DbEnv::lock_get", ret, DB_LOCK_GET, lock_mode, obj, *lock, -1, error_policy()))DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags), (dbenv, statp, flags))DBENV_METHOD_ERR(lock_vec, (u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[], int nlist, DB_LOCKREQ **elist_returned), (dbenv, locker, flags, list, nlist, elist_returned), DbEnv::runtime_error_lock_get("DbEnv::lock_vec", ret, (*elist_returned)->op, (*elist_returned)->mode, Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock), (*elist_returned) - list, error_policy()))// log methodsDBENV_METHOD(log_archive, (char **list[], u_int32_t flags), (dbenv, list, flags))int DbEnv::log_compare(const DbLsn *lsn0, const DbLsn *lsn1){ return (::log_compare(lsn0, lsn1));}// The following cast implies that DbLogc can be no larger than DB_LOGCDBENV_METHOD(log_cursor, (DbLogc **cursorp, u_int32_t flags), (dbenv, (DB_LOGC **)cursorp, flags))DBENV_METHOD(log_file, (DbLsn *lsn, char *namep, size_t len), (dbenv, lsn, namep, len))DBENV_METHOD(log_flush, (const DbLsn *lsn), (dbenv, lsn))DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags), (dbenv, lsn, data, flags))DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags), (dbenv, spp, flags))int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -