You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
4.6 KiB

  1. #include <stdarg.h>
  2. #include <assert.h>
  3. #include <errno.h>
  4. #include "../newbrt/brttypes.h"
  5. #include <db_cxx.h>
  6. DbEnv::DbEnv (u_int32_t flags)
  7. : do_no_exceptions((flags&DB_CXX_NO_EXCEPTIONS)!=0),
  8. errcall(NULL)
  9. {
  10. int ret = db_env_create(&the_env, flags & ~DB_CXX_NO_EXCEPTIONS);
  11. assert(ret==0); // should do an error.
  12. the_env->api1_internal = this;
  13. }
  14. DbEnv::DbEnv(DB_ENV *env, u_int32_t flags)
  15. : do_no_exceptions((flags&DB_CXX_NO_EXCEPTIONS)!=0), _error_stream(0)
  16. {
  17. the_env = env;
  18. if (env == 0) {
  19. DB_ENV *new_env;
  20. int ret = db_env_create(&new_env, flags & ~DB_CXX_NO_EXCEPTIONS);
  21. assert(ret==0); // should do an error.
  22. the_env = new_env;
  23. }
  24. the_env->api1_internal = this;
  25. }
  26. // If still open, close it. In most cases, the caller should call close explicitly so that they can catch the exceptions.
  27. DbEnv::~DbEnv(void)
  28. {
  29. if (the_env!=NULL) {
  30. (void)the_env->close(the_env, 0);
  31. the_env = 0;
  32. }
  33. }
  34. int DbEnv::close(u_int32_t flags) {
  35. int ret = EINVAL;
  36. if (the_env)
  37. ret = the_env->close(the_env, flags);
  38. the_env = 0; /* get rid of the env ref, so we don't touch it (even if we failed, or when the destructor is called) */
  39. return maybe_throw_error(ret);
  40. }
  41. int DbEnv::open(const char *home, u_int32_t flags, int mode) {
  42. int ret = the_env->open(the_env, home, flags, mode);
  43. return maybe_throw_error(ret);
  44. }
  45. int DbEnv::set_cachesize(u_int32_t gbytes, u_int32_t bytes, int ncache) {
  46. int ret = the_env->set_cachesize(the_env, gbytes, bytes, ncache);
  47. return maybe_throw_error(ret);
  48. }
  49. int DbEnv::set_flags(u_int32_t flags, int onoff) {
  50. int ret = the_env->set_flags(the_env, flags, onoff);
  51. return maybe_throw_error(ret);
  52. }
  53. #if DB_VERSION_MAJOR<4 || (DB_VERSION_MAJOR==4 && DB_VERSION_MINOR<=4)
  54. int DbEnv::set_lk_max(u_int32_t flags) {
  55. int ret = the_env->set_lk_max(the_env, flags);
  56. return maybe_throw_error(ret);
  57. }
  58. #endif
  59. int DbEnv::txn_begin(DbTxn *parenttxn, DbTxn **txnp, u_int32_t flags) {
  60. DB_TXN *txn;
  61. int ret = the_env->txn_begin(the_env, parenttxn->get_DB_TXN(), &txn, flags);
  62. if (ret==0) {
  63. *txnp = new DbTxn(txn);
  64. }
  65. return maybe_throw_error(ret);
  66. }
  67. int DbEnv::set_data_dir(const char *dir) {
  68. int ret = the_env->set_data_dir(the_env, dir);
  69. return maybe_throw_error(ret);
  70. }
  71. void DbEnv::set_errpfx(const char *errpfx) {
  72. the_env->set_errpfx(the_env, errpfx);
  73. }
  74. int DbEnv::maybe_throw_error(int err, DbEnv *env, int no_exceptions) throw (DbException) {
  75. if (err==0 || err==DB_NOTFOUND || err==DB_KEYEXIST || err==DB_KEYEMPTY) return err;
  76. if (no_exceptions) return err;
  77. if (err==DB_LOCK_DEADLOCK) {
  78. DbDeadlockException e(env);
  79. throw e;
  80. } else {
  81. DbException e(err);
  82. e.set_env(env);
  83. throw e;
  84. }
  85. }
  86. int DbEnv::maybe_throw_error(int err) throw (DbException) {
  87. return maybe_throw_error(err, this, do_no_exceptions);
  88. }
  89. extern "C" {
  90. void toku_ydb_error_all_cases(const DB_ENV * env,
  91. int error,
  92. BOOL include_stderrstring,
  93. BOOL use_stderr_if_nothing_else,
  94. const char *fmt, va_list ap);
  95. };
  96. void DbEnv::err(int error, const char *fmt, ...) {
  97. va_list ap;
  98. va_start(ap, fmt);
  99. toku_ydb_error_all_cases(the_env, error, TRUE, TRUE, fmt, ap);
  100. va_end(ap);
  101. }
  102. void DbEnv::set_errfile(FILE *errfile) {
  103. the_env->set_errfile(the_env, errfile);
  104. }
  105. int DbEnv::get_flags(u_int32_t *flagsp) {
  106. int ret = the_env->get_flags(the_env, flagsp);
  107. return maybe_throw_error(ret);
  108. }
  109. extern "C" void toku_db_env_errcall_c(const DB_ENV *dbenv_c, const char *errpfx, const char *msg) {
  110. DbEnv *dbenv = (DbEnv *) dbenv_c->api1_internal;
  111. dbenv->errcall(dbenv, errpfx, msg);
  112. }
  113. void DbEnv::set_errcall(void (*db_errcall_fcn)(const DbEnv *, const char *, const char *)) {
  114. errcall = db_errcall_fcn;
  115. the_env->set_errcall(the_env, toku_db_env_errcall_c);
  116. }
  117. extern "C" void toku_db_env_error_stream_c(const DB_ENV *dbenv_c, const char *errpfx, const char *msg) {
  118. DbEnv *dbenv = (DbEnv *) dbenv_c->api1_internal;
  119. if (dbenv->_error_stream) {
  120. if (errpfx) *(dbenv->_error_stream) << errpfx;
  121. if (msg) *(dbenv->_error_stream) << ":" << msg << "\n";
  122. }
  123. }
  124. void DbEnv::set_error_stream(std::ostream *new_error_stream) {
  125. _error_stream = new_error_stream;
  126. the_env->set_errcall(the_env, toku_db_env_error_stream_c);
  127. }
  128. int DbEnv::set_lk_max_locks(u_int32_t max_locks) {
  129. int ret = the_env->set_lk_max_locks(the_env, max_locks);
  130. return maybe_throw_error(ret);
  131. }
  132. int DbEnv::get_lk_max_locks(u_int32_t *max_locks) {
  133. int ret = the_env->get_lk_max_locks(the_env, max_locks);
  134. return maybe_throw_error(ret);
  135. }