diff options
Diffstat (limited to 'src/dbinc/debug.h')
-rw-r--r-- | src/dbinc/debug.h | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/src/dbinc/debug.h b/src/dbinc/debug.h new file mode 100644 index 00000000..a8da000d --- /dev/null +++ b/src/dbinc/debug.h @@ -0,0 +1,283 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * $Id$ + */ + +#ifndef _DB_DEBUG_H_ +#define _DB_DEBUG_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Turn on additional error checking in gcc 3.X. + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#define __attribute__(s) +#endif + +/* + * 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. + * + * Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific. + */ +#if defined(DIAGNOSTIC) && defined(__STDC__) +#define DB_ASSERT(env, e) \ + ((e) ? (void)0 : __db_assert(env, #e, __FILE__, __LINE__)) +#else +#define DB_ASSERT(env, e) NOP_STATEMENT +#endif + +/* + * "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) do { \ + (n) = (v); \ + (n) = (n); \ +} while (0) + +/* + * 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) NOP_STATEMENT +#endif + +/* + * Errors are in one of two areas: a Berkeley DB error, or a system-level + * error. We use db_strerror to translate the former and __os_strerror to + * translate the latter. + */ +typedef enum { + DB_ERROR_NOT_SET=0, + DB_ERROR_SET=1, + DB_ERROR_SYSTEM=2 +} db_error_set_t; + +/* + * Message handling. Use a macro instead of a function because va_list + * 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. + */ +#if defined(STDC_HEADERS) || defined(__cplusplus) +#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap, fmt); \ + if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ + __db_errcall(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, and it's an application error message \ + * using {DbEnv,Db}.{err,errx} or the application has never \ + * configured an output channel, default by writing to stderr. \ + */ \ + va_start(__ap, fmt); \ + if ((dbenv) == NULL || \ + (dbenv)->db_errfile != NULL || \ + ((dbenv)->db_errcall == NULL && \ + ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ + __db_errfile(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ +} +#else +#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap); \ + if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ + __db_errcall(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, and it's an application error message \ + * using {DbEnv,Db}.{err,errx} or the application has never \ + * configured an output channel, default by writing to stderr. \ + */ \ + va_start(__ap); \ + if ((dbenv) == NULL || \ + (dbenv)->db_errfile != NULL || \ + ((dbenv)->db_errcall == NULL && \ + ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ + __db_errfile(env, error, error_set, fmt, __ap); \ + va_end(__ap); \ +} +#endif +#if defined(STDC_HEADERS) || defined(__cplusplus) +#define DB_REAL_MSG(dbenv, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap, fmt); \ + if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ + __db_msgcall(dbenv, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, write to stdout. \ + */ \ + va_start(__ap, fmt); \ + if ((dbenv) == NULL || \ + (dbenv)->db_msgfile != NULL || \ + (dbenv)->db_msgcall == NULL) { \ + __db_msgfile(dbenv, fmt, __ap); \ + } \ + va_end(__ap); \ +} +#else +#define DB_REAL_MSG(dbenv, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap); \ + if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ + __db_msgcall(dbenv, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, write to stdout. \ + */ \ + va_start(__ap); \ + if ((dbenv) == NULL || \ + (dbenv)->db_msgfile != NULL || \ + (dbenv)->db_msgcall == NULL) { \ + __db_msgfile(dbenv, fmt, __ap); \ + } \ + va_end(__ap); \ +} +#endif + +/* + * 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 = (u_int32_t)strlen(O) + 1; \ + (void)__db_debug_log((C)->env, 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 +#define DB_TEST_SUBLOCKS(env, flags) do { \ + if ((env)->test_abort == DB_TEST_SUBDB_LOCKS) \ + (flags) |= DB_LOCK_NOWAIT; \ +} while (0) + +#define DB_ENV_TEST_RECOVERY(env, val, ret, name) do { \ + int __ret; \ + PANIC_CHECK((env)); \ + if ((env)->test_copy == (val)) { \ + /* COPY the FILE */ \ + if ((__ret = __db_testcopy((env), NULL, (name))) != 0) \ + (ret) = __env_panic((env), __ret); \ + } \ + if ((env)->test_abort == (val)) { \ + /* ABORT the TXN */ \ + (env)->test_abort = 0; \ + (ret) = EINVAL; \ + goto db_tr_err; \ + } \ +} while (0) + +#define DB_TEST_RECOVERY(dbp, val, ret, name) do { \ + ENV *__env = (dbp)->env; \ + int __ret; \ + PANIC_CHECK(__env); \ + if (__env->test_copy == (val)) { \ + /* Copy the file. */ \ + if (F_ISSET((dbp), \ + DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL) \ + (void)__db_sync(dbp); \ + if ((__ret = \ + __db_testcopy(__env, (dbp), (name))) != 0) \ + (ret) = __env_panic(__env, __ret); \ + } \ + if (__env->test_abort == (val)) { \ + /* Abort the transaction. */ \ + __env->test_abort = 0; \ + (ret) = EINVAL; \ + goto db_tr_err; \ + } \ +} while (0) + +#define DB_TEST_RECOVERY_LABEL db_tr_err: + +#define DB_TEST_SET(field, val) do { \ + if (field == (val)) \ + goto db_tr_err; \ +} while (0) + +#define DB_TEST_WAIT(env, val) \ + if ((val) != 0) \ + __os_yield((env), (u_long)(val), 0) +#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 +#define DB_TEST_SET(env, val) +#define DB_TEST_WAIT(env, val) +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_DEBUG_H_ */ |