MySQL 8.3.0
Source Code Documentation
ut0dbg.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1994, 2023, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
25*****************************************************************************/
26
27/** @file include/ut0dbg.h
28 Debug utilities for Innobase
29
30 Created 1/30/1994 Heikki Tuuri
31 **********************************************************************/
32
33#ifndef ut0dbg_h
34#define ut0dbg_h
35
36#include "my_compiler.h"
37
38/* Do not include univ.i because univ.i includes this. */
39
40#include <cstdio>
41#include <functional>
42#include <sstream>
43
44/** Set a callback function to be called before exiting.
45@param[in] callback user callback function */
46void ut_set_assert_callback(std::function<void()> &callback);
47
48/** Report a failed assertion.
49@param[in] expr The failed assertion
50@param[in] file Source file containing the assertion
51@param[in] line Line number of the assertion */
52[[noreturn]] void ut_dbg_assertion_failed(const char *expr, const char *file,
53 uint64_t line);
54
55template <typename L, typename R>
56[[noreturn]] void inline ut_dbg_comparison_failed(
57 const char *lhs_expr, const L &lhs_value, const char *op,
58 const char *rhs_expr, const R &rhs_value, const char *file, uint64_t line) {
60 text << lhs_expr << " == " << lhs_value << ' ' << op << ' ' << rhs_value
61 << " == " << rhs_expr;
62 ut_dbg_assertion_failed(text.str().c_str(), file, line);
63}
64
65/** Assert that LHS OP RHS, where OP is an operator.
66Abort execution otherwise.
67Technical remarks: The LHS and RHS are evaluated exactly once (no short
68circuiting, even if OP is && or ||). Each value is stored in a local variable,
69so it's fine for LHS or RHS to return a temporary.
70In case of assertion failure references to const values of LHS and RHS will be
71passed to std::ostringstream::operator<<, so it must be implemented for them. */
72#define ut_a_op(LHS, OP, RHS) \
73 do { \
74 const auto lhs{LHS}; \
75 const auto rhs{RHS}; \
76 if (unlikely(!(lhs OP rhs))) { \
77 ut_dbg_comparison_failed(#LHS, lhs, #OP, #RHS, rhs, __FILE__, __LINE__); \
78 } \
79 } while (0)
80
81/** Assert that LHS < RHS. Abort execution otherwise. */
82#define ut_a_lt(LHS, RHS) ut_a_op(LHS, <, RHS)
83/** Assert that LHS <= RHS. Abort execution otherwise. */
84#define ut_a_le(LHS, RHS) ut_a_op(LHS, <=, RHS)
85/** Assert that LHS == RHS. Abort execution otherwise. */
86#define ut_a_eq(LHS, RHS) ut_a_op(LHS, ==, RHS)
87/** Assert that LHS != RHS. Abort execution otherwise. */
88#define ut_a_ne(LHS, RHS) ut_a_op(LHS, !=, RHS)
89
90/** Abort execution if EXPR does not evaluate to nonzero.
91@param EXPR assertion expression that should hold */
92#define ut_a(EXPR) \
93 do { \
94 if (unlikely(false == (bool)(EXPR))) { \
95 ut_dbg_assertion_failed(#EXPR, __FILE__, __LINE__); \
96 } \
97 } while (0)
98
99/** Abort execution. */
100#define ut_error ut_dbg_assertion_failed(nullptr, __FILE__, __LINE__)
101
102#ifdef UNIV_DEBUG
103/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
104#define ut_ad(EXPR) ut_a(EXPR)
105/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
106#define ut_d(EXPR) EXPR
107/** Opposite of ut_d(). Does nothing if UNIV_DEBUG is defined. */
108#define ut_o(EXPR)
109/** Debug-only assertion that LHS < RHS. */
110#define ut_ad_lt(LHS, RHS) ut_a_lt(LHS, RHS)
111/** Debug-only assertion that LHS <= RHS. */
112#define ut_ad_le(LHS, RHS) ut_a_le(LHS, RHS)
113/** Debug-only assertion that LHS == RHS. */
114#define ut_ad_eq(LHS, RHS) ut_a_eq(LHS, RHS)
115/** Assert that LHS != RHS. Abort execution otherwise. */
116#define ut_ad_ne(LHS, RHS) ut_a_op(LHS, !=, RHS)
117#else
118/** Debug assertion. Does nothing unless UNIV_DEBUG is defined. */
119#define ut_ad(EXPR)
120/** Debug statement. Does nothing unless UNIV_DEBUG is defined. */
121#define ut_d(EXPR)
122/** Opposite of ut_d(). Does nothing if UNIV_DEBUG is defined. */
123#define ut_o(EXPR) EXPR
124/** Debug-only assertion that LHS < RHS. */
125#define ut_ad_lt(LHS, RHS)
126/** Debug-only assertion that LHS <= RHS. */
127#define ut_ad_le(LHS, RHS)
128/** Debug-only assertion that LHS == RHS. */
129#define ut_ad_eq(LHS, RHS)
130/** Assert that LHS != RHS. */
131#define ut_ad_ne(LHS, RHS)
132#endif
133
134/** Debug crash point */
135#ifdef UNIV_DEBUG
136#define DBUG_INJECT_CRASH(prefix, count) \
137 do { \
138 char buf[64]; \
139 snprintf(buf, sizeof buf, prefix "_%u", count); \
140 DBUG_EXECUTE_IF(buf, DBUG_SUICIDE();); \
141 } while (0)
142
143#define DBUG_INJECT_CRASH_WITH_LOG_FLUSH(prefix, count) \
144 do { \
145 char buf[64]; \
146 snprintf(buf, sizeof buf, prefix "_%u", count); \
147 DBUG_EXECUTE_IF(buf, log_buffer_flush_to_disk(); DBUG_SUICIDE();); \
148 } while (0)
149
150#else
151#define DBUG_INJECT_CRASH(prefix, count)
152#define DBUG_INJECT_CRASH_WITH_LOG_FLUSH(prefix, count)
153#endif
154
155/** Silence warnings about an unused variable by doing a null assignment.
156@param A the unused variable */
157#define UT_NOT_USED(A) std::ignore = A
158
159#if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H)
160
161#define HAVE_UT_CHRONO_T
162
163#include <sys/resource.h>
164#include <sys/time.h>
165#include <sys/types.h>
166
167/** A "chronometer" used to clock snippets of code.
168Example usage:
169 ut_chrono_t ch("this loop");
170 for (;;) { ... }
171 ch.show();
172would print the timings of the for() loop, prefixed with "this loop:" */
174 public:
175 /** Constructor.
176 @param[in] name chrono's name, used when showing the values */
178 reset();
179 }
180
181 /** Resets the chrono (records the current time in it). */
182 void reset() {
183 gettimeofday(&m_tv, nullptr);
184
185 getrusage(RUSAGE_SELF, &m_ru);
186 }
187
188 /** Shows the time elapsed and usage statistics since the last reset. */
189 void show() {
190 struct rusage ru_now;
191 struct timeval tv_now;
192 struct timeval tv_diff;
193
194 getrusage(RUSAGE_SELF, &ru_now);
195
196 gettimeofday(&tv_now, nullptr);
197
198#ifndef timersub
199#define timersub(a, b, r) \
200 do { \
201 (r)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
202 (r)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
203 if ((r)->tv_usec < 0) { \
204 (r)->tv_sec--; \
205 (r)->tv_usec += 1000000; \
206 } \
207 } while (0)
208#endif /* timersub */
209
210#define CHRONO_PRINT(type, tvp) \
211 fprintf(stderr, "%s: %s% 5ld.%06ld sec\n", m_name, type, \
212 static_cast<long>((tvp)->tv_sec), static_cast<long>((tvp)->tv_usec))
213
214 timersub(&tv_now, &m_tv, &tv_diff);
215 CHRONO_PRINT("real", &tv_diff);
216
217 timersub(&ru_now.ru_utime, &m_ru.ru_utime, &tv_diff);
218 CHRONO_PRINT("user", &tv_diff);
219
220 timersub(&ru_now.ru_stime, &m_ru.ru_stime, &tv_diff);
221 CHRONO_PRINT("sys ", &tv_diff);
222 }
223
224 /** Cause the timings not to be printed from the destructor. */
225 void end() { m_show_from_destructor = false; }
226
227 /** Destructor. */
230 show();
231 }
232 }
233
234 private:
235 /** Name of this chronometer. */
236 const char *m_name;
237
238 /** True if the current timings should be printed by the destructor. */
240
241 /** getrusage() result as of the last reset(). */
242 struct rusage m_ru;
243
244 /** gettimeofday() result as of the last reset(). */
245 struct timeval m_tv;
246};
247
248#endif /* HAVE_SYS_TIME_H && HAVE_SYS_RESOURCE_H */
249
250#endif
A "chronometer" used to clock snippets of code.
Definition: ut0dbg.h:173
void show()
Shows the time elapsed and usage statistics since the last reset.
Definition: ut0dbg.h:189
bool m_show_from_destructor
True if the current timings should be printed by the destructor.
Definition: ut0dbg.h:239
struct rusage m_ru
getrusage() result as of the last reset().
Definition: ut0dbg.h:242
ut_chrono_t(const char *name)
Constructor.
Definition: ut0dbg.h:177
const char * m_name
Name of this chronometer.
Definition: ut0dbg.h:236
struct timeval m_tv
gettimeofday() result as of the last reset().
Definition: ut0dbg.h:245
void reset()
Resets the chrono (records the current time in it).
Definition: ut0dbg.h:182
void end()
Cause the timings not to be printed from the destructor.
Definition: ut0dbg.h:225
~ut_chrono_t()
Destructor.
Definition: ut0dbg.h:228
#define L
Definition: ctype-tis620.cc:74
Header for compiler-dependent features.
Definition: os0file.h:88
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2869
case opt name
Definition: sslopt-case.h:32
Include file for Sun RPC to compile out of the box.
#define CHRONO_PRINT(type, tvp)
void ut_dbg_assertion_failed(const char *expr, const char *file, uint64_t line)
Report a failed assertion.
Definition: ut0dbg.cc:55
#define timersub(a, b, r)
void ut_dbg_comparison_failed(const char *lhs_expr, const L &lhs_value, const char *op, const char *rhs_expr, const R &rhs_value, const char *file, uint64_t line)
Definition: ut0dbg.h:56
void ut_set_assert_callback(std::function< void()> &callback)
Set a callback function to be called before exiting.
Definition: ut0dbg.cc:47