cxx_env.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:22k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1997-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: cxx_env.cpp,v 11.88 2002/08/26 22:13:36 mjc Exp $";
  10. #endif /* not lint */
  11. #include <errno.h>
  12. #include <stdio.h>              // needed for set_error_stream
  13. #include <string.h>
  14. #include "db_cxx.h"
  15. #include "dbinc/cxx_int.h"
  16. #include "db_int.h"
  17. #include "dbinc_auto/common_ext.h"
  18. #ifdef HAVE_CXX_STDHEADERS
  19. using std::cerr;
  20. #endif
  21. // Helper macros for simple methods that pass through to the
  22. // underlying C method.  They may return an error or raise an exception.
  23. // These macros expect that input _argspec is an argument
  24. // list element (e.g., "char *arg") and that _arglist is the arguments
  25. // that should be passed through to the C method (e.g., "(dbenv, arg)")
  26. //
  27. #define DBENV_METHOD_ERR(_name, _argspec, _arglist, _on_err)   
  28. int DbEnv::_name _argspec   
  29. {   
  30. DB_ENV *dbenv = unwrap(this);   
  31. int ret;   
  32.   
  33. if ((ret = dbenv->_name _arglist) != 0) {   
  34. _on_err;   
  35. }   
  36. return (ret);   
  37. }
  38. #define DBENV_METHOD(_name, _argspec, _arglist)   
  39. DBENV_METHOD_ERR(_name, _argspec, _arglist,   
  40.  DB_ERROR("DbEnv::" # _name, ret, error_policy()))
  41. #define DBENV_METHOD_QUIET(_name, _argspec, _arglist)   
  42. int DbEnv::_name _argspec   
  43. {   
  44. DB_ENV *dbenv = unwrap(this);   
  45.   
  46. return (dbenv->_name _arglist);   
  47. }
  48. #define DBENV_METHOD_VOID(_name, _argspec, _arglist)   
  49. void DbEnv::_name _argspec   
  50. {   
  51. DB_ENV *dbenv = unwrap(this);   
  52.   
  53. dbenv->_name _arglist;   
  54. }
  55. // This datatype is needed for picky compilers.
  56. //
  57. extern "C" {
  58. typedef void (*db_errcall_fcn_type)
  59. (const char *, char *);
  60. };
  61. // The reason for a static variable is that some structures
  62. // (like Dbts) have no connection to any Db or DbEnv, so when
  63. // errors occur in their methods, we must have some reasonable
  64. // way to determine whether to throw or return errors.
  65. //
  66. // This variable is taken from flags whenever a DbEnv is constructed.
  67. // Normally there is only one DbEnv per program, and even if not,
  68. // there is typically a single policy of throwing or returning.
  69. //
  70. static int last_known_error_policy = ON_ERROR_UNKNOWN;
  71. __DB_OSTREAMCLASS *DbEnv::error_stream_ = 0;
  72. // These 'glue' function are declared as extern "C" so they will
  73. // be compatible with picky compilers that do not allow mixing
  74. // of function pointers to 'C' functions with function pointers
  75. // to C++ functions.
  76. //
  77. extern "C"
  78. void _feedback_intercept_c(DB_ENV *env, int opcode, int pct)
  79. {
  80. DbEnv::_feedback_intercept(env, opcode, pct);
  81. }
  82. extern "C"
  83. void _paniccall_intercept_c(DB_ENV *env, int errval)
  84. {
  85. DbEnv::_paniccall_intercept(env, errval);
  86. }
  87. extern "C"
  88. void _stream_error_function_c(const char *prefix, char *message)
  89. {
  90. DbEnv::_stream_error_function(prefix, message);
  91. }
  92. extern "C"
  93. int _app_dispatch_intercept_c(DB_ENV *env, DBT *dbt,
  94.     DB_LSN *lsn, db_recops op)
  95. {
  96. return (DbEnv::_app_dispatch_intercept(env, dbt, lsn, op));
  97. }
  98. extern "C"
  99. int _rep_send_intercept_c(DB_ENV *env, const DBT *cntrl,
  100.   const DBT *data, int id, u_int32_t flags)
  101. {
  102. return (DbEnv::_rep_send_intercept(env,
  103.     cntrl, data, id, flags));
  104. }
  105. void DbEnv::_feedback_intercept(DB_ENV *env, int opcode, int pct)
  106. {
  107. if (env == 0) {
  108. DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
  109. return;
  110. }
  111. DbEnv *cxxenv = (DbEnv *)env->api1_internal;
  112. if (cxxenv == 0) {
  113. DB_ERROR("DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
  114. return;
  115. }
  116. if (cxxenv->feedback_callback_ == 0) {
  117. DB_ERROR("DbEnv::feedback_callback", EINVAL,
  118.  cxxenv->error_policy());
  119. return;
  120. }
  121. (*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
  122. }
  123. void DbEnv::_paniccall_intercept(DB_ENV *env, int errval)
  124. {
  125. if (env == 0) {
  126. DB_ERROR("DbEnv::paniccall_callback", EINVAL,
  127.     ON_ERROR_UNKNOWN);
  128. }
  129. DbEnv *cxxenv = (DbEnv *)env->api1_internal;
  130. if (cxxenv == 0) {
  131. DB_ERROR("DbEnv::paniccall_callback", EINVAL,
  132.     ON_ERROR_UNKNOWN);
  133. }
  134. if (cxxenv->paniccall_callback_ == 0) {
  135. DB_ERROR("DbEnv::paniccall_callback", EINVAL,
  136.     cxxenv->error_policy());
  137. }
  138. (*cxxenv->paniccall_callback_)(cxxenv, errval);
  139. }
  140. int DbEnv::_app_dispatch_intercept(DB_ENV *env, DBT *dbt,
  141. DB_LSN *lsn, db_recops op)
  142. {
  143. if (env == 0) {
  144. DB_ERROR("DbEnv::app_dispatch_callback",
  145.     EINVAL, ON_ERROR_UNKNOWN);
  146. return (EINVAL);
  147. }
  148. DbEnv *cxxenv = (DbEnv *)env->api1_internal;
  149. if (cxxenv == 0) {
  150. DB_ERROR("DbEnv::app_dispatch_callback",
  151.     EINVAL, ON_ERROR_UNKNOWN);
  152. return (EINVAL);
  153. }
  154. if (cxxenv->app_dispatch_callback_ == 0) {
  155. DB_ERROR("DbEnv::app_dispatch_callback",
  156.     EINVAL, cxxenv->error_policy());
  157. return (EINVAL);
  158. }
  159. Dbt *cxxdbt = (Dbt *)dbt;
  160. DbLsn *cxxlsn = (DbLsn *)lsn;
  161. return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));
  162. }
  163. int DbEnv::_rep_send_intercept(DB_ENV *env, const DBT *cntrl,
  164.        const DBT *data, int id, u_int32_t flags)
  165. {
  166. if (env == 0) {
  167. DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
  168. return (EINVAL);
  169. }
  170. DbEnv *cxxenv = (DbEnv *)env->api1_internal;
  171. if (cxxenv == 0) {
  172. DB_ERROR("DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
  173. return (EINVAL);
  174. }
  175. const Dbt *cxxcntrl = (const Dbt *)cntrl;
  176. Dbt *cxxdata = (Dbt *)data;
  177. return ((*cxxenv->rep_send_callback_)(cxxenv,
  178.     cxxcntrl, cxxdata, id, flags));
  179. }
  180. // A truism for the DbEnv object is that there is a valid
  181. // DB_ENV handle from the constructor until close().
  182. // After the close, the DB_ENV handle is invalid and
  183. // no operations are permitted on the DbEnv (other than
  184. // destructor).  Leaving the DbEnv handle open and not
  185. // doing a close is generally considered an error.
  186. //
  187. // We used to allow DbEnv objects to be closed and reopened.
  188. // This implied always keeping a valid DB_ENV object, and
  189. // coordinating the open objects between Db/DbEnv turned
  190. // out to be overly complicated.  Now we do not allow this.
  191. DbEnv::DbEnv(u_int32_t flags)
  192. : imp_(0)
  193. , construct_error_(0)
  194. , construct_flags_(flags)
  195. , app_dispatch_callback_(0)
  196. , feedback_callback_(0)
  197. , paniccall_callback_(0)
  198. , pgin_callback_(0)
  199. , pgout_callback_(0)
  200. , rep_send_callback_(0)
  201. {
  202. if ((construct_error_ = initialize(0)) != 0)
  203. DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
  204. }
  205. DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
  206. : imp_(0)
  207. , construct_error_(0)
  208. , construct_flags_(flags)
  209. , app_dispatch_callback_(0)
  210. , feedback_callback_(0)
  211. , paniccall_callback_(0)
  212. , pgin_callback_(0)
  213. , pgout_callback_(0)
  214. , rep_send_callback_(0)
  215. {
  216. if ((construct_error_ = initialize(env)) != 0)
  217. DB_ERROR("DbEnv::DbEnv", construct_error_, error_policy());
  218. }
  219. // If the DB_ENV handle is still open, we close it.  This is to make stack
  220. // allocation of DbEnv objects easier so that they are cleaned up in the error
  221. // path.  Note that the C layer catches cases where handles are open in the
  222. // environment at close time and reports an error.  Applications should call
  223. // close explicitly in normal (non-exceptional) cases to check the return
  224. // value.
  225. //
  226. DbEnv::~DbEnv()
  227. {
  228. DB_ENV *env = unwrap(this);
  229. if (env != NULL) {
  230. cleanup();
  231. (void)env->close(env, 0);
  232. }
  233. }
  234. // called by destructors before the DB_ENV is destroyed.
  235. void DbEnv::cleanup()
  236. {
  237. DB_ENV *env = unwrap(this);
  238. if (env != NULL) {
  239. env->api1_internal = 0;
  240. imp_ = 0;
  241. }
  242. }
  243. int DbEnv::close(u_int32_t flags)
  244. {
  245. int ret;
  246. DB_ENV *env = unwrap(this);
  247. // after a close (no matter if success or failure),
  248. // the underlying DB_ENV object must not be accessed,
  249. // so we clean up in advance.
  250. //
  251. cleanup();
  252. // It's safe to throw an error after the close,
  253. // since our error mechanism does not peer into
  254. // the DB* structures.
  255. //
  256. if ((ret = env->close(env, flags)) != 0)
  257. DB_ERROR("DbEnv::close", ret, error_policy());
  258. return (ret);
  259. }
  260. DBENV_METHOD(dbremove,
  261.     (DbTxn *txn, const char *name, const char *subdb, u_int32_t flags),
  262.     (dbenv, unwrap(txn), name, subdb, flags))
  263. DBENV_METHOD(dbrename, (DbTxn *txn, const char *name, const char *subdb,
  264.     const char *newname, u_int32_t flags),
  265.     (dbenv, unwrap(txn), name, subdb, newname, flags))
  266. void DbEnv::err(int error, const char *format, ...)
  267. {
  268. DB_ENV *env = unwrap(this);
  269. DB_REAL_ERR(env, error, 1, 1, format);
  270. }
  271. // Return a tristate value corresponding to whether we should
  272. // throw exceptions on errors:
  273. //   ON_ERROR_RETURN
  274. //   ON_ERROR_THROW
  275. //   ON_ERROR_UNKNOWN
  276. //
  277. int DbEnv::error_policy()
  278. {
  279. if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
  280. return (ON_ERROR_RETURN);
  281. }
  282. else {
  283. return (ON_ERROR_THROW);
  284. }
  285. }
  286. void DbEnv::errx(const char *format, ...)
  287. {
  288. DB_ENV *env = unwrap(this);
  289. DB_REAL_ERR(env, 0, 0, 1, format);
  290. }
  291. void *DbEnv::get_app_private() const
  292. {
  293. return unwrapConst(this)->app_private;
  294. }
  295. // used internally during constructor
  296. // to associate an existing DB_ENV with this DbEnv,
  297. // or create a new one.
  298. //
  299. int DbEnv::initialize(DB_ENV *env)
  300. {
  301. int ret;
  302. last_known_error_policy = error_policy();
  303. if (env == 0) {
  304. // Create a new DB_ENV environment.
  305. if ((ret = ::db_env_create(&env,
  306.     construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0)
  307. return (ret);
  308. }
  309. imp_ = wrap(env);
  310. env->api1_internal = this; // for DB_ENV* to DbEnv* conversion
  311. return (0);
  312. }
  313. // lock methods
  314. DBENV_METHOD(lock_detect, (u_int32_t flags, u_int32_t atype, int *aborted),
  315.     (dbenv, flags, atype, aborted))
  316. DBENV_METHOD_ERR(lock_get,
  317.     (u_int32_t locker, u_int32_t flags, const Dbt *obj,
  318.     db_lockmode_t lock_mode, DbLock *lock),
  319.     (dbenv, locker, flags, obj, lock_mode, &lock->lock_),
  320.     DbEnv::runtime_error_lock_get("DbEnv::lock_get", ret,
  321.   DB_LOCK_GET, lock_mode, obj, *lock,
  322.   -1, error_policy()))
  323. DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))
  324. DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))
  325. DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))
  326. DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags),
  327.     (dbenv, statp, flags))
  328. DBENV_METHOD_ERR(lock_vec,
  329.     (u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
  330.     int nlist, DB_LOCKREQ **elist_returned),
  331.     (dbenv, locker, flags, list, nlist, elist_returned),
  332.     DbEnv::runtime_error_lock_get("DbEnv::lock_vec", ret,
  333. (*elist_returned)->op, (*elist_returned)->mode,
  334. Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock),
  335. (*elist_returned) - list, error_policy()))
  336. // log methods
  337. DBENV_METHOD(log_archive, (char **list[], u_int32_t flags),
  338.     (dbenv, list, flags))
  339. int DbEnv::log_compare(const DbLsn *lsn0, const DbLsn *lsn1)
  340. {
  341. return (::log_compare(lsn0, lsn1));
  342. }
  343. // The following cast implies that DbLogc can be no larger than DB_LOGC
  344. DBENV_METHOD(log_cursor, (DbLogc **cursorp, u_int32_t flags),
  345.     (dbenv, (DB_LOGC **)cursorp, flags))
  346. DBENV_METHOD(log_file, (DbLsn *lsn, char *namep, size_t len),
  347.     (dbenv, lsn, namep, len))
  348. DBENV_METHOD(log_flush, (const DbLsn *lsn), (dbenv, lsn))
  349. DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
  350.     (dbenv, lsn, data, flags))
  351. DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
  352.     (dbenv, spp, flags))
  353. int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
  354. {
  355. DB_ENV *env = unwrap(this);
  356. int ret;
  357. DB_MPOOLFILE *mpf;
  358. if (env == NULL)
  359. ret = EINVAL;
  360. else
  361. ret = env->memp_fcreate(env, &mpf, flags);
  362. if (DB_RETOK_STD(ret)) {
  363. *dbmfp = new DbMpoolFile();
  364. (*dbmfp)->imp_ = wrap(mpf);
  365. } else
  366. DB_ERROR("DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
  367. return (ret);
  368. }
  369. DBENV_METHOD(memp_register,
  370.     (int ftype, pgin_fcn_type pgin_fcn, pgout_fcn_type pgout_fcn),
  371.     (dbenv, ftype, pgin_fcn, pgout_fcn))
  372. // memory pool methods
  373. DBENV_METHOD(memp_stat,
  374.     (DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags),
  375.     (dbenv, gsp, fsp, flags))
  376. DBENV_METHOD(memp_sync, (DbLsn *sn), (dbenv, sn))
  377. DBENV_METHOD(memp_trickle, (int pct, int *nwrotep), (dbenv, pct, nwrotep))
  378. // If an error occurred during the constructor, report it now.
  379. // Otherwise, call the underlying DB->open method.
  380. //
  381. int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
  382. {
  383. int ret;
  384. DB_ENV *env = unwrap(this);
  385. if (construct_error_ != 0)
  386. ret = construct_error_;
  387. else
  388. ret = env->open(env, db_home, flags, mode);
  389. if (!DB_RETOK_STD(ret))
  390. DB_ERROR("DbEnv::open", ret, error_policy());
  391. return (ret);
  392. }
  393. int DbEnv::remove(const char *db_home, u_int32_t flags)
  394. {
  395. int ret;
  396. DB_ENV *env = unwrap(this);
  397. // after a remove (no matter if success or failure),
  398. // the underlying DB_ENV object must not be accessed,
  399. // so we clean up in advance.
  400. //
  401. cleanup();
  402. if ((ret = env->remove(env, db_home, flags)) != 0)
  403. DB_ERROR("DbEnv::remove", ret, error_policy());
  404. return (ret);
  405. }
  406. // Report an error associated with the DbEnv.
  407. // error_policy is one of:
  408. //   ON_ERROR_THROW     throw an error
  409. //   ON_ERROR_RETURN    do nothing here, the caller will return an error
  410. //   ON_ERROR_UNKNOWN   defer the policy to policy saved in DbEnv::DbEnv
  411. //
  412. void DbEnv::runtime_error(const char *caller, int error, int error_policy)
  413. {
  414. if (error_policy == ON_ERROR_UNKNOWN)
  415. error_policy = last_known_error_policy;
  416. if (error_policy == ON_ERROR_THROW) {
  417. // Creating and throwing the object in two separate
  418. // statements seems to be necessary for HP compilers.
  419. switch (error) {
  420. case DB_LOCK_DEADLOCK:
  421. {
  422. DbDeadlockException dl_except(caller);
  423. throw dl_except;
  424. }
  425. break;
  426. case DB_RUNRECOVERY:
  427. {
  428. DbRunRecoveryException rr_except(caller);
  429. throw rr_except;
  430. }
  431. break;
  432. default:
  433. {
  434. DbException except(caller, error);
  435. throw except;
  436. }
  437. break;
  438. }
  439. }
  440. }
  441. // Like DbEnv::runtime_error, but issue a DbMemoryException
  442. // based on the fact that this Dbt is not large enough.
  443. void DbEnv::runtime_error_dbt(const char *caller, Dbt *dbt, int error_policy)
  444. {
  445. if (error_policy == ON_ERROR_UNKNOWN)
  446. error_policy = last_known_error_policy;
  447. if (error_policy == ON_ERROR_THROW) {
  448. // Creating and throwing the object in two separate
  449. // statements seems to be necessary for HP compilers.
  450. DbMemoryException except(caller, dbt);
  451. throw except;
  452. }
  453. }
  454. // Like DbEnv::runtime_error, but issue a DbLockNotGrantedException,
  455. // or a regular runtime error.
  456. // call regular runtime_error if it
  457. void DbEnv::runtime_error_lock_get(const char *caller, int error,
  458.     db_lockop_t op, db_lockmode_t mode, const Dbt *obj,
  459.     DbLock lock, int index, int error_policy)
  460. {
  461. if (error != DB_LOCK_NOTGRANTED) {
  462. runtime_error(caller, error, error_policy);
  463. return;
  464. }
  465. if (error_policy == ON_ERROR_UNKNOWN)
  466. error_policy = last_known_error_policy;
  467. if (error_policy == ON_ERROR_THROW) {
  468. // Creating and throwing the object in two separate
  469. // statements seems to be necessary for HP compilers.
  470. DbLockNotGrantedException except(caller, op, mode,
  471.     obj, lock, index);
  472. throw except;
  473. }
  474. }
  475. // static method
  476. char *DbEnv::strerror(int error)
  477. {
  478. return (db_strerror(error));
  479. }
  480. void DbEnv::_stream_error_function(const char *prefix, char *message)
  481. {
  482. // HP compilers need the extra casts, we don't know why.
  483. if (error_stream_) {
  484. if (prefix) {
  485. (*error_stream_) << prefix << (const char *)": ";
  486. }
  487. if (message) {
  488. (*error_stream_) << (const char *)message;
  489. }
  490. (*error_stream_) << (const char *)"n";
  491. }
  492. }
  493. // set methods
  494. DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
  495. DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
  496. // We keep these alphabetical by field name,
  497. // for comparison with Java's list.
  498. //
  499. DBENV_METHOD(set_data_dir, (const char *dir), (dbenv, dir))
  500. DBENV_METHOD(set_encrypt, (const char *passwd, int flags),
  501.     (dbenv, passwd, flags))
  502. DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
  503. DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir))
  504. DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
  505. DBENV_METHOD(set_lg_regionmax, (u_int32_t regionmax), (dbenv, regionmax))
  506. DBENV_METHOD(set_lk_detect, (u_int32_t detect), (dbenv, detect))
  507. DBENV_METHOD(set_lk_max, (u_int32_t max), (dbenv, max))
  508. DBENV_METHOD(set_lk_max_lockers, (u_int32_t max_lockers), (dbenv, max_lockers))
  509. DBENV_METHOD(set_lk_max_locks, (u_int32_t max_locks), (dbenv, max_locks))
  510. DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects))
  511. DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
  512. DBENV_METHOD(set_tmp_dir, (const char *tmp_dir), (dbenv, tmp_dir))
  513. DBENV_METHOD(set_tx_max, (u_int32_t tx_max), (dbenv, tx_max))
  514. DBENV_METHOD_QUIET(set_alloc,
  515.     (db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn,
  516.     db_free_fcn_type free_fcn),
  517.     (dbenv, malloc_fcn, realloc_fcn, free_fcn))
  518. void DbEnv::set_app_private(void *value)
  519. {
  520. unwrap(this)->app_private = value;
  521. }
  522. DBENV_METHOD(set_cachesize,
  523.     (u_int32_t gbytes, u_int32_t bytes, int ncache),
  524.     (dbenv, gbytes, bytes, ncache))
  525. void DbEnv::set_errcall(void (*arg)(const char *, char *))
  526. {
  527. DB_ENV *dbenv = unwrap(this);
  528. // XXX
  529. // We are casting from a function ptr declared with C++
  530. // linkage to one (same arg types) declared with C
  531. // linkage.  It's hard to imagine a pair of C/C++
  532. // compilers from the same vendor for which this
  533. // won't work.  Unfortunately, we can't use a
  534. // intercept function like the others since the
  535. // function does not have a (DbEnv*) as one of
  536. // the args.  If this causes trouble, we can pull
  537. // the same trick we use in Java, namely stuffing
  538. // a (DbEnv*) pointer into the prefix.  We're
  539. // avoiding this for the moment because it obfuscates.
  540. //
  541. (*(dbenv->set_errcall))(dbenv, (db_errcall_fcn_type)arg);
  542. }
  543. // Note: This actually behaves a bit like a static function,
  544. // since DB_ENV.db_errcall has no information about which
  545. // db_env triggered the call.  A user that has multiple DB_ENVs
  546. // will simply not be able to have different streams for each one.
  547. //
  548. void DbEnv::set_error_stream(__DB_OSTREAMCLASS *stream)
  549. {
  550. DB_ENV *dbenv = unwrap(this);
  551. error_stream_ = stream;
  552. dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
  553.    _stream_error_function_c);
  554. }
  555. int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
  556. {
  557. DB_ENV *dbenv = unwrap(this);
  558. feedback_callback_ = arg;
  559. return ((*(dbenv->set_feedback))(dbenv, _feedback_intercept_c));
  560. }
  561. DBENV_METHOD(set_flags, (u_int32_t flags, int onoff), (dbenv, flags, onoff))
  562. DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
  563.     (dbenv, lk_conflicts, lk_max))
  564. int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
  565. {
  566. DB_ENV *dbenv = unwrap(this);
  567. paniccall_callback_ = arg;
  568. return ((*(dbenv->set_paniccall))(dbenv, _paniccall_intercept_c));
  569. }
  570. DBENV_METHOD(set_rpc_server,
  571.     (void *cl, char *host, long tsec, long ssec, u_int32_t flags),
  572.     (dbenv, cl, host, tsec, ssec, flags))
  573. DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key))
  574. // Note: this changes from last_known_error_policy to error_policy()
  575. DBENV_METHOD(set_tas_spins, (u_int32_t arg), (dbenv, arg))
  576. int DbEnv::set_app_dispatch
  577.     (int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
  578. {
  579. DB_ENV *dbenv = unwrap(this);
  580. int ret;
  581. app_dispatch_callback_ = arg;
  582. if ((ret = (*(dbenv->set_app_dispatch))(dbenv,
  583.     _app_dispatch_intercept_c)) != 0)
  584. DB_ERROR("DbEnv::set_app_dispatch", ret, error_policy());
  585. return (ret);
  586. }
  587. DBENV_METHOD(set_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
  588. DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff))
  589. int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
  590. {
  591. DB_ENV *env = unwrap(this);
  592. DB_TXN *txn;
  593. int ret;
  594. ret = env->txn_begin(env, unwrap(pid), &txn, flags);
  595. if (DB_RETOK_STD(ret))
  596. *tid = new DbTxn(txn);
  597. else
  598. DB_ERROR("DbEnv::txn_begin", ret, error_policy());
  599. return (ret);
  600. }
  601. DBENV_METHOD(txn_checkpoint, (u_int32_t kbyte, u_int32_t min, u_int32_t flags),
  602.     (dbenv, kbyte, min, flags))
  603. int DbEnv::txn_recover(DbPreplist *preplist, long count,
  604.     long *retp, u_int32_t flags)
  605. {
  606. DB_ENV *dbenv = unwrap(this);
  607. DB_PREPLIST *c_preplist;
  608. long i;
  609. int ret;
  610. /*
  611.  * We need to allocate some local storage for the
  612.  * returned preplist, and that requires us to do
  613.  * our own argument validation.
  614.  */
  615. if (count <= 0)
  616. ret = EINVAL;
  617. else
  618. ret = __os_malloc(dbenv, sizeof(DB_PREPLIST) * count,
  619.     &c_preplist);
  620. if (ret != 0) {
  621. DB_ERROR("DbEnv::txn_recover", ret, error_policy());
  622. return (ret);
  623. }
  624. if ((ret =
  625.     dbenv->txn_recover(dbenv, c_preplist, count, retp, flags)) != 0) {
  626. __os_free(dbenv, c_preplist);
  627. DB_ERROR("DbEnv::txn_recover", ret, error_policy());
  628. return (ret);
  629. }
  630. for (i = 0; i < *retp; i++) {
  631. preplist[i].txn = new DbTxn();
  632. preplist[i].txn->imp_ = wrap(c_preplist[i].txn);
  633. memcpy(preplist[i].gid, c_preplist[i].gid,
  634.     sizeof(preplist[i].gid));
  635. }
  636. __os_free(dbenv, c_preplist);
  637. return (0);
  638. }
  639. DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
  640.     (dbenv, statp, flags))
  641. int DbEnv::set_rep_transport(u_int32_t myid,
  642.     int (*f_send)(DbEnv *, const Dbt *, const Dbt *, int, u_int32_t))
  643. {
  644. DB_ENV *dbenv = unwrap(this);
  645. int ret;
  646. rep_send_callback_ = f_send;
  647. if ((ret = dbenv->set_rep_transport(dbenv,
  648.     myid, _rep_send_intercept_c)) != 0)
  649. DB_ERROR("DbEnv::set_rep_transport", ret, error_policy());
  650. return (ret);
  651. }
  652. DBENV_METHOD(rep_elect,
  653.     (int nsites, int pri, u_int32_t timeout, int *idp),
  654.     (dbenv, nsites, pri, timeout, idp))
  655. int DbEnv::rep_process_message(Dbt *control, Dbt *rec, int *idp)
  656. {
  657. DB_ENV *dbenv = unwrap(this);
  658. int ret;
  659. ret = dbenv->rep_process_message(dbenv, control, rec, idp);
  660. if (!DB_RETOK_REPPMSG(ret))
  661. DB_ERROR("DbEnv::rep_process_message", ret, error_policy());
  662. return (ret);
  663. }
  664. DBENV_METHOD(rep_start,
  665.     (Dbt *cookie, u_int32_t flags),
  666.     (dbenv, (DBT *)cookie, flags))
  667. DBENV_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
  668.     (dbenv, statp, flags))
  669. DBENV_METHOD(set_rep_limit, (u_int32_t gbytes, u_int32_t bytes),
  670.     (dbenv, gbytes, bytes))
  671. DBENV_METHOD(set_timeout,
  672.     (db_timeout_t timeout, u_int32_t flags),
  673.     (dbenv, timeout, flags))
  674. // static method
  675. char *DbEnv::version(int *major, int *minor, int *patch)
  676. {
  677. return (db_version(major, minor, patch));
  678. }
  679. // static method
  680. DbEnv *DbEnv::wrap_DB_ENV(DB_ENV *dbenv)
  681. {
  682. DbEnv *wrapped_env = get_DbEnv(dbenv);
  683. if (wrapped_env == NULL)
  684. wrapped_env = new DbEnv(dbenv, 0);
  685. return wrapped_env;
  686. }