1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1998,2008 Oracle. All rights reserved. 5 * 6 * $Id: debug.h,v 12.19 2008/01/29 01:41:10 bostic Exp $ 7 */ 8 9#ifndef _DB_DEBUG_H_ 10#define _DB_DEBUG_H_ 11 12#if defined(__cplusplus) 13extern "C" { 14#endif 15 16/* 17 * Turn on additional error checking in gcc 3.X. 18 */ 19#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) 20#define __attribute__(s) 21#endif 22 23/* 24 * When running with #DIAGNOSTIC defined, we smash memory and do memory 25 * guarding with a special byte value. 26 */ 27#define CLEAR_BYTE 0xdb 28#define GUARD_BYTE 0xdc 29 30/* 31 * DB assertions. 32 * 33 * Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific. 34 */ 35#if defined(DIAGNOSTIC) && defined(__STDC__) 36#define DB_ASSERT(env, e) \ 37 ((e) ? (void)0 : __db_assert(env, #e, __FILE__, __LINE__)) 38#else 39#define DB_ASSERT(env, e) 40#endif 41 42/* 43 * "Shut that bloody compiler up!" 44 * 45 * Unused, or not-used-yet variable. We need to write and then read the 46 * variable, some compilers are too bloody clever by half. 47 */ 48#define COMPQUIET(n, v) do { \ 49 (n) = (v); \ 50 (n) = (n); \ 51} while (0) 52 53/* 54 * Purify and other run-time tools complain about uninitialized reads/writes 55 * of structure fields whose only purpose is padding, as well as when heap 56 * memory that was never initialized is written to disk. 57 */ 58#ifdef UMRW 59#define UMRW_SET(v) (v) = 0 60#else 61#define UMRW_SET(v) 62#endif 63 64/* 65 * Errors are in one of two areas: a Berkeley DB error, or a system-level 66 * error. We use db_strerror to translate the former and __os_strerror to 67 * translate the latter. 68 */ 69typedef enum { 70 DB_ERROR_NOT_SET=0, 71 DB_ERROR_SET=1, 72 DB_ERROR_SYSTEM=2 73} db_error_set_t; 74 75/* 76 * Message handling. Use a macro instead of a function because va_list 77 * references to variadic arguments cannot be reset to the beginning of the 78 * variadic argument list (and then rescanned), by functions other than the 79 * original routine that took the variadic list of arguments. 80 */ 81#if defined(STDC_HEADERS) || defined(__cplusplus) 82#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ 83 va_list __ap; \ 84 \ 85 /* Call the application's callback function, if specified. */ \ 86 va_start(__ap, fmt); \ 87 if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ 88 __db_errcall(dbenv, error, error_set, fmt, __ap); \ 89 va_end(__ap); \ 90 \ 91 /* \ 92 * If the application specified a file descriptor, write to it. \ 93 * If we wrote to neither the application's callback routine or \ 94 * its file descriptor, and it's an application error message \ 95 * using {DbEnv,Db}.{err,errx} or the application has never \ 96 * configured an output channel, default by writing to stderr. \ 97 */ \ 98 va_start(__ap, fmt); \ 99 if ((dbenv) == NULL || \ 100 (dbenv)->db_errfile != NULL || \ 101 ((dbenv)->db_errcall == NULL && \ 102 ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ 103 __db_errfile(dbenv, error, error_set, fmt, __ap); \ 104 va_end(__ap); \ 105} 106#else 107#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ 108 va_list __ap; \ 109 \ 110 /* Call the application's callback function, if specified. */ \ 111 va_start(__ap); \ 112 if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ 113 __db_errcall(dbenv, error, error_set, fmt, __ap); \ 114 va_end(__ap); \ 115 \ 116 /* \ 117 * If the application specified a file descriptor, write to it. \ 118 * If we wrote to neither the application's callback routine or \ 119 * its file descriptor, and it's an application error message \ 120 * using {DbEnv,Db}.{err,errx} or the application has never \ 121 * configured an output channel, default by writing to stderr. \ 122 */ \ 123 va_start(__ap); \ 124 if ((dbenv) == NULL || \ 125 (dbenv)->db_errfile != NULL || \ 126 ((dbenv)->db_errcall == NULL && \ 127 ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ 128 __db_errfile(env, error, error_set, fmt, __ap); \ 129 va_end(__ap); \ 130} 131#endif 132#if defined(STDC_HEADERS) || defined(__cplusplus) 133#define DB_REAL_MSG(dbenv, fmt) { \ 134 va_list __ap; \ 135 \ 136 /* Call the application's callback function, if specified. */ \ 137 va_start(__ap, fmt); \ 138 if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ 139 __db_msgcall(dbenv, fmt, __ap); \ 140 va_end(__ap); \ 141 \ 142 /* \ 143 * If the application specified a file descriptor, write to it. \ 144 * If we wrote to neither the application's callback routine or \ 145 * its file descriptor, write to stdout. \ 146 */ \ 147 va_start(__ap, fmt); \ 148 if ((dbenv) == NULL || \ 149 (dbenv)->db_msgfile != NULL || \ 150 (dbenv)->db_msgcall == NULL) { \ 151 __db_msgfile(dbenv, fmt, __ap); \ 152 } \ 153 va_end(__ap); \ 154} 155#else 156#define DB_REAL_MSG(dbenv, fmt) { \ 157 va_list __ap; \ 158 \ 159 /* Call the application's callback function, if specified. */ \ 160 va_start(__ap); \ 161 if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ 162 __db_msgcall(dbenv, fmt, __ap); \ 163 va_end(__ap); \ 164 \ 165 /* \ 166 * If the application specified a file descriptor, write to it. \ 167 * If we wrote to neither the application's callback routine or \ 168 * its file descriptor, write to stdout. \ 169 */ \ 170 va_start(__ap); \ 171 if ((dbenv) == NULL || \ 172 (dbenv)->db_msgfile != NULL || \ 173 (dbenv)->db_msgcall == NULL) { \ 174 __db_msgfile(dbenv, fmt, __ap); \ 175 } \ 176 va_end(__ap); \ 177} 178#endif 179 180/* 181 * Debugging macro to log operations. 182 * If DEBUG_WOP is defined, log operations that modify the database. 183 * If DEBUG_ROP is defined, log operations that read the database. 184 * 185 * D dbp 186 * T txn 187 * O operation (string) 188 * K key 189 * A data 190 * F flags 191 */ 192#define LOG_OP(C, T, O, K, A, F) { \ 193 DB_LSN __lsn; \ 194 DBT __op; \ 195 if (DBC_LOGGING((C))) { \ 196 memset(&__op, 0, sizeof(__op)); \ 197 __op.data = O; \ 198 __op.size = strlen(O) + 1; \ 199 (void)__db_debug_log((C)->env, T, &__lsn, 0, \ 200 &__op, (C)->dbp->log_filename->id, K, A, F); \ 201 } \ 202} 203#ifdef DEBUG_ROP 204#define DEBUG_LREAD(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) 205#else 206#define DEBUG_LREAD(C, T, O, K, A, F) 207#endif 208#ifdef DEBUG_WOP 209#define DEBUG_LWRITE(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) 210#else 211#define DEBUG_LWRITE(C, T, O, K, A, F) 212#endif 213 214/* 215 * Hook for testing recovery at various places in the create/delete paths. 216 * Hook for testing subdb locks. 217 */ 218#if CONFIG_TEST 219#define DB_TEST_SUBLOCKS(env, flags) do { \ 220 if ((env)->test_abort == DB_TEST_SUBDB_LOCKS) \ 221 (flags) |= DB_LOCK_NOWAIT; \ 222} while (0) 223 224#define DB_ENV_TEST_RECOVERY(env, val, ret, name) do { \ 225 int __ret; \ 226 PANIC_CHECK((env)); \ 227 if ((env)->test_copy == (val)) { \ 228 /* COPY the FILE */ \ 229 if ((__ret = __db_testcopy((env), NULL, (name))) != 0) \ 230 (ret) = __env_panic((env), __ret); \ 231 } \ 232 if ((env)->test_abort == (val)) { \ 233 /* ABORT the TXN */ \ 234 (env)->test_abort = 0; \ 235 (ret) = EINVAL; \ 236 goto db_tr_err; \ 237 } \ 238} while (0) 239 240#define DB_TEST_RECOVERY(dbp, val, ret, name) do { \ 241 ENV *__env = (dbp)->env; \ 242 int __ret; \ 243 PANIC_CHECK(__env); \ 244 if (__env->test_copy == (val)) { \ 245 /* Copy the file. */ \ 246 if (F_ISSET((dbp), \ 247 DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL) \ 248 (void)__db_sync(dbp); \ 249 if ((__ret = \ 250 __db_testcopy(__env, (dbp), (name))) != 0) \ 251 (ret) = __env_panic(__env, __ret); \ 252 } \ 253 if (__env->test_abort == (val)) { \ 254 /* Abort the transaction. */ \ 255 __env->test_abort = 0; \ 256 (ret) = EINVAL; \ 257 goto db_tr_err; \ 258 } \ 259} while (0) 260 261#define DB_TEST_RECOVERY_LABEL db_tr_err: 262 263#define DB_TEST_WAIT(env, val) \ 264 if ((val) != 0) \ 265 __os_yield((env), (u_long)(val), 0) 266#else 267#define DB_TEST_SUBLOCKS(env, flags) 268#define DB_ENV_TEST_RECOVERY(env, val, ret, name) 269#define DB_TEST_RECOVERY(dbp, val, ret, name) 270#define DB_TEST_RECOVERY_LABEL 271#define DB_TEST_WAIT(env, val) 272#endif 273 274#if defined(__cplusplus) 275} 276#endif 277#endif /* !_DB_DEBUG_H_ */ 278