debug.h 7.4 KB
Newer Older
unknown's avatar
unknown committed
1 2 3
/*-
 * See the file LICENSE for redistribution information.
 *
unknown's avatar
unknown committed
4
 * Copyright (c) 1998-2005
unknown's avatar
unknown committed
5 6
 *	Sleepycat Software.  All rights reserved.
 *
unknown's avatar
unknown committed
7
 * $Id: debug.h,v 12.2 2005/06/16 20:21:47 bostic Exp $
unknown's avatar
unknown committed
8 9 10 11 12 13 14 15 16
 */

#ifndef _DB_DEBUG_H_
#define	_DB_DEBUG_H_

#if defined(__cplusplus)
extern "C" {
#endif

unknown's avatar
unknown committed
17 18 19 20 21 22 23
/*
 * Turn on additional error checking in gcc 3.X.
 */
#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
#define	__attribute__(s)
#endif

unknown's avatar
unknown committed
24 25 26 27 28 29 30 31 32
/*
 * When running with #DIAGNOSTIC defined, we smash memory and do memory
 * guarding with a special byte value.
 */
#define	CLEAR_BYTE	0xdb
#define	GUARD_BYTE	0xdc

/*
 * DB assertions.
unknown's avatar
unknown committed
33 34
 *
 * Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific.
unknown's avatar
unknown committed
35
 */
unknown's avatar
unknown committed
36
#if defined(__STDC__) && defined(DIAGNOSTIC)
unknown's avatar
unknown committed
37 38 39 40 41
#define	DB_ASSERT(e)	((e) ? (void)0 : __db_assert(#e, __FILE__, __LINE__))
#else
#define	DB_ASSERT(e)
#endif

unknown's avatar
unknown committed
42 43 44 45 46 47 48 49 50 51
/*
 * "Shut that bloody compiler up!"
 *
 * Unused, or not-used-yet variable.  We need to write and then read the
 * variable, some compilers are too bloody clever by half.
 */
#define	COMPQUIET(n, v)							\
	(n) = (v);							\
	(n) = (n)

unknown's avatar
unknown committed
52 53 54 55 56 57 58 59 60 61 62 63
/*
 * Purify and other run-time tools complain about uninitialized reads/writes
 * of structure fields whose only purpose is padding, as well as when heap
 * memory that was never initialized is written to disk.
 */
#ifdef	UMRW
#define	UMRW_SET(v)	(v) = 0
#else
#define	UMRW_SET(v)
#endif

/*
unknown's avatar
unknown committed
64
 * Message handling.  Use a macro instead of a function because va_list
unknown's avatar
unknown committed
65 66 67 68
 * references to variadic arguments cannot be reset to the beginning of the
 * variadic argument list (and then rescanned), by functions other than the
 * original routine that took the variadic list of arguments.
 */
unknown's avatar
unknown committed
69 70
#if defined(STDC_HEADERS) || defined(__cplusplus)
#define	DB_REAL_ERR(env, error, error_set, default_stream, fmt) {	\
unknown's avatar
unknown committed
71 72
	va_list ap;							\
									\
unknown's avatar
unknown committed
73
	/* Call the application's callback function, if specified. */	\
unknown's avatar
unknown committed
74 75 76 77 78
	va_start(ap, fmt);						\
	if ((env) != NULL && (env)->db_errcall != NULL)			\
		__db_errcall(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
									\
unknown's avatar
unknown committed
79
	/* Write to the application's file descriptor, if specified. */\
unknown's avatar
unknown committed
80 81 82 83 84 85 86 87 88 89
	va_start(ap, fmt);						\
	if ((env) != NULL && (env)->db_errfile != NULL)			\
		__db_errfile(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
									\
	/*								\
	 * If we have a default and we didn't do either of the above,	\
	 * write to the default.					\
	 */								\
	va_start(ap, fmt);						\
unknown's avatar
unknown committed
90
	if ((default_stream) && ((env) == NULL ||			\
unknown's avatar
unknown committed
91 92 93 94 95
	    ((env)->db_errcall == NULL && (env)->db_errfile == NULL)))	\
		__db_errfile(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
}
#else
unknown's avatar
unknown committed
96
#define	DB_REAL_ERR(env, error, error_set, default_stream, fmt) {	\
unknown's avatar
unknown committed
97 98
	va_list ap;							\
									\
unknown's avatar
unknown committed
99
	/* Call the application's callback function, if specified. */	\
unknown's avatar
unknown committed
100 101 102 103 104
	va_start(ap);							\
	if ((env) != NULL && (env)->db_errcall != NULL)			\
		__db_errcall(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
									\
unknown's avatar
unknown committed
105
	/* Write to the application's file descriptor, if specified. */\
unknown's avatar
unknown committed
106 107 108 109 110 111 112 113 114 115
	va_start(ap);							\
	if ((env) != NULL && (env)->db_errfile != NULL)			\
		__db_errfile(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
									\
	/*								\
	 * If we have a default and we didn't do either of the above,	\
	 * write to the default.					\
	 */								\
	va_start(ap);							\
unknown's avatar
unknown committed
116
	if ((default_stream) && ((env) == NULL ||			\
unknown's avatar
unknown committed
117 118 119 120 121
	    ((env)->db_errcall == NULL && (env)->db_errfile == NULL)))	\
		__db_errfile(env, error, error_set, fmt, ap);		\
	va_end(ap);							\
}
#endif
unknown's avatar
unknown committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
#if defined(STDC_HEADERS) || defined(__cplusplus)
#define	DB_REAL_MSG(env, fmt) {						\
	va_list ap;							\
									\
	/* Call the application's callback function, if specified. */	\
	va_start(ap, fmt);						\
	if ((env) != NULL && (env)->db_msgcall != NULL)			\
		__db_msgcall(env, fmt, ap);				\
	va_end(ap);							\
									\
	/*								\
	 * If the application specified a file descriptor, or we wrote	\
	 * to neither the application's callback routine or to its file	\
	 * descriptor, write to stdout.					\
	 */								\
	va_start(ap, fmt);						\
	if ((env) == NULL ||						\
	    (env)->db_msgfile != NULL || (env)->db_msgcall == NULL) {	\
		__db_msgfile(env, fmt, ap);				\
	}								\
	va_end(ap);							\
}
#else
#define	DB_REAL_MSG(env, fmt) {						\
	va_list ap;							\
									\
	/* Call the application's callback function, if specified. */	\
	va_start(ap);							\
	if ((env) != NULL && (env)->db_msgcall != NULL)			\
		__db_msgcall(env, fmt, ap);				\
	va_end(ap);							\
									\
	/*								\
	 * If the application specified a file descriptor, or we wrote	\
	 * to neither the application's callback routine or to its file	\
	 * descriptor, write to stdout.					\
	 */								\
	va_start(ap);							\
	if ((env) == NULL ||						\
	    (env)->db_msgfile != NULL || (env)->db_msgcall == NULL) {	\
		__db_msgfile(env, fmt, ap);				\
	}								\
	va_end(ap);							\
}
#endif
unknown's avatar
unknown committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206

/*
 * Debugging macro to log operations.
 *	If DEBUG_WOP is defined, log operations that modify the database.
 *	If DEBUG_ROP is defined, log operations that read the database.
 *
 * D dbp
 * T txn
 * O operation (string)
 * K key
 * A data
 * F flags
 */
#define	LOG_OP(C, T, O, K, A, F) {					\
	DB_LSN __lsn;							\
	DBT __op;							\
	if (DBC_LOGGING((C))) {						\
		memset(&__op, 0, sizeof(__op));				\
		__op.data = O;						\
		__op.size = strlen(O) + 1;				\
		(void)__db_debug_log((C)->dbp->dbenv, T, &__lsn, 0,	\
		    &__op, (C)->dbp->log_filename->id, K, A, F);	\
	}								\
}
#ifdef	DEBUG_ROP
#define	DEBUG_LREAD(C, T, O, K, A, F)	LOG_OP(C, T, O, K, A, F)
#else
#define	DEBUG_LREAD(C, T, O, K, A, F)
#endif
#ifdef	DEBUG_WOP
#define	DEBUG_LWRITE(C, T, O, K, A, F)	LOG_OP(C, T, O, K, A, F)
#else
#define	DEBUG_LWRITE(C, T, O, K, A, F)
#endif

/*
 * Hook for testing recovery at various places in the create/delete paths.
 * Hook for testing subdb locks.
 */
#if CONFIG_TEST
unknown's avatar
unknown committed
207
#define	DB_TEST_SUBLOCKS(env, flags) do {				\
unknown's avatar
unknown committed
208 209 210 211
	if ((env)->test_abort == DB_TEST_SUBDB_LOCKS)			\
		(flags) |= DB_LOCK_NOWAIT;				\
} while (0)

unknown's avatar
unknown committed
212
#define	DB_ENV_TEST_RECOVERY(env, val, ret, name) do {			\
unknown's avatar
unknown committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	int __ret;							\
	PANIC_CHECK((env));						\
	if ((env)->test_copy == (val)) {				\
		/* COPY the FILE */					\
		if ((__ret = __db_testcopy((env), NULL, (name))) != 0)	\
			(ret) = __db_panic((env), __ret);		\
	}								\
	if ((env)->test_abort == (val)) {				\
		/* ABORT the TXN */					\
		(env)->test_abort = 0;					\
		(ret) = EINVAL;						\
		goto db_tr_err;						\
	}								\
} while (0)

unknown's avatar
unknown committed
228
#define	DB_TEST_RECOVERY(dbp, val, ret, name) do {			\
unknown's avatar
unknown committed
229 230 231 232 233 234
	int __ret;							\
	PANIC_CHECK((dbp)->dbenv);					\
	if ((dbp)->dbenv->test_copy == (val)) {				\
		/* Copy the file. */					\
		if (F_ISSET((dbp),					\
		    DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL)		\
unknown's avatar
unknown committed
235
			(void)__db_sync(dbp);				\
unknown's avatar
unknown committed
236 237 238 239 240 241 242 243 244 245 246 247 248
		if ((__ret =						\
		    __db_testcopy((dbp)->dbenv, (dbp), (name))) != 0)	\
			(ret) = __db_panic((dbp)->dbenv, __ret);	\
	}								\
	if ((dbp)->dbenv->test_abort == (val)) {			\
		/* Abort the transaction. */				\
		(dbp)->dbenv->test_abort = 0;				\
		(ret) = EINVAL;						\
		goto db_tr_err;						\
	}								\
} while (0)

#define	DB_TEST_RECOVERY_LABEL	db_tr_err:
unknown's avatar
unknown committed
249

unknown's avatar
unknown committed
250 251
#define	DB_TEST_WAIT(env, val)					\
	if ((val) != 0)						\
unknown's avatar
unknown committed
252
		__os_sleep((env), (u_long)(val), 0)
unknown's avatar
unknown committed
253 254 255 256 257
#else
#define	DB_TEST_SUBLOCKS(env, flags)
#define	DB_ENV_TEST_RECOVERY(env, val, ret, name)
#define	DB_TEST_RECOVERY(dbp, val, ret, name)
#define	DB_TEST_RECOVERY_LABEL
unknown's avatar
unknown committed
258
#define	DB_TEST_WAIT(env, val)
unknown's avatar
unknown committed
259 260 261 262 263 264
#endif

#if defined(__cplusplus)
}
#endif
#endif /* !_DB_DEBUG_H_ */