1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13#include "db_cxx.h" 14#include "dbinc/cxx_int.h" 15 16#include "dbinc/db_page.h" 17#include "dbinc_auto/db_auto.h" 18#include "dbinc_auto/crdel_auto.h" 19#include "dbinc/db_dispatch.h" 20#include "dbinc_auto/db_ext.h" 21#include "dbinc_auto/common_ext.h" 22 23// Helper macros for simple methods that pass through to the 24// underlying C method. It may return an error or raise an exception. 25// Note this macro expects that input _argspec is an argument 26// list element (e.g., "char *arg") and that _arglist is the arguments 27// that should be passed through to the C method (e.g., "(db, arg)") 28// 29#define DB_METHOD(_name, _argspec, _arglist, _retok) \ 30int Db::_name _argspec \ 31{ \ 32 int ret; \ 33 DB *db = unwrap(this); \ 34 \ 35 ret = db->_name _arglist; \ 36 if (!_retok(ret)) \ 37 DB_ERROR(dbenv_, "Db::" # _name, ret, error_policy()); \ 38 return (ret); \ 39} 40 41#define DB_DESTRUCTOR(_name, _argspec, _arglist, _retok) \ 42int Db::_name _argspec \ 43{ \ 44 int ret; \ 45 DB *db = unwrap(this); \ 46 \ 47 if (!db) { \ 48 DB_ERROR(dbenv_, "Db::" # _name, EINVAL, error_policy()); \ 49 return (EINVAL); \ 50 } \ 51 ret = db->_name _arglist; \ 52 cleanup(); \ 53 if (!_retok(ret)) \ 54 DB_ERROR(dbenv_, "Db::" # _name, ret, error_policy()); \ 55 return (ret); \ 56} 57 58#define DB_METHOD_QUIET(_name, _argspec, _arglist) \ 59int Db::_name _argspec \ 60{ \ 61 DB *db = unwrap(this); \ 62 \ 63 return (db->_name _arglist); \ 64} 65 66#define DB_METHOD_VOID(_name, _argspec, _arglist) \ 67void Db::_name _argspec \ 68{ \ 69 DB *db = unwrap(this); \ 70 \ 71 db->_name _arglist; \ 72} 73 74// A truism for the Db object is that there is a valid 75// DB handle from the constructor until close(). 76// After the close, the DB handle is invalid and 77// no operations are permitted on the Db (other than 78// destructor). Leaving the Db handle open and not 79// doing a close is generally considered an error. 80// 81// We used to allow Db objects to be closed and reopened. 82// This implied always keeping a valid DB object, and 83// coordinating the open objects between Db/DbEnv turned 84// out to be overly complicated. Now we do not allow this. 85 86Db::Db(DbEnv *dbenv, u_int32_t flags) 87: imp_(0) 88, dbenv_(dbenv) 89, mpf_(0) 90, construct_error_(0) 91, flags_(0) 92, construct_flags_(flags) 93, append_recno_callback_(0) 94, associate_callback_(0) 95, associate_foreign_callback_(0) 96, bt_compare_callback_(0) 97, bt_compress_callback_(0) 98, bt_decompress_callback_(0) 99, bt_prefix_callback_(0) 100, db_partition_callback_(0) 101, dup_compare_callback_(0) 102, feedback_callback_(0) 103, h_compare_callback_(0) 104, h_hash_callback_(0) 105{ 106 if (dbenv_ == 0) 107 flags_ |= DB_CXX_PRIVATE_ENV; 108 109 if ((construct_error_ = initialize()) != 0) 110 DB_ERROR(dbenv_, "Db::Db", construct_error_, error_policy()); 111} 112 113// If the DB handle is still open, we close it. This is to make stack 114// allocation of Db objects easier so that they are cleaned up in the error 115// path. If the environment was closed prior to this, it may cause a trap, but 116// an error message is generated during the environment close. Applications 117// should call close explicitly in normal (non-exceptional) cases to check the 118// return value. 119// 120Db::~Db() 121{ 122 DB *db; 123 124 db = unwrap(this); 125 if (db != NULL) { 126 (void)db->close(db, 0); 127 cleanup(); 128 } 129} 130 131// private method to initialize during constructor. 132// initialize must create a backing DB object, 133// and if that creates a new DB_ENV, it must be tied to a new DbEnv. 134// 135int Db::initialize() 136{ 137 DB *db; 138 DB_ENV *cenv = unwrap(dbenv_); 139 int ret; 140 u_int32_t cxx_flags; 141 142 cxx_flags = construct_flags_ & DB_CXX_NO_EXCEPTIONS; 143 144 // Create a new underlying DB object. 145 // We rely on the fact that if a NULL DB_ENV* is given, 146 // one is allocated by DB. 147 // 148 if ((ret = db_create(&db, cenv, 149 construct_flags_ & ~cxx_flags)) != 0) 150 return (ret); 151 152 // Associate the DB with this object 153 imp_ = db; 154 db->api_internal = this; 155 156 // Create a new DbEnv from a DB_ENV* if it was created locally. 157 // It is deleted in Db::close(). 158 // 159 if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) 160 dbenv_ = new DbEnv(db->dbenv, cxx_flags); 161 162 // Create a DbMpoolFile from the DB_MPOOLFILE* in the DB handle. 163 mpf_ = new DbMpoolFile(); 164 mpf_->imp_ = db->mpf; 165 166 return (0); 167} 168 169// private method to cleanup after destructor or during close. 170// If the environment was created by this Db object, we need to delete it. 171// 172void Db::cleanup() 173{ 174 if (imp_ != 0) { 175 imp_ = 0; 176 177 // we must dispose of the DbEnv object if 178 // we created it. This will be the case 179 // if a NULL DbEnv was passed into the constructor. 180 // The underlying DB_ENV object will be inaccessible 181 // after the close, so we must clean it up now. 182 // 183 if ((flags_ & DB_CXX_PRIVATE_ENV) != 0) { 184 dbenv_->cleanup(); 185 delete dbenv_; 186 dbenv_ = 0; 187 } 188 189 delete mpf_; 190 } 191} 192 193// Return a tristate value corresponding to whether we should 194// throw exceptions on errors: 195// ON_ERROR_RETURN 196// ON_ERROR_THROW 197// ON_ERROR_UNKNOWN 198// 199int Db::error_policy() 200{ 201 if (dbenv_ != NULL) 202 return (dbenv_->error_policy()); 203 else { 204 // If the dbenv_ is null, that means that the user 205 // did not attach an environment, so the correct error 206 // policy can be deduced from constructor flags 207 // for this Db. 208 // 209 if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) { 210 return (ON_ERROR_RETURN); 211 } 212 else { 213 return (ON_ERROR_THROW); 214 } 215 } 216} 217 218DB_DESTRUCTOR(close, (u_int32_t flags), (db, flags), DB_RETOK_STD) 219DB_METHOD(compact, (DbTxn *txnid, Dbt *start, Dbt *stop, 220 DB_COMPACT *c_data, u_int32_t flags, Dbt *end), 221 (db, unwrap(txnid), start, stop, c_data, flags, end), DB_RETOK_STD) 222 223// The following cast implies that Dbc can be no larger than DBC 224DB_METHOD(cursor, (DbTxn *txnid, Dbc **cursorp, u_int32_t flags), 225 (db, unwrap(txnid), (DBC **)cursorp, flags), 226 DB_RETOK_STD) 227 228DB_METHOD(del, (DbTxn *txnid, Dbt *key, u_int32_t flags), 229 (db, unwrap(txnid), key, flags), 230 DB_RETOK_DBDEL) 231 232void Db::err(int error, const char *format, ...) 233{ 234 DB *db = unwrap(this); 235 236 DB_REAL_ERR(db->dbenv, error, DB_ERROR_SET, 1, format); 237} 238 239void Db::errx(const char *format, ...) 240{ 241 DB *db = unwrap(this); 242 243 DB_REAL_ERR(db->dbenv, 0, DB_ERROR_NOT_SET, 1, format); 244} 245 246DB_METHOD(exists, (DbTxn *txnid, Dbt *key, u_int32_t flags), 247 (db, unwrap(txnid), key, flags), DB_RETOK_EXISTS) 248 249DB_METHOD(fd, (int *fdp), (db, fdp), DB_RETOK_STD) 250 251int Db::get(DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags) 252{ 253 DB *db = unwrap(this); 254 int ret; 255 256 ret = db->get(db, unwrap(txnid), key, value, flags); 257 258 if (!DB_RETOK_DBGET(ret)) { 259 if (ret == DB_BUFFER_SMALL) 260 DB_ERROR_DBT(dbenv_, "Db::get", value, error_policy()); 261 else 262 DB_ERROR(dbenv_, "Db::get", ret, error_policy()); 263 } 264 265 return (ret); 266} 267 268int Db::get_byteswapped(int *isswapped) 269{ 270 DB *db = (DB *)unwrapConst(this); 271 return (db->get_byteswapped(db, isswapped)); 272} 273 274DbEnv *Db::get_env() 275{ 276 DB *db = (DB *)unwrapConst(this); 277 DB_ENV *dbenv = db->get_env(db); 278 return (dbenv != NULL ? DbEnv::get_DbEnv(dbenv) : NULL); 279} 280 281DbMpoolFile *Db::get_mpf() 282{ 283 return (mpf_); 284} 285 286DB_METHOD(get_dbname, (const char **filenamep, const char **dbnamep), 287 (db, filenamep, dbnamep), DB_RETOK_STD) 288 289DB_METHOD(get_open_flags, (u_int32_t *flagsp), (db, flagsp), DB_RETOK_STD) 290 291int Db::get_type(DBTYPE *dbtype) 292{ 293 DB *db = (DB *)unwrapConst(this); 294 return (db->get_type(db, dbtype)); 295} 296 297// Dbc is a "compatible" subclass of DBC - that is, no virtual functions 298// or even extra data members, so these casts, although technically 299// non-portable, "should" always be okay. 300DB_METHOD(join, (Dbc **curslist, Dbc **cursorp, u_int32_t flags), 301 (db, (DBC **)curslist, (DBC **)cursorp, flags), DB_RETOK_STD) 302 303DB_METHOD(key_range, 304 (DbTxn *txnid, Dbt *key, DB_KEY_RANGE *results, u_int32_t flags), 305 (db, unwrap(txnid), key, results, flags), DB_RETOK_STD) 306 307// If an error occurred during the constructor, report it now. 308// Otherwise, call the underlying DB->open method. 309// 310int Db::open(DbTxn *txnid, const char *file, const char *database, 311 DBTYPE type, u_int32_t flags, int mode) 312{ 313 int ret; 314 DB *db = unwrap(this); 315 316 if (construct_error_ != 0) 317 ret = construct_error_; 318 else 319 ret = db->open(db, unwrap(txnid), file, database, type, flags, 320 mode); 321 322 if (!DB_RETOK_STD(ret)) 323 DB_ERROR(dbenv_, "Db::open", ret, error_policy()); 324 325 return (ret); 326} 327 328int Db::pget(DbTxn *txnid, Dbt *key, Dbt *pkey, Dbt *value, u_int32_t flags) 329{ 330 DB *db = unwrap(this); 331 int ret; 332 333 ret = db->pget(db, unwrap(txnid), key, pkey, value, flags); 334 335 /* The logic here is identical to Db::get - reuse the macro. */ 336 if (!DB_RETOK_DBGET(ret)) { 337 if (ret == DB_BUFFER_SMALL && DB_OVERFLOWED_DBT(value)) 338 DB_ERROR_DBT(dbenv_, "Db::pget", value, error_policy()); 339 else 340 DB_ERROR(dbenv_, "Db::pget", ret, error_policy()); 341 } 342 343 return (ret); 344} 345 346DB_METHOD(put, (DbTxn *txnid, Dbt *key, Dbt *value, u_int32_t flags), 347 (db, unwrap(txnid), key, value, flags), DB_RETOK_DBPUT) 348 349DB_DESTRUCTOR(rename, 350 (const char *file, const char *database, const char *newname, 351 u_int32_t flags), 352 (db, file, database, newname, flags), DB_RETOK_STD) 353 354DB_DESTRUCTOR(remove, (const char *file, const char *database, u_int32_t flags), 355 (db, file, database, flags), DB_RETOK_STD) 356 357DB_METHOD(truncate, (DbTxn *txnid, u_int32_t *countp, u_int32_t flags), 358 (db, unwrap(txnid), countp, flags), DB_RETOK_STD) 359 360DB_METHOD(stat, (DbTxn *txnid, void *sp, u_int32_t flags), 361 (db, unwrap(txnid), sp, flags), DB_RETOK_STD) 362 363DB_METHOD(stat_print, (u_int32_t flags), (db, flags), DB_RETOK_STD) 364 365DB_METHOD(sync, (u_int32_t flags), (db, flags), DB_RETOK_STD) 366 367DB_METHOD(upgrade, 368 (const char *name, u_int32_t flags), (db, name, flags), DB_RETOK_STD) 369 370//////////////////////////////////////////////////////////////////////// 371// 372// callbacks 373// 374// *_intercept_c are 'glue' functions that must be declared 375// as extern "C" so to be typesafe. Using a C++ method, even 376// a static class method with 'correct' arguments, will not pass 377// the test; some picky compilers do not allow mixing of function 378// pointers to 'C' functions with function pointers to C++ functions. 379// 380// One wart with this scheme is that the *_callback_ method pointer 381// must be declared public to be accessible by the C intercept. 382// It's possible to accomplish the goal without this, and with 383// another public transfer method, but it's just too much overhead. 384// These callbacks are supposed to be *fast*. 385// 386// The DBTs we receive in these callbacks from the C layer may be 387// manufactured there, but we want to treat them as a Dbts. 388// Technically speaking, these DBTs were not constructed as a Dbts, 389// but it should be safe to cast them as such given that Dbt is a 390// *very* thin extension of the DBT. That is, Dbt has no additional 391// data elements, does not use virtual functions, virtual inheritance, 392// multiple inheritance, RTI, or any other language feature that 393// causes the structure to grow or be displaced. Although this may 394// sound risky, a design goal of C++ is complete structure 395// compatibility with C, and has the philosophy 'if you don't use it, 396// you shouldn't incur the overhead'. If the C/C++ compilers you're 397// using on a given machine do not have matching struct layouts, then 398// a lot more things will be broken than just this. 399// 400// The alternative, creating a Dbt here in the callback, and populating 401// it from the DBT, is just too slow and cumbersome to be very useful. 402 403// These macros avoid a lot of boilerplate code for callbacks 404 405#define DB_CALLBACK_C_INTERCEPT(_name, _rettype, _cargspec, \ 406 _return, _cxxargs) \ 407extern "C" _rettype _db_##_name##_intercept_c _cargspec \ 408{ \ 409 Db *cxxthis; \ 410 \ 411 /* We don't have a dbenv handle at this point. */ \ 412 DB_ASSERT(NULL, cthis != NULL); \ 413 cxxthis = Db::get_Db(cthis); \ 414 DB_ASSERT(cthis->dbenv->env, cxxthis != NULL); \ 415 DB_ASSERT(cthis->dbenv->env, cxxthis->_name##_callback_ != 0); \ 416 \ 417 _return (*cxxthis->_name##_callback_) _cxxargs; \ 418} 419 420#define DB_SET_CALLBACK(_cxxname, _name, _cxxargspec, _cb) \ 421int Db::_cxxname _cxxargspec \ 422{ \ 423 DB *cthis = unwrap(this); \ 424 \ 425 _name##_callback_ = _cb; \ 426 return ((*(cthis->_cxxname))(cthis, \ 427 (_cb) ? _db_##_name##_intercept_c : NULL)); \ 428} 429 430#define DB_GET_CALLBACK(_cxxname, _name, _cxxargspec, _cbp) \ 431int Db::_cxxname _cxxargspec \ 432{ \ 433 if (_cbp != NULL) \ 434 *(_cbp) = _name##_callback_; \ 435 return 0; \ 436} 437 438/* associate callback - doesn't quite fit the pattern because of the flags */ 439DB_CALLBACK_C_INTERCEPT(associate, 440 int, (DB *cthis, const DBT *key, const DBT *data, DBT *retval), 441 return, (cxxthis, Dbt::get_const_Dbt(key), Dbt::get_const_Dbt(data), 442 Dbt::get_Dbt(retval))) 443 444int Db::associate(DbTxn *txn, Db *secondary, int (*callback)(Db *, const Dbt *, 445 const Dbt *, Dbt *), u_int32_t flags) 446{ 447 DB *cthis = unwrap(this); 448 449 /* Since the secondary Db is used as the first argument 450 * to the callback, we store the C++ callback on it 451 * rather than on 'this'. 452 */ 453 secondary->associate_callback_ = callback; 454 return ((*(cthis->associate))(cthis, unwrap(txn), unwrap(secondary), 455 (callback) ? _db_associate_intercept_c : NULL, flags)); 456} 457 458/* associate callback - doesn't quite fit the pattern because of the flags */ 459DB_CALLBACK_C_INTERCEPT(associate_foreign, int, 460 (DB *cthis, const DBT *key, DBT *data, const DBT *fkey, int *changed), 461 return, (cxxthis, Dbt::get_const_Dbt(key), 462 Dbt::get_Dbt(data), Dbt::get_const_Dbt(fkey), changed)) 463 464int Db::associate_foreign(Db *secondary, int (*callback)(Db *, 465 const Dbt *, Dbt *, const Dbt *, int *), u_int32_t flags) 466{ 467 DB *cthis = unwrap(this); 468 469 secondary->associate_foreign_callback_ = callback; 470 return ((*(cthis->associate_foreign))(cthis, unwrap(secondary), 471 (callback) ? _db_associate_foreign_intercept_c : NULL, flags)); 472} 473 474DB_CALLBACK_C_INTERCEPT(feedback, 475 void, (DB *cthis, int opcode, int pct), 476 /* no return */ (void), (cxxthis, opcode, pct)) 477 478DB_GET_CALLBACK(get_feedback, feedback, 479 (void (**argp)(Db *cxxthis, int opcode, int pct)), argp) 480 481DB_SET_CALLBACK(set_feedback, feedback, 482 (void (*arg)(Db *cxxthis, int opcode, int pct)), arg) 483 484DB_CALLBACK_C_INTERCEPT(append_recno, 485 int, (DB *cthis, DBT *data, db_recno_t recno), 486 return, (cxxthis, Dbt::get_Dbt(data), recno)) 487 488DB_GET_CALLBACK(get_append_recno, append_recno, 489 (int (**argp)(Db *cxxthis, Dbt *data, db_recno_t recno)), argp) 490 491DB_SET_CALLBACK(set_append_recno, append_recno, 492 (int (*arg)(Db *cxxthis, Dbt *data, db_recno_t recno)), arg) 493 494DB_CALLBACK_C_INTERCEPT(bt_compare, 495 int, (DB *cthis, const DBT *data1, const DBT *data2), 496 return, 497 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2))) 498 499DB_GET_CALLBACK(get_bt_compare, bt_compare, 500 (int (**argp)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), argp) 501 502DB_SET_CALLBACK(set_bt_compare, bt_compare, 503 (int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg) 504 505DB_CALLBACK_C_INTERCEPT(bt_compress, 506 int, (DB *cthis, const DBT *data1, const DBT *data2, const DBT *data3, 507 const DBT *data4, DBT *data5), return, 508 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2), 509 Dbt::get_const_Dbt(data3), Dbt::get_const_Dbt(data4), Dbt::get_Dbt(data5))) 510 511DB_CALLBACK_C_INTERCEPT(bt_decompress, 512 int, (DB *cthis, const DBT *data1, const DBT *data2, DBT *data3, 513 DBT *data4, DBT *data5), return, 514 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2), 515 Dbt::get_Dbt(data3), Dbt::get_Dbt(data4), Dbt::get_Dbt(data5))) 516 517// The {g|s}et_bt_compress methods don't fit into the standard macro templates 518// since they take two callback functions. 519int Db::get_bt_compress( 520 int (**bt_compress) 521 (Db *, const Dbt *, const Dbt *, const Dbt *, const Dbt *, Dbt *), 522 int (**bt_decompress) 523 (Db *, const Dbt *, const Dbt *, Dbt *, Dbt *, Dbt *)) 524{ 525 if (bt_compress != NULL) 526 *(bt_compress) = bt_compress_callback_; 527 if (bt_decompress != NULL) 528 *(bt_decompress) = bt_decompress_callback_; 529 return 0; 530} 531 532int Db::set_bt_compress( 533 int (*bt_compress) 534 (Db *, const Dbt *, const Dbt *, const Dbt *, const Dbt *, Dbt *), 535 int (*bt_decompress)(Db *, const Dbt *, const Dbt *, Dbt *, Dbt *, Dbt *)) 536{ 537 DB *cthis = unwrap(this); 538 539 bt_compress_callback_ = bt_compress; 540 bt_decompress_callback_ = bt_decompress; 541 return ((*(cthis->set_bt_compress))(cthis, 542 (bt_compress ? _db_bt_compress_intercept_c : NULL), 543 (bt_decompress ? _db_bt_decompress_intercept_c : NULL))); 544 545} 546 547DB_CALLBACK_C_INTERCEPT(bt_prefix, 548 size_t, (DB *cthis, const DBT *data1, const DBT *data2), 549 return, 550 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2))) 551 552DB_GET_CALLBACK(get_bt_prefix, bt_prefix, 553 (size_t (**argp)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), argp) 554 555DB_SET_CALLBACK(set_bt_prefix, bt_prefix, 556 (size_t (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg) 557 558DB_CALLBACK_C_INTERCEPT(dup_compare, 559 int, (DB *cthis, const DBT *data1, const DBT *data2), 560 return, 561 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2))) 562 563DB_GET_CALLBACK(get_dup_compare, dup_compare, 564 (int (**argp)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), argp) 565 566DB_SET_CALLBACK(set_dup_compare, dup_compare, 567 (int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg) 568 569DB_CALLBACK_C_INTERCEPT(h_compare, 570 int, (DB *cthis, const DBT *data1, const DBT *data2), 571 return, 572 (cxxthis, Dbt::get_const_Dbt(data1), Dbt::get_const_Dbt(data2))) 573 574DB_GET_CALLBACK(get_h_compare, h_compare, 575 (int (**argp)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), argp) 576 577DB_SET_CALLBACK(set_h_compare, h_compare, 578 (int (*arg)(Db *cxxthis, const Dbt *data1, const Dbt *data2)), arg) 579 580DB_CALLBACK_C_INTERCEPT(h_hash, 581 u_int32_t, (DB *cthis, const void *data, u_int32_t len), 582 return, (cxxthis, data, len)) 583 584DB_GET_CALLBACK(get_h_hash, h_hash, 585 (u_int32_t (**argp)(Db *cxxthis, const void *data, u_int32_t len)), argp) 586 587DB_SET_CALLBACK(set_h_hash, h_hash, 588 (u_int32_t (*arg)(Db *cxxthis, const void *data, u_int32_t len)), arg) 589 590// This is a 'glue' function declared as extern "C" so it will 591// be compatible with picky compilers that do not allow mixing 592// of function pointers to 'C' functions with function pointers 593// to C++ functions. 594// 595extern "C" 596int _verify_callback_c(void *handle, const void *str_arg) 597{ 598 char *str; 599 __DB_STD(ostream) *out; 600 601 str = (char *)str_arg; 602 out = (__DB_STD(ostream) *)handle; 603 604 (*out) << str; 605 if (out->fail()) 606 return (EIO); 607 608 return (0); 609} 610 611int Db::verify(const char *name, const char *subdb, 612 __DB_STD(ostream) *ostr, u_int32_t flags) 613{ 614 DB *db = unwrap(this); 615 int ret; 616 617 if (!db) 618 ret = EINVAL; 619 else { 620 ret = __db_verify_internal(db, name, subdb, ostr, 621 _verify_callback_c, flags); 622 623 // After a DB->verify (no matter if success or failure), 624 // the underlying DB object must not be accessed. 625 // 626 cleanup(); 627 } 628 629 if (!DB_RETOK_STD(ret)) 630 DB_ERROR(dbenv_, "Db::verify", ret, error_policy()); 631 632 return (ret); 633} 634 635DB_METHOD(set_bt_compare, (bt_compare_fcn_type func), 636 (db, func), DB_RETOK_STD) 637DB_METHOD(get_bt_minkey, (u_int32_t *bt_minkeyp), 638 (db, bt_minkeyp), DB_RETOK_STD) 639DB_METHOD(set_bt_minkey, (u_int32_t bt_minkey), 640 (db, bt_minkey), DB_RETOK_STD) 641DB_METHOD(set_bt_prefix, (bt_prefix_fcn_type func), 642 (db, func), DB_RETOK_STD) 643DB_METHOD(set_dup_compare, (dup_compare_fcn_type func), 644 (db, func), DB_RETOK_STD) 645DB_METHOD(get_encrypt_flags, (u_int32_t *flagsp), 646 (db, flagsp), DB_RETOK_STD) 647DB_METHOD(set_encrypt, (const char *passwd, u_int32_t flags), 648 (db, passwd, flags), DB_RETOK_STD) 649DB_METHOD_VOID(get_errfile, (FILE **errfilep), (db, errfilep)) 650DB_METHOD_VOID(set_errfile, (FILE *errfile), (db, errfile)) 651DB_METHOD_VOID(get_errpfx, (const char **errpfx), (db, errpfx)) 652DB_METHOD_VOID(set_errpfx, (const char *errpfx), (db, errpfx)) 653DB_METHOD(get_flags, (u_int32_t *flagsp), (db, flagsp), 654 DB_RETOK_STD) 655DB_METHOD(set_flags, (u_int32_t flags), (db, flags), 656 DB_RETOK_STD) 657DB_METHOD(set_h_compare, (h_compare_fcn_type func), 658 (db, func), DB_RETOK_STD) 659DB_METHOD(get_h_ffactor, (u_int32_t *h_ffactorp), 660 (db, h_ffactorp), DB_RETOK_STD) 661DB_METHOD(set_h_ffactor, (u_int32_t h_ffactor), 662 (db, h_ffactor), DB_RETOK_STD) 663DB_METHOD(set_h_hash, (h_hash_fcn_type func), 664 (db, func), DB_RETOK_STD) 665DB_METHOD(get_h_nelem, (u_int32_t *h_nelemp), 666 (db, h_nelemp), DB_RETOK_STD) 667DB_METHOD(set_h_nelem, (u_int32_t h_nelem), 668 (db, h_nelem), DB_RETOK_STD) 669DB_METHOD(get_lorder, (int *db_lorderp), (db, db_lorderp), 670 DB_RETOK_STD) 671DB_METHOD(set_lorder, (int db_lorder), (db, db_lorder), 672 DB_RETOK_STD) 673DB_METHOD_VOID(get_msgfile, (FILE **msgfilep), (db, msgfilep)) 674DB_METHOD_VOID(set_msgfile, (FILE *msgfile), (db, msgfile)) 675DB_METHOD_QUIET(get_multiple, (), (db)) 676DB_METHOD(get_pagesize, (u_int32_t *db_pagesizep), 677 (db, db_pagesizep), DB_RETOK_STD) 678DB_METHOD(set_pagesize, (u_int32_t db_pagesize), 679 (db, db_pagesize), DB_RETOK_STD) 680 681DB_CALLBACK_C_INTERCEPT(db_partition, 682 u_int32_t, (DB *cthis, DBT *key), 683 return, (cxxthis, Dbt::get_Dbt(key))) 684 685// set_partition and get_partition_callback do not fit into the macro 686// templates, since there is an additional argument in the API calls. 687int Db::set_partition(u_int32_t parts, Dbt *keys, 688 u_int32_t (*arg)(Db *cxxthis, Dbt *key)) 689{ 690 DB *cthis = unwrap(this); 691 692 db_partition_callback_ = arg; 693 return ((*(cthis->set_partition))(cthis, parts, keys, 694 arg ? _db_db_partition_intercept_c : NULL)); 695} 696 697int Db::get_partition_callback(u_int32_t *parts, 698 u_int32_t (**argp)(Db *cxxthis, Dbt *key)) 699{ 700 DB *cthis = unwrap(this); 701 if (argp != NULL) 702 *(argp) = db_partition_callback_; 703 if (parts != NULL) 704 (cthis->get_partition_callback)(cthis, parts, NULL); 705 return 0; 706} 707 708DB_METHOD(set_partition_dirs, (const char **dirp), (db, dirp), DB_RETOK_STD) 709DB_METHOD(get_partition_dirs, (const char ***dirpp), (db, dirpp), DB_RETOK_STD) 710DB_METHOD(get_partition_keys, (u_int32_t *parts, Dbt **keys), 711 (db, parts, (DBT **)keys), DB_RETOK_STD) 712DB_METHOD(get_priority, (DB_CACHE_PRIORITY *priorityp), 713 (db, priorityp), DB_RETOK_STD) 714DB_METHOD(set_priority, (DB_CACHE_PRIORITY priority), 715 (db, priority), DB_RETOK_STD) 716DB_METHOD(get_re_delim, (int *re_delimp), 717 (db, re_delimp), DB_RETOK_STD) 718DB_METHOD(set_re_delim, (int re_delim), 719 (db, re_delim), DB_RETOK_STD) 720DB_METHOD(get_re_len, (u_int32_t *re_lenp), 721 (db, re_lenp), DB_RETOK_STD) 722DB_METHOD(set_re_len, (u_int32_t re_len), 723 (db, re_len), DB_RETOK_STD) 724DB_METHOD(get_re_pad, (int *re_padp), 725 (db, re_padp), DB_RETOK_STD) 726DB_METHOD(set_re_pad, (int re_pad), 727 (db, re_pad), DB_RETOK_STD) 728DB_METHOD(get_re_source, (const char **re_source), 729 (db, re_source), DB_RETOK_STD) 730DB_METHOD(set_re_source, (const char *re_source), 731 (db, re_source), DB_RETOK_STD) 732DB_METHOD(sort_multiple, (Dbt *key, Dbt *data, u_int32_t flags), 733 (db, key, data, flags), DB_RETOK_STD) 734DB_METHOD(get_q_extentsize, (u_int32_t *extentsizep), 735 (db, extentsizep), DB_RETOK_STD) 736DB_METHOD(set_q_extentsize, (u_int32_t extentsize), 737 (db, extentsize), DB_RETOK_STD) 738 739DB_METHOD_QUIET(get_alloc, (db_malloc_fcn_type *malloc_fcnp, 740 db_realloc_fcn_type *realloc_fcnp, db_free_fcn_type *free_fcnp), 741 (db, malloc_fcnp, realloc_fcnp, free_fcnp)) 742 743DB_METHOD_QUIET(set_alloc, (db_malloc_fcn_type malloc_fcn, 744 db_realloc_fcn_type realloc_fcn, db_free_fcn_type free_fcn), 745 (db, malloc_fcn, realloc_fcn, free_fcn)) 746 747void Db::get_errcall(void (**argp)(const DbEnv *, const char *, const char *)) 748{ 749 dbenv_->get_errcall(argp); 750} 751 752void Db::set_errcall(void (*arg)(const DbEnv *, const char *, const char *)) 753{ 754 dbenv_->set_errcall(arg); 755} 756 757void Db::get_msgcall(void (**argp)(const DbEnv *, const char *)) 758{ 759 dbenv_->get_msgcall(argp); 760} 761 762void Db::set_msgcall(void (*arg)(const DbEnv *, const char *)) 763{ 764 dbenv_->set_msgcall(arg); 765} 766 767void *Db::get_app_private() const 768{ 769 return unwrapConst(this)->app_private; 770} 771 772void Db::set_app_private(void *value) 773{ 774 unwrap(this)->app_private = value; 775} 776 777DB_METHOD(get_cachesize, (u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep), 778 (db, gbytesp, bytesp, ncachep), DB_RETOK_STD) 779DB_METHOD(set_cachesize, (u_int32_t gbytes, u_int32_t bytes, int ncache), 780 (db, gbytes, bytes, ncache), DB_RETOK_STD) 781 782DB_METHOD(get_create_dir, (const char **dirp), (db, dirp), DB_RETOK_STD) 783DB_METHOD(set_create_dir, (const char *dir), (db, dir), DB_RETOK_STD) 784 785int Db::set_paniccall(void (*callback)(DbEnv *, int)) 786{ 787 return (dbenv_->set_paniccall(callback)); 788} 789 790__DB_STD(ostream) *Db::get_error_stream() 791{ 792 return dbenv_->get_error_stream(); 793} 794 795void Db::set_error_stream(__DB_STD(ostream) *error_stream) 796{ 797 dbenv_->set_error_stream(error_stream); 798} 799 800__DB_STD(ostream) *Db::get_message_stream() 801{ 802 return dbenv_->get_message_stream(); 803} 804 805void Db::set_message_stream(__DB_STD(ostream) *message_stream) 806{ 807 dbenv_->set_message_stream(message_stream); 808} 809 810DB_METHOD_QUIET(get_transactional, (), (db)) 811