1/* DO NOT EDIT: automatically built by dist/s_vxworks. */
2/*-
3 * See the file LICENSE for redistribution information.
4 *
5 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
6 *
7 * $Id: db_int.in,v 12.76 2008/05/07 12:34:15 bschmeck Exp $
8 */
9
10#ifndef _DB_INT_H_
11#define	_DB_INT_H_
12
13/*******************************************************
14 * Berkeley DB ANSI/POSIX include files.
15 *******************************************************/
16#include "vxWorks.h"
17#ifdef HAVE_SYSTEM_INCLUDE_FILES
18#include <sys/types.h>
19#ifdef DIAG_MVCC
20#include <sys/mman.h>
21#endif
22#include <sys/stat.h>
23
24#if defined(__INCLUDE_SELECT_H)
25#ifdef HAVE_SYS_SELECT_H
26#include <sys/select.h>
27#endif
28#ifdef HAVE_VXWORKS
29#include <selectLib.h>
30#endif
31#endif
32
33#if TIME_WITH_SYS_TIME
34#include <sys/time.h>
35#include <time.h>
36#else
37#if HAVE_SYS_TIME_H
38#include <sys/time.h>
39#else
40#include <time.h>
41#endif
42#endif
43
44#ifdef HAVE_VXWORKS
45#include <net/uio.h>
46#else
47#include <sys/uio.h>
48#endif
49
50#if defined(__INCLUDE_NETWORKING)
51#ifdef HAVE_SYS_SOCKET_H
52#include <sys/socket.h>
53#endif
54#include <netinet/in.h>
55#include <netdb.h>
56#include <arpa/inet.h>
57#endif
58
59#if defined(STDC_HEADERS) || defined(__cplusplus)
60#include <stdarg.h>
61#else
62#include <varargs.h>
63#endif
64
65#include <ctype.h>
66#include <errno.h>
67#include <fcntl.h>
68#include <limits.h>
69#include <signal.h>
70#include <stddef.h>
71#include <stdio.h>
72#include <stdlib.h>
73#include <string.h>
74#include <unistd.h>
75
76#if defined(__INCLUDE_DIRECTORY)
77#if HAVE_DIRENT_H
78# include <dirent.h>
79# define NAMLEN(dirent) strlen((dirent)->d_name)
80#else
81# define dirent direct
82# define NAMLEN(dirent) (dirent)->d_namlen
83# if HAVE_SYS_NDIR_H
84#  include <sys/ndir.h>
85# endif
86# if HAVE_SYS_DIR_H
87#  include <sys/dir.h>
88# endif
89# if HAVE_NDIR_H
90#  include <ndir.h>
91# endif
92#endif
93#endif /* __INCLUDE_DIRECTORY */
94
95#endif /* !HAVE_SYSTEM_INCLUDE_FILES */
96#include "clib_port.h"
97#include "db.h"
98
99#ifdef DB_WIN32
100#include "dbinc/win_db.h"
101#endif
102
103#include "db.h"
104#include "clib_port.h"
105
106#include "dbinc/queue.h"
107#include "dbinc/shqueue.h"
108
109#if defined(__cplusplus)
110extern "C" {
111#endif
112
113/*******************************************************
114 * Forward structure declarations.
115 *******************************************************/
116struct __db_reginfo_t;	typedef struct __db_reginfo_t REGINFO;
117struct __db_txnhead;	typedef struct __db_txnhead DB_TXNHEAD;
118struct __db_txnlist;	typedef struct __db_txnlist DB_TXNLIST;
119struct __vrfy_childinfo;typedef struct __vrfy_childinfo VRFY_CHILDINFO;
120struct __vrfy_dbinfo;   typedef struct __vrfy_dbinfo VRFY_DBINFO;
121struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO;
122
123typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB;
124
125/*******************************************************
126 * General purpose constants and macros.
127 *******************************************************/
128#undef	FALSE
129#define	FALSE		0
130#undef	TRUE
131#define	TRUE		(!FALSE)
132
133#define	MEGABYTE	1048576
134#define	GIGABYTE	1073741824
135
136#define	NS_PER_MS	1000000		/* Nanoseconds in a millisecond */
137#define	NS_PER_US	1000		/* Nanoseconds in a microsecond */
138#define	NS_PER_SEC	1000000000	/* Nanoseconds in a second */
139#define	US_PER_MS	1000		/* Microseconds in a millisecond */
140#define	US_PER_SEC	1000000		/* Microseconds in a second */
141#define	MS_PER_SEC	1000		/* Milliseconds in a second */
142
143#define	RECNO_OOB	0		/* Illegal record number. */
144
145/* Test for a power-of-two (tests true for zero, which doesn't matter here). */
146#define	POWER_OF_TWO(x)	(((x) & ((x) - 1)) == 0)
147
148/* Test for valid page sizes. */
149#define	DB_MIN_PGSIZE	0x000200	/* Minimum page size (512). */
150#define	DB_MAX_PGSIZE	0x010000	/* Maximum page size (65536). */
151#define	IS_VALID_PAGESIZE(x)						\
152	(POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE))
153
154/* Minimum number of pages cached, by default. */
155#define	DB_MINPAGECACHE	16
156
157/*
158 * If we are unable to determine the underlying filesystem block size, use
159 * 8K on the grounds that most OS's use less than 8K for a VM page size.
160 */
161#define	DB_DEF_IOSIZE	(8 * 1024)
162
163/* Align an integer to a specific boundary. */
164#undef	DB_ALIGN
165#define	DB_ALIGN(v, bound)						\
166	(((v) + (bound) - 1) & ~(((uintmax_t)(bound)) - 1))
167
168/* Increment a pointer to a specific boundary. */
169#undef	ALIGNP_INC
170#define	ALIGNP_INC(p, bound)						\
171	(void *)(((uintptr_t)(p) + (bound) - 1) & ~(((uintptr_t)(bound)) - 1))
172
173/*
174 * Print an address as a u_long (a u_long is the largest type we can print
175 * portably).  Most 64-bit systems have made longs 64-bits, so this should
176 * work.
177 */
178#define	P_TO_ULONG(p)	((u_long)(uintptr_t)(p))
179
180/*
181 * Convert a pointer to a small integral value.
182 *
183 * The (u_int16_t)(uintptr_t) cast avoids warnings: the (uintptr_t) cast
184 * converts the value to an integral type, and the (u_int16_t) cast converts
185 * it to a small integral type so we don't get complaints when we assign the
186 * final result to an integral type smaller than uintptr_t.
187 */
188#define	P_TO_UINT32(p)	((u_int32_t)(uintptr_t)(p))
189#define	P_TO_UINT16(p)	((u_int16_t)(uintptr_t)(p))
190
191/*
192 * There are several on-page structures that are declared to have a number of
193 * fields followed by a variable length array of items.  The structure size
194 * without including the variable length array or the address of the first of
195 * those elements can be found using SSZ.
196 *
197 * This macro can also be used to find the offset of a structure element in a
198 * structure.  This is used in various places to copy structure elements from
199 * unaligned memory references, e.g., pointers into a packed page.
200 *
201 * There are two versions because compilers object if you take the address of
202 * an array.
203 */
204#undef	SSZ
205#define	SSZ(name, field)  P_TO_UINT16(&(((name *)0)->field))
206
207#undef	SSZA
208#define	SSZA(name, field) P_TO_UINT16(&(((name *)0)->field[0]))
209
210/* Structure used to print flag values. */
211typedef struct __fn {
212	u_int32_t mask;			/* Flag value. */
213	const char *name;		/* Flag name. */
214} FN;
215
216/* Set, clear and test flags. */
217#define	FLD_CLR(fld, f)		(fld) &= ~(f)
218#define	FLD_ISSET(fld, f)	((fld) & (f))
219#define	FLD_SET(fld, f)		(fld) |= (f)
220#define	F_CLR(p, f)		(p)->flags &= ~(f)
221#define	F_ISSET(p, f)		((p)->flags & (f))
222#define	F_SET(p, f)		(p)->flags |= (f)
223#define	LF_CLR(f)		((flags) &= ~(f))
224#define	LF_ISSET(f)		((flags) & (f))
225#define	LF_SET(f)		((flags) |= (f))
226
227/*
228 * Calculate a percentage.  The values can overflow 32-bit integer arithmetic
229 * so we use floating point.
230 *
231 * When calculating a bytes-vs-page size percentage, we're getting the inverse
232 * of the percentage in all cases, that is, we want 100 minus the percentage we
233 * calculate.
234 */
235#define	DB_PCT(v, total)						\
236	((int)((total) == 0 ? 0 : ((double)(v) * 100) / (total)))
237#define	DB_PCT_PG(v, total, pgsize)					\
238	((int)((total) == 0 ? 0 :					\
239	    100 - ((double)(v) * 100) / (((double)total) * (pgsize))))
240
241/*
242 * Statistics update shared memory and so are expensive -- don't update the
243 * values unless we're going to display the results.
244 */
245#undef	STAT
246#ifdef	HAVE_STATISTICS
247#define	STAT(x)	x
248#else
249#define	STAT(x)
250#endif
251
252/*
253 * Structure used for callback message aggregation.
254 *
255 * Display values in XXX_stat_print calls.
256 */
257typedef struct __db_msgbuf {
258	char *buf;			/* Heap allocated buffer. */
259	char *cur;			/* Current end of message. */
260	size_t len;			/* Allocated length of buffer. */
261} DB_MSGBUF;
262#define	DB_MSGBUF_INIT(a) do {						\
263	(a)->buf = (a)->cur = NULL;					\
264	(a)->len = 0;							\
265} while (0)
266#define	DB_MSGBUF_FLUSH(env, a) do {					\
267	if ((a)->buf != NULL) {						\
268		if ((a)->cur != (a)->buf)				\
269			__db_msg(env, "%s", (a)->buf);		\
270		__os_free(env, (a)->buf);				\
271		DB_MSGBUF_INIT(a);					\
272	}								\
273} while (0)
274#define	STAT_FMT(msg, fmt, type, v) do {				\
275	DB_MSGBUF __mb;							\
276	DB_MSGBUF_INIT(&__mb);						\
277	__db_msgadd(env, &__mb, fmt, (type)(v));			\
278	__db_msgadd(env, &__mb, "\t%s", msg);				\
279	DB_MSGBUF_FLUSH(env, &__mb);					\
280} while (0)
281#define	STAT_HEX(msg, v)						\
282	__db_msg(env, "%#lx\t%s", (u_long)(v), msg)
283#define	STAT_ISSET(msg, p)						\
284	__db_msg(env, "%sSet\t%s", (p) == NULL ? "!" : " ", msg)
285#define	STAT_LONG(msg, v)						\
286	__db_msg(env, "%ld\t%s", (long)(v), msg)
287#define	STAT_LSN(msg, lsnp)						\
288	__db_msg(env, "%lu/%lu\t%s",					\
289	    (u_long)(lsnp)->file, (u_long)(lsnp)->offset, msg)
290#define	STAT_POINTER(msg, v)						\
291	__db_msg(env, "%#lx\t%s", P_TO_ULONG(v), msg)
292#define	STAT_STRING(msg, p) do {					\
293	const char *__p = p;	/* p may be a function call. */		\
294	__db_msg(env, "%s\t%s", __p == NULL ? "!Set" : __p, msg);	\
295} while (0)
296#define	STAT_ULONG(msg, v)						\
297	__db_msg(env, "%lu\t%s", (u_long)(v), msg)
298
299/*
300 * There are quite a few places in Berkeley DB where we want to initialize
301 * a DBT from a string or other random pointer type, using a length typed
302 * to size_t in most cases.  This macro avoids a lot of casting.  The macro
303 * comes in two flavors because we often want to clear the DBT first.
304 */
305#define	DB_SET_DBT(dbt, d, s)  do {					\
306	(dbt).data = (void *)(d);					\
307	(dbt).size = (u_int32_t)(s);					\
308} while (0)
309#define	DB_INIT_DBT(dbt, d, s)  do {					\
310	memset(&(dbt), 0, sizeof(dbt));					\
311	DB_SET_DBT(dbt, d, s);						\
312} while (0)
313
314/*******************************************************
315 * API return values
316 *******************************************************/
317/*
318 * Return values that are OK for each different call.  Most calls have a
319 * standard 'return of 0 is only OK value', but some, like db->get have
320 * DB_NOTFOUND as a return value, but it really isn't an error.
321 */
322#define	DB_RETOK_STD(ret)	((ret) == 0)
323#define	DB_RETOK_DBCDEL(ret)	((ret) == 0 || (ret) == DB_KEYEMPTY || \
324				    (ret) == DB_NOTFOUND)
325#define	DB_RETOK_DBCGET(ret)	((ret) == 0 || (ret) == DB_KEYEMPTY || \
326				    (ret) == DB_NOTFOUND)
327#define	DB_RETOK_DBCPUT(ret)	((ret) == 0 || (ret) == DB_KEYEXIST || \
328				    (ret) == DB_NOTFOUND)
329#define	DB_RETOK_DBDEL(ret)	DB_RETOK_DBCDEL(ret)
330#define	DB_RETOK_DBGET(ret)	DB_RETOK_DBCGET(ret)
331#define	DB_RETOK_DBPUT(ret)	((ret) == 0 || (ret) == DB_KEYEXIST)
332#define	DB_RETOK_EXISTS(ret)	DB_RETOK_DBCGET(ret)
333#define	DB_RETOK_LGGET(ret)	((ret) == 0 || (ret) == DB_NOTFOUND)
334#define	DB_RETOK_MPGET(ret)	((ret) == 0 || (ret) == DB_PAGE_NOTFOUND)
335#define	DB_RETOK_REPPMSG(ret)	((ret) == 0 || \
336				    (ret) == DB_REP_IGNORE || \
337				    (ret) == DB_REP_ISPERM || \
338				    (ret) == DB_REP_NEWMASTER || \
339				    (ret) == DB_REP_NEWSITE || \
340				    (ret) == DB_REP_NOTPERM)
341
342/* Find a reasonable operation-not-supported error. */
343#ifdef	EOPNOTSUPP
344#define	DB_OPNOTSUP	EOPNOTSUPP
345#else
346#ifdef	ENOTSUP
347#define	DB_OPNOTSUP	ENOTSUP
348#else
349#define	DB_OPNOTSUP	EINVAL
350#endif
351#endif
352
353/*******************************************************
354 * Files.
355 *******************************************************/
356/*
357 * We use 1024 as the maximum path length.  It's too hard to figure out what
358 * the real path length is, as it was traditionally stored in <sys/param.h>,
359 * and that file isn't always available.
360 */
361#define	DB_MAXPATHLEN	1024
362
363#define	PATH_DOT	"."	/* Current working directory. */
364				/* Path separator character(s). */
365#define	PATH_SEPARATOR	"/\\"
366
367/*******************************************************
368 * Environment.
369 *******************************************************/
370/* Type passed to __db_appname(). */
371typedef enum {
372	DB_APP_NONE=0,			/* No type (region). */
373	DB_APP_DATA,			/* Data file. */
374	DB_APP_LOG,			/* Log file. */
375	DB_APP_TMP			/* Temporary file. */
376} APPNAME;
377
378/*
379 * A set of macros to check if various functionality has been configured.
380 *
381 * ALIVE_ON	The is_alive function is configured.
382 * CDB_LOCKING	CDB product locking.
383 * CRYPTO_ON	Security has been configured.
384 * LOCKING_ON	Locking has been configured.
385 * LOGGING_ON	Logging has been configured.
386 * MUTEX_ON	Mutexes have been configured.
387 * MPOOL_ON	Memory pool has been configured.
388 * REP_ON	Replication has been configured.
389 * RPC_ON	RPC has been configured.
390 * TXN_ON	Transactions have been configured.
391 *
392 * REP_ON is more complex than most: if the BDB library was compiled without
393 * replication support, ENV->rep_handle will be NULL; if the BDB library has
394 * replication support, but it was not configured, the region reference will
395 * be NULL.
396 */
397#define	ALIVE_ON(env)		((env)->dbenv->is_alive != NULL)
398#define	CDB_LOCKING(env)	F_ISSET(env, ENV_CDB)
399#define	CRYPTO_ON(env)		((env)->crypto_handle != NULL)
400#define	LOCKING_ON(env)		((env)->lk_handle != NULL)
401#define	LOGGING_ON(env)		((env)->lg_handle != NULL)
402#define	MPOOL_ON(env)		((env)->mp_handle != NULL)
403#define	MUTEX_ON(env)		((env)->mutex_handle != NULL)
404#define	REP_ON(env)							\
405	((env)->rep_handle != NULL && (env)->rep_handle->region != NULL)
406#define	RPC_ON(dbenv)		((dbenv)->cl_handle != NULL)
407#define	TXN_ON(env)		((env)->tx_handle != NULL)
408
409/*
410 * STD_LOCKING	Standard locking, that is, locking was configured and CDB
411 *		was not.  We do not do locking in off-page duplicate trees,
412 *		so we check for that in the cursor first.
413 */
414#define	STD_LOCKING(dbc)						\
415	(!F_ISSET(dbc, DBC_OPD) &&					\
416	    !CDB_LOCKING((dbc)->env) && LOCKING_ON((dbc)->env))
417
418/*
419 * IS_RECOVERING: The system is running recovery.
420 */
421#define	IS_RECOVERING(env)						\
422	(LOGGING_ON(env) && F_ISSET((env)->lg_handle, DBLOG_RECOVER))
423
424/* Initialization methods are often illegal before/after open is called. */
425#define	ENV_ILLEGAL_AFTER_OPEN(env, name)				\
426	if (F_ISSET((env), ENV_OPEN_CALLED))				\
427		return (__db_mi_open(env, name, 1));
428#define	ENV_ILLEGAL_BEFORE_OPEN(env, name)				\
429	if (!F_ISSET((env), ENV_OPEN_CALLED))				\
430		return (__db_mi_open(env, name, 0));
431
432/* We're not actually user hostile, honest. */
433#define	ENV_REQUIRES_CONFIG(env, handle, i, flags)			\
434	if (handle == NULL)						\
435		return (__env_not_config(env, i, flags));
436#define	ENV_REQUIRES_CONFIG_XX(env, handle, i, flags)			\
437	if ((env)->handle->region == NULL)				\
438		return (__env_not_config(env, i, flags));
439#define	ENV_NOT_CONFIGURED(env, handle, i, flags)			\
440	if (F_ISSET((env), ENV_OPEN_CALLED))				\
441		ENV_REQUIRES_CONFIG(env, handle, i, flags)
442
443#define	ENV_ENTER(env, ip) do {						\
444	int __ret;							\
445	PANIC_CHECK(env);						\
446	if ((env)->thr_hashtab == NULL)					\
447		ip = NULL;						\
448	else {								\
449		if ((__ret =						\
450		    __env_set_state(env, &(ip), THREAD_ACTIVE)) != 0)	\
451			return (__ret);					\
452	}								\
453} while (0)
454
455#define ENV_GET_THREAD_INFO(env, ip) ENV_ENTER(env, ip)
456
457#ifdef DIAGNOSTIC
458#define	ENV_LEAVE(env, ip) do {						\
459	if ((ip) != NULL) {						\
460		DB_ASSERT(env, (ip)->dbth_state == THREAD_ACTIVE);	\
461		(ip)->dbth_state = THREAD_OUT;				\
462	}								\
463} while (0)
464#else
465#define	ENV_LEAVE(env, ip) do {						\
466	if ((ip) != NULL)						\
467		(ip)->dbth_state = THREAD_OUT;				\
468} while (0)
469#endif
470#ifdef DIAGNOSTIC
471#define	CHECK_THREAD(env) do {						\
472	if ((env)->thr_hashtab != NULL)					\
473		(void)__env_set_state(env, NULL, THREAD_VERIFY);	\
474} while (0)
475#ifdef HAVE_STATISTICS
476#define	CHECK_MTX_THREAD(env, mtx) do {					\
477	if (mtx->alloc_id != MTX_MUTEX_REGION &&			\
478	    mtx->alloc_id != MTX_ENV_REGION &&				\
479	    mtx->alloc_id != MTX_APPLICATION)				\
480		CHECK_THREAD(env);					\
481} while (0)
482#else
483#define	CHECK_MTX_THREAD(env, mtx)
484#endif
485#else
486#define	CHECK_THREAD(env)
487#define	CHECK_MTX_THREAD(env, mtx)
488#endif
489
490typedef enum {
491	THREAD_SLOT_NOT_IN_USE=0,
492	THREAD_OUT,
493	THREAD_ACTIVE,
494	THREAD_BLOCKED,
495	THREAD_BLOCKED_DEAD
496#ifdef DIAGNOSTIC
497	, THREAD_VERIFY
498#endif
499} DB_THREAD_STATE;
500
501typedef struct __pin_list {
502	roff_t b_ref;		/* offset to buffer. */
503	int region;		/* region containing buffer. */
504} PIN_LIST;
505#define PINMAX 4
506
507struct __db_thread_info {
508	pid_t		dbth_pid;
509	db_threadid_t	dbth_tid;
510	DB_THREAD_STATE	dbth_state;
511	SH_TAILQ_ENTRY	dbth_links;
512	/*
513	 * The following fields track which buffers this thread of
514	 * control has pinned in the mpool buffer cache.
515	 */
516	u_int16_t	dbth_pincount;	/* Number of pins for this thread. */
517	u_int16_t	dbth_pinmax;	/* Number of slots allocated. */
518	roff_t		dbth_pinlist;	/* List of pins. */
519	PIN_LIST	dbth_pinarray[PINMAX];	/* Initial array of slots. */
520};
521
522typedef struct __env_thread_info {
523	u_int32_t	thr_count;
524	u_int32_t	thr_max;
525	u_int32_t	thr_nbucket;
526	roff_t		thr_hashoff;
527} THREAD_INFO;
528
529#define	DB_EVENT(env, e, einfo) do {					\
530	DB_ENV *__dbenv = (env)->dbenv;					\
531	if (__dbenv->db_event_func != NULL)				\
532		__dbenv->db_event_func(__dbenv, e, einfo);		\
533} while (0)
534
535typedef struct __flag_map {
536	u_int32_t inflag, outflag;
537} FLAG_MAP;
538
539/*
540 * Internal database environment structure.
541 *
542 * This is the private database environment handle.  The public environment
543 * handle is the DB_ENV structure.   The library owns this structure, the user
544 * owns the DB_ENV structure.  The reason there are two structures is because
545 * the user's configuration outlives any particular DB_ENV->open call, and
546 * separate structures allows us to easily discard internal information without
547 * discarding the user's configuration.
548 */
549struct __env {
550	DB_ENV *dbenv;			/* Linked DB_ENV structure */
551
552	/*
553	 * The ENV structure can be used concurrently, so field access is
554	 * protected.
555	 */
556	db_mutex_t mtx_env;		/* ENV structure mutex */
557
558	/*
559	 * Some fields are included in the ENV structure rather than in the
560	 * DB_ENV structure because they are only set as arguments to the
561	 * DB_ENV->open method.  In other words, because of the historic API,
562	 * not for any rational reason.
563	 *
564	 * Arguments to DB_ENV->open.
565	 */
566	char	 *db_home;		/* Database home */
567	u_int32_t open_flags;		/* Flags */
568	int	  db_mode;		/* Default open permissions */
569
570	pid_t	pid_cache;		/* Cached process ID */
571
572	DB_FH	*lockfhp;		/* fcntl(2) locking file handle */
573
574	DB_LOCKER *env_lref;		/* Locker in non-threaded handles */
575
576	DB_DISTAB   recover_dtab;	/* Dispatch table for recover funcs */
577
578	int dir_mode;			/* Intermediate directory perms. */
579
580	/* Thread tracking */
581	u_int32_t	 thr_nbucket;	/* Number of hash buckets */
582	DB_HASHTAB	*thr_hashtab;	/* Hash table of DB_THREAD_INFO */
583
584	/* Mutex allocation */
585	struct {
586		int	  alloc_id;	/* Allocation ID argument */
587		u_int32_t flags;	/* Flags argument */
588	} *mutex_iq;			/* Initial mutexes queue */
589	u_int		mutex_iq_next;	/* Count of initial mutexes */
590	u_int		mutex_iq_max;	/* Maximum initial mutexes */
591
592	/*
593	 * List of open DB handles for this ENV, used for cursor
594	 * adjustment.  Must be protected for multi-threaded support.
595	 */
596	db_mutex_t mtx_dblist;
597	int	   db_ref;		/* DB handle reference count */
598	TAILQ_HEAD(__dblist, __db) dblist;
599
600	/*
601	 * XA support.
602	 */
603	int		 xa_rmid;		/* XA Resource Manager ID */
604	TAILQ_ENTRY(__env) links;		/* XA environments */
605	TAILQ_HEAD(__xa_txn, __db_txn) xa_txn;	/* XA active transactions */
606
607	/*
608	 * List of open file handles for this ENV.  Must be protected
609	 * for multi-threaded support.
610	 */
611	TAILQ_HEAD(__fdlist, __fh_t) fdlist;
612
613	db_mutex_t	 mtx_mt;	/* Mersenne Twister mutex */
614	int		 mti;		/* Mersenne Twister index */
615	u_long		*mt;		/* Mersenne Twister state vector */
616
617	DB_CIPHER	*crypto_handle;	/* Crypto handle */
618	DB_LOCKTAB	*lk_handle;	/* Lock handle */
619	DB_LOG		*lg_handle;	/* Log handle */
620	DB_MPOOL	*mp_handle;	/* Mpool handle */
621	DB_MUTEXMGR	*mutex_handle;	/* Mutex handle */
622	DB_REP		*rep_handle;	/* Replication handle */
623	DB_TXNMGR	*tx_handle;	/* Txn handle */
624
625	/* Application callback to copy data to/from a custom data source */
626#define	DB_USERCOPY_GETDATA	0x0001
627#define	DB_USERCOPY_SETDATA	0x0002
628	int (*dbt_usercopy)
629	    __P((DBT *, u_int32_t, void *, u_int32_t, u_int32_t));
630
631	REGINFO	*reginfo;		/* REGINFO structure reference */
632
633#define	DB_TEST_ELECTINIT	 1	/* after __rep_elect_init */
634#define	DB_TEST_ELECTVOTE1	 2	/* after sending VOTE1 */
635#define	DB_TEST_POSTDESTROY	 3	/* after destroy op */
636#define	DB_TEST_POSTLOG		 4	/* after logging all pages */
637#define	DB_TEST_POSTLOGMETA	 5	/* after logging meta in btree */
638#define	DB_TEST_POSTOPEN	 6	/* after __os_open */
639#define	DB_TEST_POSTSYNC	 7	/* after syncing the log */
640#define	DB_TEST_PREDESTROY	 8	/* before destroy op */
641#define	DB_TEST_PREOPEN		 9	/* before __os_open */
642#define	DB_TEST_SUBDB_LOCKS	 10	/* subdb locking tests */
643	int	test_abort;		/* Abort value for testing */
644	int	test_check;		/* Checkpoint value for testing */
645	int	test_copy;		/* Copy value for testing */
646
647#define	ENV_CDB			0x00000001 /* DB_INIT_CDB */
648#define	ENV_DBLOCAL		0x00000002 /* Environment for a private DB */
649#define	ENV_LITTLEENDIAN	0x00000004 /* Little endian system. */
650#define	ENV_LOCKDOWN		0x00000008 /* DB_LOCKDOWN set */
651#define	ENV_NO_OUTPUT_SET	0x00000010 /* No output channel set */
652#define	ENV_OPEN_CALLED		0x00000020 /* DB_ENV->open called */
653#define	ENV_PRIVATE		0x00000040 /* DB_PRIVATE set */
654#define	ENV_RECOVER_FATAL	0x00000080 /* Doing fatal recovery in env */
655#define	ENV_REF_COUNTED		0x00000100 /* Region references this handle */
656#define	ENV_SYSTEM_MEM		0x00000200 /* DB_SYSTEM_MEM set */
657#define	ENV_THREAD		0x00000400 /* DB_THREAD set */
658	u_int32_t flags;
659};
660
661/*******************************************************
662 * Database Access Methods.
663 *******************************************************/
664/*
665 * DB_IS_THREADED --
666 *	The database handle is free-threaded (was opened with DB_THREAD).
667 */
668#define	DB_IS_THREADED(dbp)						\
669	((dbp)->mutex != MUTEX_INVALID)
670
671/* Initialization methods are often illegal before/after open is called. */
672#define	DB_ILLEGAL_AFTER_OPEN(dbp, name)				\
673	if (F_ISSET((dbp), DB_AM_OPEN_CALLED))				\
674		return (__db_mi_open((dbp)->env, name, 1));
675#define	DB_ILLEGAL_BEFORE_OPEN(dbp, name)				\
676	if (!F_ISSET((dbp), DB_AM_OPEN_CALLED))				\
677		return (__db_mi_open((dbp)->env, name, 0));
678/* Some initialization methods are illegal if environment isn't local. */
679#define	DB_ILLEGAL_IN_ENV(dbp, name)					\
680	if (!F_ISSET((dbp)->env, ENV_DBLOCAL))				\
681		return (__db_mi_env((dbp)->env, name));
682#define	DB_ILLEGAL_METHOD(dbp, flags) {					\
683	int __ret;							\
684	if ((__ret = __dbh_am_chk(dbp, flags)) != 0)			\
685		return (__ret);						\
686}
687
688/*
689 * Common DBC->internal fields.  Each access method adds additional fields
690 * to this list, but the initial fields are common.
691 */
692#define	__DBC_INTERNAL							\
693	DBC	 *opd;			/* Off-page duplicate cursor. */\
694									\
695	void	 *page;			/* Referenced page. */		\
696	db_pgno_t root;			/* Tree root. */		\
697	db_pgno_t pgno;			/* Referenced page number. */	\
698	db_indx_t indx;			/* Referenced key item index. */\
699									\
700	DB_LOCK		lock;		/* Cursor lock. */		\
701	db_lockmode_t	lock_mode;	/* Lock mode. */
702
703struct __dbc_internal {
704	__DBC_INTERNAL
705};
706
707/* Actions that __db_master_update can take. */
708typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN } mu_action;
709
710/*
711 * Access-method-common macro for determining whether a cursor
712 * has been initialized.
713 */
714#define	IS_INITIALIZED(dbc)	((dbc)->internal->pgno != PGNO_INVALID)
715
716/* Free the callback-allocated buffer, if necessary, hanging off of a DBT. */
717#define	FREE_IF_NEEDED(env, dbt)					\
718	if (F_ISSET((dbt), DB_DBT_APPMALLOC)) {				\
719		__os_ufree((env), (dbt)->data);				\
720		F_CLR((dbt), DB_DBT_APPMALLOC);				\
721	}
722
723/*
724 * Use memory belonging to object "owner" to return the results of
725 * any no-DBT-flag get ops on cursor "dbc".
726 */
727#define	SET_RET_MEM(dbc, owner)				\
728	do {						\
729		(dbc)->rskey = &(owner)->my_rskey;	\
730		(dbc)->rkey = &(owner)->my_rkey;	\
731		(dbc)->rdata = &(owner)->my_rdata;	\
732	} while (0)
733
734/* Use the return-data memory src is currently set to use in dest as well. */
735#define	COPY_RET_MEM(src, dest)				\
736	do {						\
737		(dest)->rskey = (src)->rskey;		\
738		(dest)->rkey = (src)->rkey;		\
739		(dest)->rdata = (src)->rdata;		\
740	} while (0)
741
742/* Reset the returned-memory pointers to their defaults. */
743#define	RESET_RET_MEM(dbc)				\
744	do {						\
745		(dbc)->rskey = &(dbc)->my_rskey;	\
746		(dbc)->rkey = &(dbc)->my_rkey;		\
747		(dbc)->rdata = &(dbc)->my_rdata;	\
748	} while (0)
749
750/*******************************************************
751 * Mpool.
752 *******************************************************/
753/*
754 * File types for DB access methods.  Negative numbers are reserved to DB.
755 */
756#define	DB_FTYPE_SET		-1		/* Call pgin/pgout functions. */
757#define	DB_FTYPE_NOTSET		 0		/* Don't call... */
758#define	DB_LSN_OFF_NOTSET	-1		/* Not yet set. */
759#define	DB_CLEARLEN_NOTSET	UINT32_MAX	/* Not yet set. */
760
761/* Structure used as the DB pgin/pgout pgcookie. */
762typedef struct __dbpginfo {
763	size_t	db_pagesize;		/* Underlying page size. */
764	u_int32_t flags;		/* Some DB_AM flags needed. */
765	DBTYPE  type;			/* DB type */
766} DB_PGINFO;
767
768/*******************************************************
769 * Log.
770 *******************************************************/
771/* Initialize an LSN to 'zero'. */
772#define	ZERO_LSN(LSN) do {						\
773	(LSN).file = 0;							\
774	(LSN).offset = 0;						\
775} while (0)
776#define	IS_ZERO_LSN(LSN)	((LSN).file == 0 && (LSN).offset == 0)
777
778#define	IS_INIT_LSN(LSN)	((LSN).file == 1 && (LSN).offset == 0)
779#define	INIT_LSN(LSN)		do {					\
780	(LSN).file = 1;							\
781	(LSN).offset = 0;						\
782} while (0)
783
784#define	MAX_LSN(LSN) do {						\
785	(LSN).file = UINT32_MAX;					\
786	(LSN).offset = UINT32_MAX;					\
787} while (0)
788#define	IS_MAX_LSN(LSN) \
789	((LSN).file == UINT32_MAX && (LSN).offset == UINT32_MAX)
790
791/* If logging is turned off, smash the lsn. */
792#define	LSN_NOT_LOGGED(LSN) do {					\
793	(LSN).file = 0;							\
794	(LSN).offset = 1;						\
795} while (0)
796#define	IS_NOT_LOGGED_LSN(LSN) \
797	((LSN).file == 0 && (LSN).offset == 1)
798
799/*
800 * LOG_COMPARE -- compare two LSNs.
801 */
802
803#define	LOG_COMPARE(lsn0, lsn1)						\
804    ((lsn0)->file != (lsn1)->file ?					\
805    ((lsn0)->file < (lsn1)->file ? -1 : 1) :				\
806    ((lsn0)->offset != (lsn1)->offset ?					\
807    ((lsn0)->offset < (lsn1)->offset ? -1 : 1) : 0))
808
809/*******************************************************
810 * Txn.
811 *******************************************************/
812#define	DB_NONBLOCK(C)	((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT))
813#define	NOWAIT_FLAG(txn) \
814	((txn) != NULL && F_ISSET((txn), TXN_NOWAIT) ? DB_LOCK_NOWAIT : 0)
815#define	IS_REAL_TXN(txn)						\
816	((txn) != NULL && !F_ISSET(txn, TXN_CDSGROUP))
817#define	IS_SUBTRANSACTION(txn)						\
818	((txn) != NULL && (txn)->parent != NULL)
819
820/*******************************************************
821 * Crypto.
822 *******************************************************/
823#define	DB_IV_BYTES     16		/* Bytes per IV */
824#define	DB_MAC_KEY	20		/* Bytes per MAC checksum */
825
826/*******************************************************
827 * Secondaries over RPC.
828 *******************************************************/
829#ifdef CONFIG_TEST
830/*
831 * These are flags passed to DB->associate calls by the Tcl API if running
832 * over RPC.  The RPC server will mask out these flags before making the real
833 * DB->associate call.
834 *
835 * These flags must coexist with the valid flags to DB->associate (currently
836 * DB_AUTO_COMMIT and DB_CREATE).  DB_AUTO_COMMIT is in the group of
837 * high-order shared flags (0xff000000), and DB_CREATE is in the low-order
838 * group (0x00000fff), so we pick a range in between.
839 */
840#define	DB_RPC2ND_MASK		0x00f00000 /* Reserved bits. */
841
842#define	DB_RPC2ND_REVERSEDATA	0x00100000 /* callback_n(0) _s_reversedata. */
843#define	DB_RPC2ND_NOOP		0x00200000 /* callback_n(1) _s_noop */
844#define	DB_RPC2ND_CONCATKEYDATA	0x00300000 /* callback_n(2) _s_concatkeydata */
845#define	DB_RPC2ND_CONCATDATAKEY 0x00400000 /* callback_n(3) _s_concatdatakey */
846#define	DB_RPC2ND_REVERSECONCAT	0x00500000 /* callback_n(4) _s_reverseconcat */
847#define	DB_RPC2ND_TRUNCDATA	0x00600000 /* callback_n(5) _s_truncdata */
848#define	DB_RPC2ND_CONSTANT	0x00700000 /* callback_n(6) _s_constant */
849#define	DB_RPC2ND_GETZIP	0x00800000 /* sj_getzip */
850#define	DB_RPC2ND_GETNAME	0x00900000 /* sj_getname */
851#endif
852
853#if defined(__cplusplus)
854}
855#endif
856
857/*******************************************************
858 * Remaining general DB includes.
859 *******************************************************/
860
861
862#include "dbinc/globals.h"
863#include "dbinc/clock.h"
864#include "dbinc/debug.h"
865#include "dbinc/region.h"
866#include "dbinc_auto/env_ext.h"
867#include "dbinc/mutex.h"
868#ifdef HAVE_REPLICATION_THREADS
869#include "dbinc/repmgr.h"
870#endif
871#include "dbinc/rep.h"
872#include "dbinc/os.h"
873#include "dbinc_auto/clib_ext.h"
874#include "dbinc_auto/common_ext.h"
875
876/*******************************************************
877 * Remaining Log.
878 * These need to be defined after the general includes
879 * because they need rep.h from above.
880 *******************************************************/
881/*
882 * Test if the environment is currently logging changes.  If we're in recovery
883 * or we're a replication client, we don't need to log changes because they're
884 * already in the log, even though we have a fully functional log system.
885 */
886#define	DBENV_LOGGING(env)						\
887	(LOGGING_ON(env) && !IS_REP_CLIENT(env) && (!IS_RECOVERING(env)))
888
889/*
890 * Test if we need to log a change.  By default, we don't log operations without
891 * associated transactions, unless DIAGNOSTIC, DEBUG_ROP or DEBUG_WOP are on.
892 * This is because we want to get log records for read/write operations, and, if
893 * we are trying to debug something, more information is always better.
894 *
895 * The DBC_RECOVER flag is set when we're in abort, as well as during recovery;
896 * thus DBC_LOGGING may be false for a particular dbc even when DBENV_LOGGING
897 * is true.
898 *
899 * We explicitly use LOGGING_ON/IS_REP_CLIENT here because we don't want to pull
900 * in the log headers, which IS_RECOVERING (and thus DBENV_LOGGING) rely on, and
901 * because DBC_RECOVER should be set anytime IS_RECOVERING would be true.
902 *
903 * If we're not in recovery (master - doing an abort or a client applying
904 * a txn), then a client's only path through here is on an internal
905 * operation, and a master's only path through here is a transactional
906 * operation.  Detect if either is not the case.
907 */
908#if defined(DIAGNOSTIC) || defined(DEBUG_ROP)  || defined(DEBUG_WOP)
909#define	DBC_LOGGING(dbc)	__dbc_logging(dbc)
910#else
911#define	DBC_LOGGING(dbc)						\
912	((dbc)->txn != NULL && LOGGING_ON((dbc)->env) &&		\
913	    !F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->env))
914#endif
915
916#endif /* !_DB_INT_H_ */
917