1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9 #ifndef _DB_DEBUG_H_ 10 #define _DB_DEBUG_H_ 11 12 #if defined(__cplusplus) 13 extern "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) NOP_STATEMENT 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) NOP_STATEMENT 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 */ 69 typedef 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 = (u_int32_t)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_SET(field, val) do { \ 264 if (field == (val)) \ 265 goto db_tr_err; \ 266 } while (0) 267 268 #define DB_TEST_WAIT(env, val) \ 269 if ((val) != 0) \ 270 __os_yield((env), (u_long)(val), 0) 271 #else 272 #define DB_TEST_SUBLOCKS(env, flags) 273 #define DB_ENV_TEST_RECOVERY(env, val, ret, name) 274 #define DB_TEST_RECOVERY(dbp, val, ret, name) 275 #define DB_TEST_RECOVERY_LABEL 276 #define DB_TEST_SET(env, val) 277 #define DB_TEST_WAIT(env, val) 278 #endif 279 280 #if defined(__cplusplus) 281 } 282 #endif 283 #endif /* !_DB_DEBUG_H_ */ 284