1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: env_open.c,v 12.115 2008/03/25 16:00:28 ubell 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/lock.h" 16#include "dbinc/log.h" 17#include "dbinc/mp.h" 18#include "dbinc/txn.h" 19 20static int __env_refresh __P((DB_ENV *, u_int32_t, int)); 21static int __file_handle_cleanup __P((ENV *)); 22 23/* 24 * db_version -- 25 * Return version information. 26 * 27 * EXTERN: char *db_version __P((int *, int *, int *)); 28 */ 29char * 30db_version(majverp, minverp, patchp) 31 int *majverp, *minverp, *patchp; 32{ 33 if (majverp != NULL) 34 *majverp = DB_VERSION_MAJOR; 35 if (minverp != NULL) 36 *minverp = DB_VERSION_MINOR; 37 if (patchp != NULL) 38 *patchp = DB_VERSION_PATCH; 39 return ((char *)DB_VERSION_STRING); 40} 41 42/* 43 * __env_open_pp -- 44 * DB_ENV->open pre/post processing. 45 * 46 * PUBLIC: int __env_open_pp __P((DB_ENV *, const char *, u_int32_t, int)); 47 */ 48int 49__env_open_pp(dbenv, db_home, flags, mode) 50 DB_ENV *dbenv; 51 const char *db_home; 52 u_int32_t flags; 53 int mode; 54{ 55 ENV *env; 56 int ret; 57 58 env = dbenv->env; 59 60#undef OKFLAGS 61#define OKFLAGS \ 62 (DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG | \ 63 DB_INIT_MPOOL | DB_INIT_REP | DB_INIT_TXN | DB_LOCKDOWN | \ 64 DB_PRIVATE | DB_RECOVER | DB_RECOVER_FATAL | DB_REGISTER | \ 65 DB_SYSTEM_MEM | DB_THREAD | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) 66#undef OKFLAGS_CDB 67#define OKFLAGS_CDB \ 68 (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_LOCKDOWN | \ 69 DB_PRIVATE | DB_SYSTEM_MEM | DB_THREAD | \ 70 DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) 71 72 if ((ret = __db_fchk(env, "DB_ENV->open", flags, OKFLAGS)) != 0) 73 return (ret); 74 if ((ret = __db_fcchk( 75 env, "DB_ENV->open", flags, DB_INIT_CDB, ~OKFLAGS_CDB)) != 0) 76 return (ret); 77 if (LF_ISSET(DB_REGISTER)) { 78 if (!__os_support_db_register()) { 79 __db_errx(env, 80 "Berkeley DB library does not support DB_REGISTER on this system"); 81 return (EINVAL); 82 } 83 if ((ret = __db_fcchk(env, "DB_ENV->open", flags, 84 DB_PRIVATE, DB_REGISTER | DB_SYSTEM_MEM)) != 0) 85 return (ret); 86 if (!LF_ISSET(DB_INIT_TXN)) { 87 __db_errx( 88 env, "registration requires transaction support"); 89 return (EINVAL); 90 } 91 } 92 if (LF_ISSET(DB_INIT_REP)) { 93 if (!__os_support_replication()) { 94 __db_errx(env, 95 "Berkeley DB library does not support replication on this system"); 96 return (EINVAL); 97 } 98 if (!LF_ISSET(DB_INIT_LOCK)) { 99 __db_errx(env, 100 "replication requires locking support"); 101 return (EINVAL); 102 } 103 if (!LF_ISSET(DB_INIT_TXN)) { 104 __db_errx( 105 env, "replication requires transaction support"); 106 return (EINVAL); 107 } 108 } 109 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) { 110 if ((ret = __db_fcchk(env, 111 "DB_ENV->open", flags, DB_RECOVER, DB_RECOVER_FATAL)) != 0) 112 return (ret); 113 if ((ret = __db_fcchk(env, 114 "DB_ENV->open", flags, DB_REGISTER, DB_RECOVER_FATAL)) != 0) 115 return (ret); 116 if (!LF_ISSET(DB_CREATE)) { 117 __db_errx(env, "recovery requires the create flag"); 118 return (EINVAL); 119 } 120 if (!LF_ISSET(DB_INIT_TXN)) { 121 __db_errx( 122 env, "recovery requires transaction support"); 123 return (EINVAL); 124 } 125 } 126 127#ifdef HAVE_MUTEX_THREAD_ONLY 128 /* 129 * Currently we support one kind of mutex that is intra-process only, 130 * POSIX 1003.1 pthreads, because a variety of systems don't support 131 * the full pthreads API, and our only alternative is test-and-set. 132 */ 133 if (!LF_ISSET(DB_PRIVATE)) { 134 __db_errx(env, 135 "Berkeley DB library configured to support only private environments"); 136 return (EINVAL); 137 } 138#endif 139 140#ifdef HAVE_MUTEX_FCNTL 141 /* 142 * !!! 143 * We need a file descriptor for fcntl(2) locking. We use the file 144 * handle from the REGENV file for this purpose. 145 * 146 * Since we may be using shared memory regions, e.g., shmget(2), and 147 * not a mapped-in regular file, the backing file may be only a few 148 * bytes in length. So, this depends on the ability to call fcntl to 149 * lock file offsets much larger than the actual physical file. I 150 * think that's safe -- besides, very few systems actually need this 151 * kind of support, SunOS is the only one still in wide use of which 152 * I'm aware. 153 * 154 * The error case is if an application lacks spinlocks and wants to be 155 * threaded. That doesn't work because fcntl will lock the underlying 156 * process, including all its threads. 157 */ 158 if (F_ISSET(env, ENV_THREAD)) { 159 __db_errx(env, 160 "architecture lacks fast mutexes: applications cannot be threaded"); 161 return (EINVAL); 162 } 163#endif 164 165 return (__env_open(dbenv, db_home, flags, mode)); 166} 167 168/* 169 * __env_open -- 170 * DB_ENV->open. 171 * 172 * PUBLIC: int __env_open __P((DB_ENV *, const char *, u_int32_t, int)); 173 */ 174int 175__env_open(dbenv, db_home, flags, mode) 176 DB_ENV *dbenv; 177 const char *db_home; 178 u_int32_t flags; 179 int mode; 180{ 181 DB_THREAD_INFO *ip; 182 ENV *env; 183 REGINFO *infop; 184 u_int32_t init_flags, orig_flags; 185 int create_ok, register_recovery, rep_check, ret, t_ret; 186 187 ip = NULL; 188 env = dbenv->env; 189 register_recovery = rep_check = 0; 190 191 /* Initial configuration. */ 192 if ((ret = __env_config(dbenv, db_home, flags, mode)) != 0) 193 return (ret); 194 195 /* 196 * Save the DB_ENV handle's configuration flags as set by user-called 197 * configuration methods and the environment directory's DB_CONFIG 198 * file. If we use this DB_ENV structure to recover the existing 199 * environment or to remove an environment we created after failure, 200 * we'll restore the DB_ENV flags to these values. 201 */ 202 orig_flags = dbenv->flags; 203 204 /* 205 * If we're going to register with the environment, that's the first 206 * thing we do. 207 */ 208 if (LF_ISSET(DB_REGISTER)) { 209 if ((ret = __envreg_register(env, ®ister_recovery)) != 0) 210 goto err; 211 if (register_recovery) { 212 if (!LF_ISSET(DB_RECOVER)) { 213 __db_errx(env, 214 "The DB_RECOVER flag was not specified, and recovery is needed"); 215 ret = DB_RUNRECOVERY; 216 goto err; 217 } 218 } else 219 LF_CLR(DB_RECOVER); 220 } 221 222 /* 223 * If we're doing recovery, destroy the environment so that we create 224 * all the regions from scratch. The major concern I have is if the 225 * application stomps the environment with a rogue pointer. We have 226 * no way of detecting that, and we could be forced into a situation 227 * where we start up and then crash, repeatedly. 228 * 229 * We do not check any flags like DB_PRIVATE before calling remove. 230 * We don't care if the current environment was private or not, we 231 * want to remove files left over for any reason, from any session. 232 */ 233 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) 234#ifdef HAVE_REPLICATION 235 if ((ret = __rep_reset_init(env)) != 0 || 236 (ret = __env_remove_env(env)) != 0 || 237#else 238 if ((ret = __env_remove_env(env)) != 0 || 239#endif 240 (ret = __env_refresh(dbenv, orig_flags, 0)) != 0) 241 goto err; 242 243 /* Convert the DB_ENV->open flags to internal flags. */ 244 create_ok = LF_ISSET(DB_CREATE) ? 1 : 0; 245 if (LF_ISSET(DB_LOCKDOWN)) 246 F_SET(env, ENV_LOCKDOWN); 247 if (LF_ISSET(DB_PRIVATE)) 248 F_SET(env, ENV_PRIVATE); 249 if (LF_ISSET(DB_RECOVER_FATAL)) 250 F_SET(env, ENV_RECOVER_FATAL); 251 if (LF_ISSET(DB_SYSTEM_MEM)) 252 F_SET(env, ENV_SYSTEM_MEM); 253 if (LF_ISSET(DB_THREAD)) 254 F_SET(env, ENV_THREAD); 255 256 /* 257 * Flags saved in the init_flags field of the environment, representing 258 * flags to DB_ENV->set_flags and DB_ENV->open that need to be set. 259 */ 260#define DB_INITENV_CDB 0x0001 /* DB_INIT_CDB */ 261#define DB_INITENV_CDB_ALLDB 0x0002 /* DB_INIT_CDB_ALLDB */ 262#define DB_INITENV_LOCK 0x0004 /* DB_INIT_LOCK */ 263#define DB_INITENV_LOG 0x0008 /* DB_INIT_LOG */ 264#define DB_INITENV_MPOOL 0x0010 /* DB_INIT_MPOOL */ 265#define DB_INITENV_REP 0x0020 /* DB_INIT_REP */ 266#define DB_INITENV_TXN 0x0040 /* DB_INIT_TXN */ 267 268 /* 269 * Create/join the environment. We pass in the flags of interest to 270 * a thread subsequently joining an environment we create. If we're 271 * not the ones to create the environment, our flags will be updated 272 * to match the existing environment. 273 */ 274 init_flags = 0; 275 if (LF_ISSET(DB_INIT_CDB)) 276 FLD_SET(init_flags, DB_INITENV_CDB); 277 if (F_ISSET(dbenv, DB_ENV_CDB_ALLDB)) 278 FLD_SET(init_flags, DB_INITENV_CDB_ALLDB); 279 if (LF_ISSET(DB_INIT_LOCK)) 280 FLD_SET(init_flags, DB_INITENV_LOCK); 281 if (LF_ISSET(DB_INIT_LOG)) 282 FLD_SET(init_flags, DB_INITENV_LOG); 283 if (LF_ISSET(DB_INIT_MPOOL)) 284 FLD_SET(init_flags, DB_INITENV_MPOOL); 285 if (LF_ISSET(DB_INIT_REP)) 286 FLD_SET(init_flags, DB_INITENV_REP); 287 if (LF_ISSET(DB_INIT_TXN)) 288 FLD_SET(init_flags, DB_INITENV_TXN); 289 if ((ret = __env_attach(env, &init_flags, create_ok, 1)) != 0) 290 goto err; 291 292 /* 293 * __env_attach will return the saved init_flags field, which contains 294 * the DB_INIT_* flags used when the environment was created. 295 * 296 * We may be joining an environment -- reset our flags to match the 297 * ones in the environment. 298 */ 299 if (FLD_ISSET(init_flags, DB_INITENV_CDB)) 300 LF_SET(DB_INIT_CDB); 301 if (FLD_ISSET(init_flags, DB_INITENV_LOCK)) 302 LF_SET(DB_INIT_LOCK); 303 if (FLD_ISSET(init_flags, DB_INITENV_LOG)) 304 LF_SET(DB_INIT_LOG); 305 if (FLD_ISSET(init_flags, DB_INITENV_MPOOL)) 306 LF_SET(DB_INIT_MPOOL); 307 if (FLD_ISSET(init_flags, DB_INITENV_REP)) 308 LF_SET(DB_INIT_REP); 309 if (FLD_ISSET(init_flags, DB_INITENV_TXN)) 310 LF_SET(DB_INIT_TXN); 311 if (FLD_ISSET(init_flags, DB_INITENV_CDB_ALLDB) && 312 (ret = __env_set_flags(dbenv, DB_CDB_ALLDB, 1)) != 0) 313 goto err; 314 315 /* Initialize for CDB product. */ 316 if (LF_ISSET(DB_INIT_CDB)) { 317 LF_SET(DB_INIT_LOCK); 318 F_SET(env, ENV_CDB); 319 } 320 321 /* 322 * Update the flags to match the database environment. The application 323 * may have specified flags of 0 to join the environment, and this line 324 * replaces that value with the flags corresponding to the existing, 325 * underlying set of subsystems. This means the DbEnv.get_open_flags 326 * method returns the flags to open the existing environment instead of 327 * the specific flags passed to the DbEnv.open method. 328 */ 329 env->open_flags = flags; 330 331 /* 332 * The DB_ENV structure has now been initialized. Turn off further 333 * use of the DB_ENV structure and most initialization methods, we're 334 * about to act on the values we currently have. 335 */ 336 F_SET(env, ENV_OPEN_CALLED); 337 338 /* 339 * Initialize thread tracking and enter the API. 340 */ 341 infop = env->reginfo; 342 if ((ret = 343 __env_thread_init(env, F_ISSET(infop, REGION_CREATE) ? 1 : 0)) != 0) 344 goto err; 345 346 ENV_ENTER(env, ip); 347 348 /* 349 * Initialize the subsystems. 350 */ 351#ifdef HAVE_MUTEX_SUPPORT 352 /* 353 * Initialize the mutex regions first. There's no ordering requirement, 354 * but it's simpler to get this in place so we don't have to keep track 355 * of mutexes for later allocation, once the mutex region is created we 356 * can go ahead and do the allocation for real. 357 */ 358 if ((ret = __mutex_open(env, create_ok)) != 0) 359 goto err; 360#endif 361 /* 362 * We can now acquire/create mutexes: increment the region's reference 363 * count. 364 */ 365 if ((ret = __env_ref_increment(env)) != 0) 366 goto err; 367 368 /* 369 * Initialize the handle mutexes. 370 */ 371 if ((ret = __mutex_alloc(env, 372 MTX_ENV_HANDLE, DB_MUTEX_PROCESS_ONLY, &dbenv->mtx_db_env)) != 0 || 373 (ret = __mutex_alloc(env, 374 MTX_ENV_HANDLE, DB_MUTEX_PROCESS_ONLY, &env->mtx_env)) != 0) 375 goto err; 376 377 /* 378 * Initialize the replication area next, so that we can lock out this 379 * call if we're currently running recovery for replication. 380 */ 381 if (LF_ISSET(DB_INIT_REP) && (ret = __rep_open(env)) != 0) 382 goto err; 383 384 rep_check = IS_ENV_REPLICATED(env) ? 1 : 0; 385 if (rep_check && (ret = __env_rep_enter(env, 0)) != 0) 386 goto err; 387 388 if (LF_ISSET(DB_INIT_MPOOL)) { 389 if ((ret = __memp_open(env, create_ok)) != 0) 390 goto err; 391 392 /* 393 * BDB does do cache I/O during recovery and when starting up 394 * replication. If creating a new environment, then suppress 395 * any application max-write configuration. 396 */ 397 if (create_ok) 398 (void)__memp_set_config( 399 dbenv, DB_MEMP_SUPPRESS_WRITE, 1); 400 401 /* 402 * Initialize the DB list and its mutex. If the mpool is 403 * not initialized, we can't ever open a DB handle, which 404 * is why this code lives here. 405 */ 406 TAILQ_INIT(&env->dblist); 407 if ((ret = __mutex_alloc(env, MTX_ENV_DBLIST, 408 DB_MUTEX_PROCESS_ONLY, &env->mtx_dblist)) != 0) 409 goto err; 410 411 /* Register DB's pgin/pgout functions. */ 412 if ((ret = __memp_register( 413 env, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0) 414 goto err; 415 } 416 417 /* 418 * Initialize the ciphering area prior to any running of recovery so 419 * that we can initialize the keys, etc. before recovery, including 420 * the MT mutex. 421 * 422 * !!! 423 * This must be after the mpool init, but before the log initialization 424 * because log_open may attempt to run log_recover during its open. 425 */ 426 if (LF_ISSET(DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_TXN) && 427 (ret = __crypto_region_init(env)) != 0) 428 goto err; 429 if ((ret = __mutex_alloc( 430 env, MTX_TWISTER, DB_MUTEX_PROCESS_ONLY, &env->mtx_mt)) != 0) 431 goto err; 432 433 /* 434 * Transactions imply logging but do not imply locking. While almost 435 * all applications want both locking and logging, it would not be 436 * unreasonable for a single threaded process to want transactions for 437 * atomicity guarantees, but not necessarily need concurrency. 438 */ 439 if (LF_ISSET(DB_INIT_LOG | DB_INIT_TXN)) 440 if ((ret = __log_open(env, create_ok)) != 0) 441 goto err; 442 if (LF_ISSET(DB_INIT_LOCK)) 443 if ((ret = __lock_open(env, create_ok)) != 0) 444 goto err; 445 446 if (LF_ISSET(DB_INIT_TXN)) { 447 if ((ret = __txn_open(env, create_ok)) != 0) 448 goto err; 449 450 /* 451 * If the application is running with transactions, initialize 452 * the function tables. 453 */ 454 if ((ret = __env_init_rec(env, DB_LOGVERSION)) != 0) 455 goto err; 456 } 457 458 /* Perform recovery for any previous run. */ 459 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && 460 (ret = __db_apprec(env, ip, NULL, NULL, 1, 461 LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0) 462 goto err; 463 464 /* 465 * If we've created the regions, are running with transactions, and did 466 * not just run recovery, we need to log the fact that the transaction 467 * IDs got reset. 468 * 469 * If we ran recovery, there may be prepared-but-not-yet-committed 470 * transactions that need to be resolved. Recovery resets the minimum 471 * transaction ID and logs the reset if that's appropriate, so we 472 * don't need to do anything here in the recover case. 473 */ 474 if (TXN_ON(env) && 475 !FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) && 476 F_ISSET(infop, REGION_CREATE) && 477 !LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && 478 (ret = __txn_reset(env)) != 0) 479 goto err; 480 481 /* The database environment is ready for business. */ 482 if ((ret = __env_turn_on(env)) != 0) 483 goto err; 484 485 if (rep_check) 486 ret = __env_db_rep_exit(env); 487 488 /* Turn any application-specific max-write configuration back on. */ 489 if (LF_ISSET(DB_INIT_MPOOL)) 490 (void)__memp_set_config(dbenv, DB_MEMP_SUPPRESS_WRITE, 0); 491 492err: if (ret == 0) 493 ENV_LEAVE(env, ip); 494 else { 495 /* 496 * If we fail after creating the regions, panic and remove them. 497 * 498 * !!! 499 * No need to call __env_db_rep_exit, that work is done by the 500 * calls to __env_refresh. 501 */ 502 infop = env->reginfo; 503 if (infop != NULL && F_ISSET(infop, REGION_CREATE)) { 504 ret = __env_panic(env, ret); 505 506 /* Refresh the DB_ENV so can use it to call remove. */ 507 (void)__env_refresh(dbenv, orig_flags, rep_check); 508 (void)__env_remove_env(env); 509 (void)__env_refresh(dbenv, orig_flags, 0); 510 } else 511 (void)__env_refresh(dbenv, orig_flags, rep_check); 512 } 513 514 if (register_recovery) { 515 /* 516 * If recovery succeeded, release our exclusive lock, other 517 * processes can now proceed. 518 * 519 * If recovery failed, unregister now and let another process 520 * clean up. 521 */ 522 if (ret == 0 && (t_ret = __envreg_xunlock(env)) != 0) 523 ret = t_ret; 524 if (ret != 0) 525 (void)__envreg_unregister(env, 1); 526 } 527 528 return (ret); 529} 530 531/* 532 * __env_remove -- 533 * DB_ENV->remove. 534 * 535 * PUBLIC: int __env_remove __P((DB_ENV *, const char *, u_int32_t)); 536 */ 537int 538__env_remove(dbenv, db_home, flags) 539 DB_ENV *dbenv; 540 const char *db_home; 541 u_int32_t flags; 542{ 543 ENV *env; 544 int ret, t_ret; 545 546 env = dbenv->env; 547 548#undef OKFLAGS 549#define OKFLAGS \ 550 (DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) 551 552 /* Validate arguments. */ 553 if ((ret = __db_fchk(env, "DB_ENV->remove", flags, OKFLAGS)) != 0) 554 return (ret); 555 556 ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->remove"); 557 558 if ((ret = __env_config(dbenv, db_home, flags, 0)) != 0) 559 return (ret); 560 561 /* 562 * Turn the environment off -- if the environment is corrupted, this 563 * could fail. Ignore any error if we're forcing the question. 564 */ 565 if ((ret = __env_turn_off(env, flags)) == 0 || LF_ISSET(DB_FORCE)) 566 ret = __env_remove_env(env); 567 568 if ((t_ret = __env_close(dbenv, 0)) != 0 && ret == 0) 569 ret = t_ret; 570 571 return (ret); 572} 573 574/* 575 * __env_config -- 576 * Argument-based initialization. 577 * 578 * PUBLIC: int __env_config __P((DB_ENV *, const char *, u_int32_t, int)); 579 */ 580int 581__env_config(dbenv, db_home, flags, mode) 582 DB_ENV *dbenv; 583 const char *db_home; 584 u_int32_t flags; 585 int mode; 586{ 587 ENV *env; 588 int ret; 589 char *home, home_buf[DB_MAXPATHLEN]; 590 591 env = dbenv->env; 592 593 /* 594 * Set the database home. 595 * 596 * Use db_home by default, this allows utilities to reasonably 597 * override the environment either explicitly or by using a -h 598 * option. Otherwise, use the environment if it's permitted 599 * and initialized. 600 */ 601 home = (char *)db_home; 602 if (home == NULL && (LF_ISSET(DB_USE_ENVIRON) || 603 (LF_ISSET(DB_USE_ENVIRON_ROOT) && __os_isroot()))) { 604 home = home_buf; 605 if ((ret = __os_getenv( 606 env, "DB_HOME", &home, sizeof(home_buf))) != 0) 607 return (ret); 608 /* 609 * home set to NULL if __os_getenv failed to find DB_HOME. 610 */ 611 } 612 if (home != NULL && (ret = __os_strdup(env, home, &env->db_home)) != 0) 613 return (ret); 614 615 /* Save a copy of the DB_ENV->open method flags. */ 616 env->open_flags = flags; 617 618 /* Default permissions are read-write for both owner and group. */ 619 env->db_mode = mode == 0 ? DB_MODE_660 : mode; 620 621 /* Read the DB_CONFIG file. */ 622 if ((ret = __env_read_db_config(env)) != 0) 623 return (ret); 624 625 /* 626 * If no temporary directory path was specified in the config file, 627 * choose one. 628 */ 629 if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(env, flags)) != 0) 630 return (ret); 631 632 return (0); 633} 634 635/* 636 * __env_close_pp -- 637 * DB_ENV->close pre/post processor. 638 * 639 * PUBLIC: int __env_close_pp __P((DB_ENV *, u_int32_t)); 640 */ 641int 642__env_close_pp(dbenv, flags) 643 DB_ENV *dbenv; 644 u_int32_t flags; 645{ 646 DB_THREAD_INFO *ip; 647 ENV *env; 648 int rep_check, ret, t_ret; 649 650 env = dbenv->env; 651 ret = 0; 652 653 /* 654 * Validate arguments, but as a DB_ENV handle destructor, we can't 655 * fail. 656 */ 657 if (flags != 0 && 658 (t_ret = __db_ferr(env, "DB_ENV->close", 0)) != 0 && ret == 0) 659 ret = t_ret; 660 661 /* 662 * If the environment has panic'd, all we do is try and discard 663 * the important resources. 664 */ 665 if (PANIC_ISSET(env)) { 666 /* Close all underlying file handles. */ 667 (void)__file_handle_cleanup(env); 668 669 /* Close all underlying threads and sockets. */ 670 if (IS_ENV_REPLICATED(env)) 671 (void)__repmgr_close(env); 672 673 PANIC_CHECK(env); 674 } 675 676 ENV_ENTER(env, ip); 677 678 rep_check = IS_ENV_REPLICATED(env) ? 1 : 0; 679 if (rep_check) { 680#ifdef HAVE_REPLICATION_THREADS 681 /* 682 * Shut down Replication Manager threads first of all. This 683 * must be done before __env_rep_enter to avoid a deadlock that 684 * could occur if repmgr's background threads try to do a rep 685 * operation that needs __rep_lockout. 686 */ 687 if ((t_ret = __repmgr_close(env)) != 0 && ret == 0) 688 ret = t_ret; 689#endif 690 if ((t_ret = __env_rep_enter(env, 0)) != 0 && ret == 0) 691 ret = t_ret; 692 } 693 694 if ((t_ret = __env_close(dbenv, rep_check)) != 0 && ret == 0) 695 ret = t_ret; 696 697 /* Don't ENV_LEAVE as we have already detached from the region. */ 698 return (ret); 699} 700 701/* 702 * __env_close -- 703 * DB_ENV->close. 704 * 705 * PUBLIC: int __env_close __P((DB_ENV *, int)); 706 */ 707int 708__env_close(dbenv, rep_check) 709 DB_ENV *dbenv; 710 int rep_check; 711{ 712 ENV *env; 713 int ret, t_ret; 714 char **p; 715 716 env = dbenv->env; 717 ret = 0; 718 719 /* 720 * Check to see if we were in the middle of restoring transactions and 721 * need to close the open files. 722 */ 723 if (TXN_ON(env) && (t_ret = __txn_preclose(env)) != 0 && ret == 0) 724 ret = t_ret; 725 726#ifdef HAVE_REPLICATION 727 if ((t_ret = __rep_env_close(env)) != 0 && ret == 0) 728 ret = t_ret; 729#endif 730 731 /* 732 * Detach from the regions and undo the allocations done by 733 * DB_ENV->open. 734 */ 735 if ((t_ret = __env_refresh(dbenv, 0, rep_check)) != 0 && ret == 0) 736 ret = t_ret; 737 738#ifdef HAVE_CRYPTO 739 /* 740 * Crypto comes last, because higher level close functions need 741 * cryptography. 742 */ 743 if ((t_ret = __crypto_env_close(env)) != 0 && ret == 0) 744 ret = t_ret; 745#endif 746 747 /* If we're registered, clean up. */ 748 if (dbenv->registry != NULL) { 749 (void)__envreg_unregister(env, 0); 750 dbenv->registry = NULL; 751 } 752 753 /* Check we've closed all underlying file handles. */ 754 if ((t_ret = __file_handle_cleanup(env)) != 0 && ret == 0) 755 ret = t_ret; 756 757 /* Release any string-based configuration parameters we've copied. */ 758 if (dbenv->db_log_dir != NULL) 759 __os_free(env, dbenv->db_log_dir); 760 dbenv->db_log_dir = NULL; 761 if (dbenv->db_tmp_dir != NULL) 762 __os_free(env, dbenv->db_tmp_dir); 763 dbenv->db_tmp_dir = NULL; 764 if (dbenv->db_data_dir != NULL) { 765 for (p = dbenv->db_data_dir; *p != NULL; ++p) 766 __os_free(env, *p); 767 __os_free(env, dbenv->db_data_dir); 768 dbenv->db_data_dir = NULL; 769 dbenv->data_next = 0; 770 } 771 if (dbenv->intermediate_dir_mode != NULL) 772 __os_free(env, dbenv->intermediate_dir_mode); 773 if (env->db_home != NULL) { 774 __os_free(env, env->db_home); 775 env->db_home = NULL; 776 } 777 778 /* Discard the structure. */ 779 __db_env_destroy(dbenv); 780 781 return (ret); 782} 783 784/* 785 * __env_refresh -- 786 * Refresh the DB_ENV structure. 787 */ 788static int 789__env_refresh(dbenv, orig_flags, rep_check) 790 DB_ENV *dbenv; 791 u_int32_t orig_flags; 792 int rep_check; 793{ 794 DB *ldbp; 795 DB_THREAD_INFO *ip; 796 ENV *env; 797 int ret, t_ret; 798 799 env = dbenv->env; 800 ret = 0; 801 802 /* 803 * Release resources allocated by DB_ENV->open, and return it to the 804 * state it was in just before __env_open was called. (This means 805 * state set by pre-open configuration functions must be preserved.) 806 * 807 * Refresh subsystems, in the reverse order they were opened (txn 808 * must be first, it may want to discard locks and flush the log). 809 * 810 * !!! 811 * Note that these functions, like all of __env_refresh, only undo 812 * the effects of __env_open. Functions that undo work done by 813 * db_env_create or by a configuration function should go in 814 * __env_close. 815 */ 816 if (TXN_ON(env) && 817 (t_ret = __txn_env_refresh(env)) != 0 && ret == 0) 818 ret = t_ret; 819 820 if (LOGGING_ON(env) && 821 (t_ret = __log_env_refresh(env)) != 0 && ret == 0) 822 ret = t_ret; 823 824 /* 825 * Locking should come after logging, because closing log results 826 * in files closing which may require locks being released. 827 */ 828 if (LOCKING_ON(env)) { 829 if (!F_ISSET(env, ENV_THREAD) && 830 env->env_lref != NULL && (t_ret = 831 __lock_id_free(env, env->env_lref)) != 0 && ret == 0) 832 ret = t_ret; 833 env->env_lref = NULL; 834 835 if ((t_ret = __lock_env_refresh(env)) != 0 && ret == 0) 836 ret = t_ret; 837 } 838 839 /* Discard the DB_ENV, ENV handle mutexes. */ 840 if ((t_ret = __mutex_free(env, &dbenv->mtx_db_env)) != 0 && ret == 0) 841 ret = t_ret; 842 if ((t_ret = __mutex_free(env, &env->mtx_env)) != 0 && ret == 0) 843 ret = t_ret; 844 845 /* 846 * Discard DB list and its mutex. 847 * Discard the MT mutex. 848 * 849 * !!! 850 * This must be done after we close the log region, because we close 851 * database handles and so acquire this mutex when we close log file 852 * handles. 853 */ 854 if (env->db_ref != 0) { 855 __db_errx(env, 856 "Database handles still open at environment close"); 857 TAILQ_FOREACH(ldbp, &env->dblist, dblistlinks) 858 __db_errx(env, "Open database handle: %s%s%s", 859 ldbp->fname == NULL ? "unnamed" : ldbp->fname, 860 ldbp->dname == NULL ? "" : "/", 861 ldbp->dname == NULL ? "" : ldbp->dname); 862 if (ret == 0) 863 ret = EINVAL; 864 } 865 TAILQ_INIT(&env->dblist); 866 if ((t_ret = __mutex_free(env, &env->mtx_dblist)) != 0 && ret == 0) 867 ret = t_ret; 868 if ((t_ret = __mutex_free(env, &env->mtx_mt)) != 0 && ret == 0) 869 ret = t_ret; 870 871 if (env->mt != NULL) { 872 __os_free(env, env->mt); 873 env->mt = NULL; 874 } 875 876 if (MPOOL_ON(env)) { 877 /* 878 * If it's a private environment, flush the contents to disk. 879 * Recovery would have put everything back together, but it's 880 * faster and cleaner to flush instead. 881 * 882 * Ignore application max-write configuration, we're shutting 883 * down. 884 */ 885 if (F_ISSET(env, ENV_PRIVATE) && 886 (t_ret = __memp_sync_int(env, NULL, 0, 887 DB_SYNC_CACHE | DB_SYNC_SUPPRESS_WRITE, NULL, NULL)) != 0 && 888 ret == 0) 889 ret = t_ret; 890 891 if ((t_ret = __memp_env_refresh(env)) != 0 && ret == 0) 892 ret = t_ret; 893 } 894 895 /* 896 * If we're included in a shared replication handle count, this 897 * is our last chance to decrement that count. 898 * 899 * !!! 900 * We can't afford to do anything dangerous after we decrement the 901 * handle count, of course, as replication may be proceeding with 902 * client recovery. However, since we're discarding the regions 903 * as soon as we drop the handle count, there's little opportunity 904 * to do harm. 905 */ 906 if (rep_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) 907 ret = t_ret; 908 909 /* 910 * Refresh the replication region. 911 * 912 * Must come after we call __env_db_rep_exit above. 913 */ 914 if (REP_ON(env) && (t_ret = __rep_env_refresh(env)) != 0 && ret == 0) 915 ret = t_ret; 916 917#ifdef HAVE_CRYPTO 918 /* 919 * Crypto comes last, because higher level close functions need 920 * cryptography. 921 */ 922 if (env->reginfo != NULL && 923 (t_ret = __crypto_env_refresh(env)) != 0 && ret == 0) 924 ret = t_ret; 925#endif 926 927 /* 928 * Mark the thread as out of the env before we get rid of the handles 929 * needed to do so. 930 */ 931 if (env->thr_hashtab != NULL && 932 (t_ret = __env_set_state(env, &ip, THREAD_OUT)) != 0 && ret == 0) 933 ret = t_ret; 934 935 /* 936 * We are about to detach from the mutex region. This is the last 937 * chance we have to acquire/destroy a mutex -- acquire/destroy the 938 * mutex and release our reference. 939 * 940 * !!! 941 * There are two DbEnv methods that care about environment reference 942 * counts: DbEnv.close and DbEnv.remove. The DbEnv.close method is 943 * not a problem because it only decrements the reference count and 944 * no actual resources are discarded -- lots of threads of control 945 * can call DbEnv.close at the same time, and regardless of racing 946 * on the reference count mutex, we wouldn't have a problem. Since 947 * the DbEnv.remove method actually discards resources, we can have 948 * a problem. 949 * 950 * If we decrement the reference count to 0 here, go to sleep, and 951 * the DbEnv.remove method is called, by the time we run again, the 952 * underlying shared regions could have been removed. That's fine, 953 * except we might actually need the regions to resolve outstanding 954 * operations in the various subsystems, and if we don't have hard 955 * OS references to the regions, we could get screwed. Of course, 956 * we should have hard OS references to everything we need, but just 957 * in case, we put off decrementing the reference count as long as 958 * possible. 959 */ 960 if ((t_ret = __env_ref_decrement(env)) != 0 && ret == 0) 961 ret = t_ret; 962 963#ifdef HAVE_MUTEX_SUPPORT 964 if (MUTEX_ON(env) && 965 (t_ret = __mutex_env_refresh(env)) != 0 && ret == 0) 966 ret = t_ret; 967#endif 968 /* Free memory for thread tracking. */ 969 if (env->reginfo != NULL) { 970 if (F_ISSET(env, ENV_PRIVATE)) { 971 __env_thread_destroy(env); 972 t_ret = __env_detach(env, 1); 973 } else 974 t_ret = __env_detach(env, 0); 975 976 if (t_ret != 0 && ret == 0) 977 ret = t_ret; 978 979 /* 980 * !!! 981 * Don't free env->reginfo or set the reference to NULL, 982 * that was done by __env_detach(). 983 */ 984 } 985 986 if (env->mutex_iq != NULL) { 987 __os_free(env, env->mutex_iq); 988 env->mutex_iq = NULL; 989 } 990 991 if (env->recover_dtab.int_dispatch != NULL) { 992 __os_free(env, env->recover_dtab.int_dispatch); 993 env->recover_dtab.int_size = 0; 994 env->recover_dtab.int_dispatch = NULL; 995 } 996 if (env->recover_dtab.ext_dispatch != NULL) { 997 __os_free(env, env->recover_dtab.ext_dispatch); 998 env->recover_dtab.ext_size = 0; 999 env->recover_dtab.ext_dispatch = NULL; 1000 } 1001 1002 dbenv->flags = orig_flags; 1003 1004 return (ret); 1005} 1006 1007/* 1008 * __file_handle_cleanup -- 1009 * Close any underlying open file handles so we don't leak system 1010 * resources. 1011 */ 1012static int 1013__file_handle_cleanup(env) 1014 ENV *env; 1015{ 1016 DB_FH *fhp; 1017 1018 if (TAILQ_FIRST(&env->fdlist) == NULL) 1019 return (0); 1020 1021 __db_errx(env, "File handles still open at environment close"); 1022 while ((fhp = TAILQ_FIRST(&env->fdlist)) != NULL) { 1023 __db_errx(env, "Open file handle: %s", fhp->name); 1024 (void)__os_closehandle(env, fhp); 1025 } 1026 return (EINVAL); 1027} 1028 1029/* 1030 * __env_get_open_flags 1031 * DbEnv.get_open_flags method. 1032 * 1033 * PUBLIC: int __env_get_open_flags __P((DB_ENV *, u_int32_t *)); 1034 */ 1035int 1036__env_get_open_flags(dbenv, flagsp) 1037 DB_ENV *dbenv; 1038 u_int32_t *flagsp; 1039{ 1040 ENV *env; 1041 1042 env = dbenv->env; 1043 1044 ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->get_open_flags"); 1045 1046 *flagsp = env->open_flags; 1047 return (0); 1048} 1049