1 /*-
2  * Copyright (c) 2014-2018 MongoDB, Inc.
3  * Copyright (c) 2008-2014 WiredTiger, Inc.
4  *	All rights reserved.
5  *
6  * See the file LICENSE for redistribution information.
7  */
8 #define	WT_COMPAT_MSG_PREFIX "Version incompatibility detected: "
9 
10 #define	WT_DEBUG_POINT	((void *)(uintptr_t)0xdeadbeef)
11 #define	WT_DEBUG_BYTE	(0xab)
12 
13 /* In DIAGNOSTIC mode, yield in places where we want to encourage races. */
14 #ifdef HAVE_DIAGNOSTIC
15 #define	WT_DIAGNOSTIC_YIELD do {					\
16 	__wt_yield();							\
17 } while (0)
18 #else
19 #define	WT_DIAGNOSTIC_YIELD
20 #endif
21 
22 #define	__wt_err(session, error, ...)					\
23 	__wt_err_func(session, error, __func__, __LINE__, __VA_ARGS__)
24 #define	__wt_errx(session, ...)						\
25 	__wt_errx_func(session, __func__, __LINE__, __VA_ARGS__)
26 #define	__wt_set_return(session, error)					\
27 	__wt_set_return_func(session, __func__, __LINE__, error)
28 
29 /* Set "ret" and branch-to-err-label tests. */
30 #define	WT_ERR(a) do {							\
31 	if ((ret = (a)) != 0)						\
32 		goto err;						\
33 } while (0)
34 #define	WT_ERR_MSG(session, v, ...) do {				\
35 	ret = (v);							\
36 	__wt_err(session, ret, __VA_ARGS__);				\
37 	goto err;							\
38 } while (0)
39 #define	WT_ERR_TEST(a, v) do {						\
40 	if (a) {							\
41 		ret = (v);						\
42 		goto err;						\
43 	} else								\
44 		ret = 0;						\
45 } while (0)
46 #define	WT_ERR_ERROR_OK(a, e)						\
47 	WT_ERR_TEST((ret = (a)) != 0 && ret != (e), ret)
48 #define	WT_ERR_BUSY_OK(a)	WT_ERR_ERROR_OK(a, EBUSY)
49 #define	WT_ERR_NOTFOUND_OK(a)	WT_ERR_ERROR_OK(a, WT_NOTFOUND)
50 
51 /* Return tests. */
52 #define	WT_RET(a) do {							\
53 	int __ret;							\
54 	if ((__ret = (a)) != 0)						\
55 		return (__ret);						\
56 } while (0)
57 #define	WT_RET_TRACK(a) do {						\
58 	int __ret;							\
59 	if ((__ret = (a)) != 0)	{					\
60 		WT_TRACK_OP_END(session);				\
61 		return (__ret);						\
62 	}								\
63 } while (0)
64 #define	WT_RET_MSG(session, v, ...) do {				\
65 	int __ret = (v);						\
66 	__wt_err(session, __ret, __VA_ARGS__);				\
67 	return (__ret);							\
68 } while (0)
69 #define	WT_RET_TEST(a, v) do {						\
70 	if (a)								\
71 		return (v);						\
72 } while (0)
73 #define	WT_RET_ERROR_OK(a, e) do {					\
74 	int __ret = (a);						\
75 	WT_RET_TEST(__ret != 0 && __ret != (e), __ret);			\
76 } while (0)
77 #define	WT_RET_BUSY_OK(a)	WT_RET_ERROR_OK(a, EBUSY)
78 #define	WT_RET_NOTFOUND_OK(a)	WT_RET_ERROR_OK(a, WT_NOTFOUND)
79 /* Set "ret" if not already set. */
80 #define	WT_TRET(a) do {							\
81 	int __ret;							\
82 	if ((__ret = (a)) != 0 &&					\
83 	    (__ret == WT_PANIC ||					\
84 	    ret == 0 || ret == WT_DUPLICATE_KEY ||			\
85 	    ret == WT_NOTFOUND || ret == WT_RESTART))			\
86 		ret = __ret;						\
87 } while (0)
88 #define	WT_TRET_ERROR_OK(a, e) do {					\
89 	int __ret;							\
90 	if ((__ret = (a)) != 0 && __ret != (e) &&			\
91 	    (__ret == WT_PANIC ||					\
92 	    ret == 0 || ret == WT_DUPLICATE_KEY ||			\
93 	    ret == WT_NOTFOUND || ret == WT_RESTART))			\
94 		ret = __ret;						\
95 } while (0)
96 #define	WT_TRET_BUSY_OK(a)	WT_TRET_ERROR_OK(a, EBUSY)
97 #define	WT_TRET_NOTFOUND_OK(a)	WT_TRET_ERROR_OK(a, WT_NOTFOUND)
98 
99 /* Called on unexpected code path: locate the failure. */
100 #define	__wt_illegal_value(session, v)					\
101 	__wt_illegal_value_func(session, (uintmax_t)(v), __func__, __LINE__)
102 
103 /* Return and branch-to-err-label cases for switch statements. */
104 #define	WT_ILLEGAL_VALUE(session, v)					\
105 	default:							\
106 		return (__wt_illegal_value(session, v))
107 #define	WT_ILLEGAL_VALUE_ERR(session, v)				\
108 	default:							\
109 		ret = __wt_illegal_value(session, v);			\
110 		goto err
111 
112 #define	WT_PANIC_MSG(session, v, ...) do {				\
113 	__wt_err(session, v, __VA_ARGS__);				\
114 	WT_IGNORE_RET(__wt_panic(session));				\
115 } while (0)
116 #define	WT_PANIC_ERR(session, v, ...) do {				\
117 	WT_PANIC_MSG(session, v, __VA_ARGS__);				\
118 	/* Return WT_PANIC regardless of earlier return codes. */	\
119 	WT_ERR(WT_PANIC);						\
120 } while (0)
121 #define	WT_PANIC_RET(session, v, ...) do {				\
122 	WT_PANIC_MSG(session, v, __VA_ARGS__);				\
123 	/* Return WT_PANIC regardless of earlier return codes. */	\
124 	return (WT_PANIC);						\
125 } while (0)
126 
127 /*
128  * WT_ASSERT
129  *	Assert an expression, aborting in diagnostic mode.  Otherwise,
130  * "use" the session to keep the compiler quiet and don't evaluate the
131  * expression.
132  */
133 #ifdef HAVE_DIAGNOSTIC
134 #define	WT_ASSERT(session, exp) do {					\
135 	if (!(exp)) {							\
136 		__wt_errx(session, "%s", #exp);				\
137 		__wt_abort(session);					\
138 	}								\
139 } while (0)
140 #else
141 #define	WT_ASSERT(session, exp)						\
142 	WT_UNUSED(session)
143 #endif
144 
145 /*
146  * __wt_verbose --
147  *	Display a verbose message.
148  *
149  * Not an inlined function because you can't inline functions taking variadic
150  * arguments and we don't want to make a function call in production systems
151  * just to find out a verbose flag isn't set.
152  *
153  * The macro must take a format string and at least one additional argument,
154  * there's no portable way to remove the comma before an empty __VA_ARGS__
155  * value.
156  */
157 #define	__wt_verbose(session, flag, fmt, ...) do {			\
158 	if (WT_VERBOSE_ISSET(session, flag))				\
159 		__wt_verbose_worker(session, fmt, __VA_ARGS__);		\
160 } while (0)
161