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, &register_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