1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999,2008 Oracle. All rights reserved. 5 * 6 * $Id: db_method.c,v 12.47 2008/01/31 12:50:51 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/crypto.h" 13#include "dbinc/db_page.h" 14#include "dbinc/btree.h" 15#include "dbinc/hash.h" 16#include "dbinc/lock.h" 17#include "dbinc/mp.h" 18#include "dbinc/qam.h" 19#include "dbinc/txn.h" 20 21#ifdef HAVE_RPC 22#ifdef HAVE_SYSTEM_INCLUDE_FILES 23#include <rpc/rpc.h> 24#endif 25#include "db_server.h" 26#include "dbinc_auto/rpc_client_ext.h" 27#endif 28 29static int __db_get_byteswapped __P((DB *, int *)); 30static int __db_get_dbname __P((DB *, const char **, const char **)); 31static DB_ENV *__db_get_env __P((DB *)); 32static DB_MPOOLFILE *__db_get_mpf __P((DB *)); 33static int __db_get_multiple __P((DB *)); 34static int __db_get_transactional __P((DB *)); 35static int __db_get_type __P((DB *, DBTYPE *dbtype)); 36static int __db_init __P((DB *, u_int32_t)); 37static int __db_set_alloc __P((DB *, void *(*)(size_t), 38 void *(*)(void *, size_t), void (*)(void *))); 39static int __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t))); 40static int __db_get_cachesize __P((DB *, u_int32_t *, u_int32_t *, int *)); 41static int __db_set_cachesize __P((DB *, u_int32_t, u_int32_t, int)); 42static int __db_set_dup_compare 43 __P((DB *, int (*)(DB *, const DBT *, const DBT *))); 44static int __db_get_encrypt_flags __P((DB *, u_int32_t *)); 45static int __db_set_encrypt __P((DB *, const char *, u_int32_t)); 46static int __db_set_feedback __P((DB *, void (*)(DB *, int, int))); 47static void __db_map_flags __P((DB *, u_int32_t *, u_int32_t *)); 48static int __db_get_pagesize __P((DB *, u_int32_t *)); 49static int __db_set_paniccall __P((DB *, void (*)(DB_ENV *, int))); 50static int __db_set_priority __P((DB *, DB_CACHE_PRIORITY)); 51static int __db_get_priority __P((DB *, DB_CACHE_PRIORITY *)); 52static void __db_get_errcall __P((DB *, 53 void (**)(const DB_ENV *, const char *, const char *))); 54static void __db_set_errcall 55 __P((DB *, void (*)(const DB_ENV *, const char *, const char *))); 56static void __db_get_errfile __P((DB *, FILE **)); 57static void __db_set_errfile __P((DB *, FILE *)); 58static void __db_get_errpfx __P((DB *, const char **)); 59static void __db_set_errpfx __P((DB *, const char *)); 60static void __db_set_msgcall 61 __P((DB *, void (*)(const DB_ENV *, const char *))); 62static void __db_get_msgfile __P((DB *, FILE **)); 63static void __db_set_msgfile __P((DB *, FILE *)); 64static void __dbh_err __P((DB *, int, const char *, ...)); 65static void __dbh_errx __P((DB *, const char *, ...)); 66 67/* 68 * db_create -- 69 * DB constructor. 70 * 71 * EXTERN: int db_create __P((DB **, DB_ENV *, u_int32_t)); 72 */ 73int 74db_create(dbpp, dbenv, flags) 75 DB **dbpp; 76 DB_ENV *dbenv; 77 u_int32_t flags; 78{ 79 DB_THREAD_INFO *ip; 80 ENV *env; 81 int ret; 82 83 ip = NULL; 84 env = dbenv == NULL ? NULL : dbenv->env; 85 86 /* Check for invalid function flags. */ 87 switch (flags) { 88 case 0: 89 break; 90 case DB_XA_CREATE: 91 if (dbenv != NULL) { 92 __db_errx(env, 93 "XA applications may not specify an environment to db_create"); 94 return (EINVAL); 95 } 96 97 /* 98 * If it's an XA database, open it within the XA environment, 99 * taken from the global list of environments. (When the XA 100 * transaction manager called our xa_start() routine the 101 * "current" environment was moved to the start of the list. 102 */ 103 env = TAILQ_FIRST(&DB_GLOBAL(envq)); 104 break; 105 default: 106 return (__db_ferr(env, "db_create", 0)); 107 } 108 109 if (env != NULL) 110 ENV_ENTER(env, ip); 111 ret = __db_create_internal(dbpp, env, flags); 112 if (env != NULL) 113 ENV_LEAVE(env, ip); 114 115 return (ret); 116} 117 118/* 119 * __db_create_internal -- 120 * DB constructor internal routine. 121 * 122 * PUBLIC: int __db_create_internal __P((DB **, ENV *, u_int32_t)); 123 */ 124int 125__db_create_internal(dbpp, env, flags) 126 DB **dbpp; 127 ENV *env; 128 u_int32_t flags; 129{ 130 DB *dbp; 131 DB_ENV *dbenv; 132 DB_REP *db_rep; 133 int ret; 134 135 *dbpp = NULL; 136 137 /* If we don't have an environment yet, allocate a local one. */ 138 if (env == NULL) { 139 if ((ret = db_env_create(&dbenv, 0)) != 0) 140 return (ret); 141 env = dbenv->env; 142 F_SET(env, ENV_DBLOCAL); 143 } else 144 dbenv = env->dbenv; 145 146 /* Allocate and initialize the DB handle. */ 147 if ((ret = __os_calloc(env, 1, sizeof(*dbp), &dbp)) != 0) 148 goto err; 149 150 dbp->dbenv = env->dbenv; 151 dbp->env = env; 152 if ((ret = __db_init(dbp, flags)) != 0) 153 goto err; 154 155 MUTEX_LOCK(env, env->mtx_dblist); 156 ++env->db_ref; 157 MUTEX_UNLOCK(env, env->mtx_dblist); 158 159 /* 160 * Set the replication timestamp; it's 0 if we're not in a replicated 161 * environment. Don't acquire a lock to read the value, even though 162 * it's opaque: all we check later is value equality, nothing else. 163 */ 164 dbp->timestamp = REP_ON(env) ? 165 ((REGENV *)env->reginfo->primary)->rep_timestamp : 0; 166 /* 167 * Set the replication generation number for fid management; valid 168 * replication generations start at 1. Don't acquire a lock to 169 * read the value. All we check later is value equality. 170 */ 171 db_rep = env->rep_handle; 172 dbp->fid_gen = REP_ON(env) ? ((REP *)db_rep->region)->gen : 0; 173 174 /* If not RPC, open a backing DB_MPOOLFILE handle in the memory pool. */ 175 if (!RPC_ON(dbenv) && (ret = __memp_fcreate(env, &dbp->mpf)) != 0) 176 goto err; 177 178 dbp->type = DB_UNKNOWN; 179 180 *dbpp = dbp; 181 return (0); 182 183err: if (dbp != NULL) { 184 if (dbp->mpf != NULL) 185 (void)__memp_fclose(dbp->mpf, 0); 186 __os_free(env, dbp); 187 } 188 189 if (F_ISSET(env, ENV_DBLOCAL)) 190 (void)__env_close(dbp->dbenv, 0); 191 192 return (ret); 193} 194 195/* 196 * __db_init -- 197 * Initialize a DB structure. 198 */ 199static int 200__db_init(dbp, flags) 201 DB *dbp; 202 u_int32_t flags; 203{ 204 int ret; 205 206 dbp->locker = NULL; 207 LOCK_INIT(dbp->handle_lock); 208 209 TAILQ_INIT(&dbp->free_queue); 210 TAILQ_INIT(&dbp->active_queue); 211 TAILQ_INIT(&dbp->join_queue); 212 LIST_INIT(&dbp->s_secondaries); 213 214 FLD_SET(dbp->am_ok, 215 DB_OK_BTREE | DB_OK_HASH | DB_OK_QUEUE | DB_OK_RECNO); 216 217 /* DB PUBLIC HANDLE LIST BEGIN */ 218 dbp->associate = __db_associate_pp; 219 dbp->associate_foreign = __db_associate_foreign_pp; 220 dbp->close = __db_close_pp; 221 dbp->compact = __db_compact_pp; 222 dbp->cursor = __db_cursor_pp; 223 dbp->del = __db_del_pp; 224 dbp->dump = __db_dump_pp; 225 dbp->err = __dbh_err; 226 dbp->errx = __dbh_errx; 227 dbp->exists = __db_exists; 228 dbp->fd = __db_fd_pp; 229 dbp->get = __db_get_pp; 230 dbp->get_byteswapped = __db_get_byteswapped; 231 dbp->get_cachesize = __db_get_cachesize; 232 dbp->get_dbname = __db_get_dbname; 233 dbp->get_encrypt_flags = __db_get_encrypt_flags; 234 dbp->get_env = __db_get_env; 235 dbp->get_errcall = __db_get_errcall; 236 dbp->get_errfile = __db_get_errfile; 237 dbp->get_errpfx = __db_get_errpfx; 238 dbp->get_flags = __db_get_flags; 239 dbp->get_lorder = __db_get_lorder; 240 dbp->get_mpf = __db_get_mpf; 241 dbp->get_msgfile = __db_get_msgfile; 242 dbp->get_multiple = __db_get_multiple; 243 dbp->get_open_flags = __db_get_open_flags; 244 dbp->get_pagesize = __db_get_pagesize; 245 dbp->get_priority = __db_get_priority; 246 dbp->get_transactional = __db_get_transactional; 247 dbp->get_type = __db_get_type; 248 dbp->join = __db_join_pp; 249 dbp->key_range = __db_key_range_pp; 250 dbp->open = __db_open_pp; 251 dbp->pget = __db_pget_pp; 252 dbp->put = __db_put_pp; 253 dbp->remove = __db_remove_pp; 254 dbp->rename = __db_rename_pp; 255 dbp->set_alloc = __db_set_alloc; 256 dbp->set_append_recno = __db_set_append_recno; 257 dbp->set_cachesize = __db_set_cachesize; 258 dbp->set_dup_compare = __db_set_dup_compare; 259 dbp->set_encrypt = __db_set_encrypt; 260 dbp->set_errcall = __db_set_errcall; 261 dbp->set_errfile = __db_set_errfile; 262 dbp->set_errpfx = __db_set_errpfx; 263 dbp->set_feedback = __db_set_feedback; 264 dbp->set_flags = __db_set_flags; 265 dbp->set_lorder = __db_set_lorder; 266 dbp->set_msgcall = __db_set_msgcall; 267 dbp->set_msgfile = __db_set_msgfile; 268 dbp->set_pagesize = __db_set_pagesize; 269 dbp->set_paniccall = __db_set_paniccall; 270 dbp->set_priority = __db_set_priority; 271 dbp->stat = __db_stat_pp; 272 dbp->stat_print = __db_stat_print_pp; 273 dbp->sync = __db_sync_pp; 274 dbp->truncate = __db_truncate_pp; 275 dbp->upgrade = __db_upgrade_pp; 276 dbp->verify = __db_verify_pp; 277 /* DB PUBLIC HANDLE LIST END */ 278 279 /* Access method specific. */ 280 if ((ret = __bam_db_create(dbp)) != 0) 281 return (ret); 282 if ((ret = __ham_db_create(dbp)) != 0) 283 return (ret); 284 if ((ret = __qam_db_create(dbp)) != 0) 285 return (ret); 286 287 /* 288 * XA specific: must be last, as we replace methods set by the 289 * access methods. 290 */ 291 if (LF_ISSET(DB_XA_CREATE) && (ret = __db_xa_create(dbp)) != 0) 292 return (ret); 293 294#ifdef HAVE_RPC 295 /* 296 * RPC specific: must be last, as we replace methods set by the 297 * access methods. 298 */ 299 if (RPC_ON(dbp->dbenv)) { 300 __dbcl_dbp_init(dbp); 301 /* 302 * !!! 303 * We wrap the DB->open method for RPC, and the rpc.src file 304 * can't handle that. 305 */ 306 dbp->open = __dbcl_db_open_wrap; 307 if ((ret = __dbcl_db_create(dbp, dbp->dbenv, flags)) != 0) 308 return (ret); 309 } 310#endif 311 312 return (0); 313} 314 315/* 316 * __dbh_am_chk -- 317 * Error if an unreasonable method is called. 318 * 319 * PUBLIC: int __dbh_am_chk __P((DB *, u_int32_t)); 320 */ 321int 322__dbh_am_chk(dbp, flags) 323 DB *dbp; 324 u_int32_t flags; 325{ 326 /* 327 * We start out allowing any access methods to be called, and as the 328 * application calls the methods the options become restricted. The 329 * idea is to quit as soon as an illegal method combination is called. 330 */ 331 if ((LF_ISSET(DB_OK_BTREE) && FLD_ISSET(dbp->am_ok, DB_OK_BTREE)) || 332 (LF_ISSET(DB_OK_HASH) && FLD_ISSET(dbp->am_ok, DB_OK_HASH)) || 333 (LF_ISSET(DB_OK_QUEUE) && FLD_ISSET(dbp->am_ok, DB_OK_QUEUE)) || 334 (LF_ISSET(DB_OK_RECNO) && FLD_ISSET(dbp->am_ok, DB_OK_RECNO))) { 335 FLD_CLR(dbp->am_ok, ~flags); 336 return (0); 337 } 338 339 __db_errx(dbp->env, 340 "call implies an access method which is inconsistent with previous calls"); 341 return (EINVAL); 342} 343 344/* 345 * __dbh_err -- 346 * Db.err method. 347 */ 348static void 349#ifdef STDC_HEADERS 350__dbh_err(DB *dbp, int error, const char *fmt, ...) 351#else 352__dbh_err(dbp, error, fmt, va_alist) 353 DB *dbp; 354 int error; 355 const char *fmt; 356 va_dcl 357#endif 358{ 359 /* Message with error string, to stderr by default. */ 360 DB_REAL_ERR(dbp->dbenv, error, DB_ERROR_SET, 1, fmt); 361} 362 363/* 364 * __dbh_errx -- 365 * Db.errx method. 366 */ 367static void 368#ifdef STDC_HEADERS 369__dbh_errx(DB *dbp, const char *fmt, ...) 370#else 371__dbh_errx(dbp, fmt, va_alist) 372 DB *dbp; 373 const char *fmt; 374 va_dcl 375#endif 376{ 377 /* Message without error string, to stderr by default. */ 378 DB_REAL_ERR(dbp->dbenv, 0, DB_ERROR_NOT_SET, 1, fmt); 379} 380 381/* 382 * __db_get_byteswapped -- 383 * Return if database requires byte swapping. 384 */ 385static int 386__db_get_byteswapped(dbp, isswapped) 387 DB *dbp; 388 int *isswapped; 389{ 390 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_byteswapped"); 391 392 *isswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0; 393 return (0); 394} 395 396/* 397 * __db_get_dbname -- 398 * Get the name of the database as passed to DB->open. 399 */ 400static int 401__db_get_dbname(dbp, fnamep, dnamep) 402 DB *dbp; 403 const char **fnamep, **dnamep; 404{ 405 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_dbname"); 406 407 if (fnamep != NULL) 408 *fnamep = dbp->fname; 409 if (dnamep != NULL) 410 *dnamep = dbp->dname; 411 return (0); 412} 413 414/* 415 * __db_get_env -- 416 * Get the DB_ENV handle that was passed to db_create. 417 */ 418static DB_ENV * 419__db_get_env(dbp) 420 DB *dbp; 421{ 422 return (dbp->dbenv); 423} 424 425/* 426 * __db_get_mpf -- 427 * Get the underlying DB_MPOOLFILE handle. 428 */ 429static DB_MPOOLFILE * 430__db_get_mpf(dbp) 431 DB *dbp; 432{ 433 return (dbp->mpf); 434} 435 436/* 437 * get_multiple -- 438 * Return whether this DB handle references a physical file with multiple 439 * databases. 440 */ 441static int 442__db_get_multiple(dbp) 443 DB *dbp; 444{ 445 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_multiple"); 446 447 /* 448 * Only return TRUE if the handle is for the master database, not for 449 * any subdatabase in the physical file. If it's a Btree, with the 450 * subdatabases flag set, and the meta-data page has the right value, 451 * return TRUE. (We don't need to check it's a Btree, I suppose, but 452 * it doesn't hurt.) 453 */ 454 return (dbp->type == DB_BTREE && 455 F_ISSET(dbp, DB_AM_SUBDB) && 456 dbp->meta_pgno == PGNO_BASE_MD ? 1 : 0); 457} 458 459/* 460 * get_transactional -- 461 * Return whether this database was created in a transaction. 462 */ 463static int 464__db_get_transactional(dbp) 465 DB *dbp; 466{ 467 return (F_ISSET(dbp, DB_AM_TXN) ? 1 : 0); 468} 469 470/* 471 * __db_get_type -- 472 * Return type of underlying database. 473 */ 474static int 475__db_get_type(dbp, dbtype) 476 DB *dbp; 477 DBTYPE *dbtype; 478{ 479 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_type"); 480 481 *dbtype = dbp->type; 482 return (0); 483} 484 485/* 486 * __db_set_append_recno -- 487 * Set record number append routine. 488 */ 489static int 490__db_set_append_recno(dbp, func) 491 DB *dbp; 492 int (*func) __P((DB *, DBT *, db_recno_t)); 493{ 494 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_append_recno"); 495 DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); 496 497 dbp->db_append_recno = func; 498 499 return (0); 500} 501 502/* 503 * __db_get_cachesize -- 504 * Get underlying cache size. 505 */ 506static int 507__db_get_cachesize(dbp, cache_gbytesp, cache_bytesp, ncachep) 508 DB *dbp; 509 u_int32_t *cache_gbytesp, *cache_bytesp; 510 int *ncachep; 511{ 512 DB_ILLEGAL_IN_ENV(dbp, "DB->get_cachesize"); 513 514 return (__memp_get_cachesize(dbp->dbenv, 515 cache_gbytesp, cache_bytesp, ncachep)); 516} 517 518/* 519 * __db_set_cachesize -- 520 * Set underlying cache size. 521 */ 522static int 523__db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache) 524 DB *dbp; 525 u_int32_t cache_gbytes, cache_bytes; 526 int ncache; 527{ 528 DB_ILLEGAL_IN_ENV(dbp, "DB->set_cachesize"); 529 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_cachesize"); 530 531 return (__memp_set_cachesize( 532 dbp->dbenv, cache_gbytes, cache_bytes, ncache)); 533} 534 535/* 536 * __db_set_dup_compare -- 537 * Set duplicate comparison routine. 538 */ 539static int 540__db_set_dup_compare(dbp, func) 541 DB *dbp; 542 int (*func) __P((DB *, const DBT *, const DBT *)); 543{ 544 int ret; 545 546 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->dup_compare"); 547 DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); 548 549 if ((ret = __db_set_flags(dbp, DB_DUPSORT)) != 0) 550 return (ret); 551 552 dbp->dup_compare = func; 553 554 return (0); 555} 556 557/* 558 * __db_get_encrypt_flags -- 559 */ 560static int 561__db_get_encrypt_flags(dbp, flagsp) 562 DB *dbp; 563 u_int32_t *flagsp; 564{ 565 DB_ILLEGAL_IN_ENV(dbp, "DB->get_encrypt_flags"); 566 567 return (__env_get_encrypt_flags(dbp->dbenv, flagsp)); 568} 569 570/* 571 * __db_set_encrypt -- 572 * Set database passwd. 573 */ 574static int 575__db_set_encrypt(dbp, passwd, flags) 576 DB *dbp; 577 const char *passwd; 578 u_int32_t flags; 579{ 580 DB_CIPHER *db_cipher; 581 int ret; 582 583 DB_ILLEGAL_IN_ENV(dbp, "DB->set_encrypt"); 584 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_encrypt"); 585 586 if ((ret = __env_set_encrypt(dbp->dbenv, passwd, flags)) != 0) 587 return (ret); 588 589 /* 590 * In a real env, this gets initialized with the region. In a local 591 * env, we must do it here. 592 */ 593 db_cipher = dbp->env->crypto_handle; 594 if (!F_ISSET(db_cipher, CIPHER_ANY) && 595 (ret = db_cipher->init(dbp->env, db_cipher)) != 0) 596 return (ret); 597 598 return (__db_set_flags(dbp, DB_ENCRYPT)); 599} 600 601static void 602__db_get_errcall(dbp, errcallp) 603 DB *dbp; 604 void (**errcallp) __P((const DB_ENV *, const char *, const char *)); 605{ 606 __env_get_errcall(dbp->dbenv, errcallp); 607} 608 609static void 610__db_set_errcall(dbp, errcall) 611 DB *dbp; 612 void (*errcall) __P((const DB_ENV *, const char *, const char *)); 613{ 614 __env_set_errcall(dbp->dbenv, errcall); 615} 616 617static void 618__db_get_errfile(dbp, errfilep) 619 DB *dbp; 620 FILE **errfilep; 621{ 622 __env_get_errfile(dbp->dbenv, errfilep); 623} 624 625static void 626__db_set_errfile(dbp, errfile) 627 DB *dbp; 628 FILE *errfile; 629{ 630 __env_set_errfile(dbp->dbenv, errfile); 631} 632 633static void 634__db_get_errpfx(dbp, errpfxp) 635 DB *dbp; 636 const char **errpfxp; 637{ 638 __env_get_errpfx(dbp->dbenv, errpfxp); 639} 640 641static void 642__db_set_errpfx(dbp, errpfx) 643 DB *dbp; 644 const char *errpfx; 645{ 646 __env_set_errpfx(dbp->dbenv, errpfx); 647} 648 649static int 650__db_set_feedback(dbp, feedback) 651 DB *dbp; 652 void (*feedback) __P((DB *, int, int)); 653{ 654 dbp->db_feedback = feedback; 655 return (0); 656} 657 658/* 659 * __db_map_flags -- 660 * Maps between public and internal flag values. 661 * This function doesn't check for validity, so it can't fail. 662 */ 663static void 664__db_map_flags(dbp, inflagsp, outflagsp) 665 DB *dbp; 666 u_int32_t *inflagsp, *outflagsp; 667{ 668 COMPQUIET(dbp, NULL); 669 670 if (FLD_ISSET(*inflagsp, DB_CHKSUM)) { 671 FLD_SET(*outflagsp, DB_AM_CHKSUM); 672 FLD_CLR(*inflagsp, DB_CHKSUM); 673 } 674 if (FLD_ISSET(*inflagsp, DB_ENCRYPT)) { 675 FLD_SET(*outflagsp, DB_AM_ENCRYPT | DB_AM_CHKSUM); 676 FLD_CLR(*inflagsp, DB_ENCRYPT); 677 } 678 if (FLD_ISSET(*inflagsp, DB_TXN_NOT_DURABLE)) { 679 FLD_SET(*outflagsp, DB_AM_NOT_DURABLE); 680 FLD_CLR(*inflagsp, DB_TXN_NOT_DURABLE); 681 } 682} 683 684/* 685 * __db_get_flags -- 686 * The DB->get_flags method. 687 * 688 * PUBLIC: int __db_get_flags __P((DB *, u_int32_t *)); 689 */ 690int 691__db_get_flags(dbp, flagsp) 692 DB *dbp; 693 u_int32_t *flagsp; 694{ 695 static const u_int32_t db_flags[] = { 696 DB_CHKSUM, 697 DB_DUP, 698 DB_DUPSORT, 699 DB_ENCRYPT, 700#ifdef HAVE_QUEUE 701 DB_INORDER, 702#endif 703 DB_RECNUM, 704 DB_RENUMBER, 705 DB_REVSPLITOFF, 706 DB_SNAPSHOT, 707 DB_TXN_NOT_DURABLE, 708 0 709 }; 710 u_int32_t f, flags, mapped_flag; 711 int i; 712 713 flags = 0; 714 for (i = 0; (f = db_flags[i]) != 0; i++) { 715 mapped_flag = 0; 716 __db_map_flags(dbp, &f, &mapped_flag); 717 __bam_map_flags(dbp, &f, &mapped_flag); 718 __ram_map_flags(dbp, &f, &mapped_flag); 719#ifdef HAVE_QUEUE 720 __qam_map_flags(dbp, &f, &mapped_flag); 721#endif 722 DB_ASSERT(dbp->env, f == 0); 723 if (F_ISSET(dbp, mapped_flag) == mapped_flag) 724 LF_SET(db_flags[i]); 725 } 726 727 *flagsp = flags; 728 return (0); 729} 730 731/* 732 * __db_set_flags -- 733 * DB->set_flags. 734 * 735 * PUBLIC: int __db_set_flags __P((DB *, u_int32_t)); 736 */ 737int 738__db_set_flags(dbp, flags) 739 DB *dbp; 740 u_int32_t flags; 741{ 742 ENV *env; 743 int ret; 744 745 env = dbp->env; 746 747 if (LF_ISSET(DB_ENCRYPT) && !CRYPTO_ON(env)) { 748 __db_errx(env, 749 "Database environment not configured for encryption"); 750 return (EINVAL); 751 } 752 if (LF_ISSET(DB_TXN_NOT_DURABLE)) 753 ENV_REQUIRES_CONFIG(env, 754 env->tx_handle, "DB_NOT_DURABLE", DB_INIT_TXN); 755 756 __db_map_flags(dbp, &flags, &dbp->flags); 757 758 if ((ret = __bam_set_flags(dbp, &flags)) != 0) 759 return (ret); 760 if ((ret = __ram_set_flags(dbp, &flags)) != 0) 761 return (ret); 762#ifdef HAVE_QUEUE 763 if ((ret = __qam_set_flags(dbp, &flags)) != 0) 764 return (ret); 765#endif 766 767 return (flags == 0 ? 0 : __db_ferr(env, "DB->set_flags", 0)); 768} 769 770/* 771 * __db_get_lorder -- 772 * Get whether lorder is swapped or not. 773 * 774 * PUBLIC: int __db_get_lorder __P((DB *, int *)); 775 */ 776int 777__db_get_lorder(dbp, db_lorderp) 778 DB *dbp; 779 int *db_lorderp; 780{ 781 int ret; 782 783 /* Flag if the specified byte order requires swapping. */ 784 switch (ret = __db_byteorder(dbp->env, 1234)) { 785 case 0: 786 *db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 4321 : 1234; 787 break; 788 case DB_SWAPBYTES: 789 *db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 1234 : 4321; 790 break; 791 default: 792 return (ret); 793 /* NOTREACHED */ 794 } 795 796 return (0); 797} 798 799/* 800 * __db_set_lorder -- 801 * Set whether lorder is swapped or not. 802 * 803 * PUBLIC: int __db_set_lorder __P((DB *, int)); 804 */ 805int 806__db_set_lorder(dbp, db_lorder) 807 DB *dbp; 808 int db_lorder; 809{ 810 int ret; 811 812 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_lorder"); 813 814 /* Flag if the specified byte order requires swapping. */ 815 switch (ret = __db_byteorder(dbp->env, db_lorder)) { 816 case 0: 817 F_CLR(dbp, DB_AM_SWAP); 818 break; 819 case DB_SWAPBYTES: 820 F_SET(dbp, DB_AM_SWAP); 821 break; 822 default: 823 return (ret); 824 /* NOTREACHED */ 825 } 826 return (0); 827} 828 829static int 830__db_set_alloc(dbp, mal_func, real_func, free_func) 831 DB *dbp; 832 void *(*mal_func) __P((size_t)); 833 void *(*real_func) __P((void *, size_t)); 834 void (*free_func) __P((void *)); 835{ 836 DB_ILLEGAL_IN_ENV(dbp, "DB->set_alloc"); 837 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_alloc"); 838 839 return (__env_set_alloc(dbp->dbenv, mal_func, real_func, free_func)); 840} 841 842static void 843__db_set_msgcall(dbp, msgcall) 844 DB *dbp; 845 void (*msgcall) __P((const DB_ENV *, const char *)); 846{ 847 __env_set_msgcall(dbp->dbenv, msgcall); 848} 849 850static void 851__db_get_msgfile(dbp, msgfilep) 852 DB *dbp; 853 FILE **msgfilep; 854{ 855 __env_get_msgfile(dbp->dbenv, msgfilep); 856} 857 858static void 859__db_set_msgfile(dbp, msgfile) 860 DB *dbp; 861 FILE *msgfile; 862{ 863 __env_set_msgfile(dbp->dbenv, msgfile); 864} 865 866static int 867__db_get_pagesize(dbp, db_pagesizep) 868 DB *dbp; 869 u_int32_t *db_pagesizep; 870{ 871 *db_pagesizep = dbp->pgsize; 872 return (0); 873} 874 875/* 876 * __db_set_pagesize -- 877 * DB->set_pagesize 878 * 879 * PUBLIC: int __db_set_pagesize __P((DB *, u_int32_t)); 880 */ 881int 882__db_set_pagesize(dbp, db_pagesize) 883 DB *dbp; 884 u_int32_t db_pagesize; 885{ 886 DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_pagesize"); 887 888 if (db_pagesize < DB_MIN_PGSIZE) { 889 __db_errx(dbp->env, "page sizes may not be smaller than %lu", 890 (u_long)DB_MIN_PGSIZE); 891 return (EINVAL); 892 } 893 if (db_pagesize > DB_MAX_PGSIZE) { 894 __db_errx(dbp->env, "page sizes may not be larger than %lu", 895 (u_long)DB_MAX_PGSIZE); 896 return (EINVAL); 897 } 898 899 /* 900 * We don't want anything that's not a power-of-2, as we rely on that 901 * for alignment of various types on the pages. 902 */ 903 if (!POWER_OF_TWO(db_pagesize)) { 904 __db_errx(dbp->env, "page sizes must be a power-of-2"); 905 return (EINVAL); 906 } 907 908 /* 909 * XXX 910 * Should we be checking for a page size that's not a multiple of 512, 911 * so that we never try and write less than a disk sector? 912 */ 913 dbp->pgsize = db_pagesize; 914 915 return (0); 916} 917 918static int 919__db_set_paniccall(dbp, paniccall) 920 DB *dbp; 921 void (*paniccall) __P((DB_ENV *, int)); 922{ 923 return (__env_set_paniccall(dbp->dbenv, paniccall)); 924} 925 926static int 927__db_set_priority(dbp, priority) 928 DB *dbp; 929 DB_CACHE_PRIORITY priority; 930{ 931 dbp->priority = priority; 932 return (0); 933} 934 935static int 936__db_get_priority(dbp, priority) 937 DB *dbp; 938 DB_CACHE_PRIORITY *priority; 939{ 940 *priority = dbp->priority; 941 return (0); 942} 943