MySQL 8.0.40
Source Code Documentation
ut0test.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2020, 2024, 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 designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27/*
28
29ABOUT:
30
31If you want to execute some arbitrary code on the server side, for testing
32purposes (mtr tests), then this module is for that purpose. There is no
33need to introduce more debug variables to execute code in InnoDB. Many such
34uses can be accomplished using this module.
35
36OVERVIEW:
37
38The idea of this module is to be able to write mtr test case like:
39
40Example Code:
41
42SET SESSION innodb_interpreter = 'init';
43SET SESSION innodb_interpreter = 'open_table test/t1';
44
45--echo # Identify the space_id of the given table.
46SET SESSION innodb_interpreter = 'find_space_id test/t1';
47SELECT @@session.innodb_interpreter_output INTO @space_id;
48
49--echo # Find the root page number of the given table.
50SET SESSION innodb_interpreter = 'find_root_page_no test/t1';
51SELECT @@session.innodb_interpreter_output INTO @page_no;
52
53--echo # Find the on-disk page type of the given page.
54SET @cmd = CONCAT('find_ondisk_page_type ', @space_id, ' ', @page_no);
55SET SESSION innodb_interpreter = @cmd;
56SELECT @@session.innodb_interpreter_output INTO @page_type;
57SELECT @page_type;
58
59SET SESSION innodb_interpreter = 'corrupt_ondisk_root_page test/t1';
60SET SESSION innodb_interpreter = 'destroy';
61
62INTRODUCTION:
63
64There are two system variables innodb_interpreter and
65innodb_interpreter_output. We issue commands via innodb_interpreter variable
66and we access its output via innodb_interpreter_output variable. Refer to the
67above example.
68
69USAGE:
70
71The basic way to use this infrastructure is as follows:
72
73SET SESSION innodb_interpreter = 'command arg1 arg2 ... argN';
74SELECT @@session.innodb_interpreter_output;
75
76We send some command and arguments to the innodb_interpreter variable. And we
77look at the results in the innodb_interpreter_output variable.
78
79ADDING NEW COMMANDS:
80
81If you want to add a new command, here are the list of things you need to do in
82this module:
83
841. Decide the command name. Let 'hello_world' be the command name and let is
85take 3 arguments - arg1, arg2 and arg3. So the command will be invoked as
86follows:
87
88 SET SESSION innodb_interpreter = 'hello_world arg1 arg2 arg3';
89
902. Add member function with same name as the command to the Tester class. Its
91 signature would be as follows:
92
93 [[nodiscard]] Ret_t hello_world(std::vector<std::string> &tokens) noexcept;
94
95 The command has 4 tokens - the command name followed by 3 arguments. The
96 vector will be of size 4.
97
983. In the constructor Tester::Tester() add the line:
99
100 DISPATCH(hello_world);
101
1024. While implementing the member function hello_world(), populate the member
103 Tester::m_log with the output you want to give the user for the given
104 command.
105
1065. Execute the command as follows:
107
108 SET SESSION innodb_interpreter = 'hello_world one two three';
109
110 Check its output as follows:
111
112 SELECT @@session.innodb_interpreter_output;
113
114NOTE: You can make the command either stateful or stateless. It is up to you.
115
116*/
117
118#ifndef ut0test_h
119#define ut0test_h
120#ifdef UNIV_DEBUG
121
122#include <string>
123#include <vector>
124#include "current_thd.h"
125#include "fil0fil.h"
126#include "mysql/plugin.h"
127
128/** This is the prefix used for the log messages that will be updated in the
129innodb_interpreter_output system variable. */
130#define TPREFIX "[ib::Tester] "
131
132#define TLOG(x) \
133 { \
134 std::cout << "[TLOG] thread=" << std::this_thread::get_id() << ": " << x \
135 << std::endl; \
136 }
137
138/** A macro to log output in both the server error log (via std::cout, the
139standard output) and the server system variable innodb_interpreter_output.
140To use this macro, there must be a std::ostringstream object "sout" available
141in the scope in which it is used. */
142#define XLOG(x) \
143 { \
144 TLOG(x) \
145 sout << x; \
146 }
147
148namespace ib {
149
150/** This class contains implementations of the commands that can be executed
151at server side by passing them via the innodb_interpreter system variable. */
152struct Tester {
153 public:
154 /** The return status code used by the various commands in this module. */
155 enum Ret_t {
158
159 /* The command is yet to handled. */
160 RET_CMD_TBD = 2
161 };
162
163 /** Default constructor. */
164 Tester() noexcept;
165
166 /** Run the given command.
167 @param[in] cmd the command to run.
168 @return 0 on success.
169 @return error code on failure. */
170 [[nodiscard]] Ret_t run(ulong cmd) noexcept;
171
172 /** Run the given command.
173 @param[in] cmd the command to run.
174 @return 0 on success.
175 @return error code on failure. */
176 [[nodiscard]] Ret_t run(const std::string &cmd) noexcept;
177
178 /** Get the last generated output.
179 @return the last generated output. */
180 [[nodiscard]] const char *get_last_log() const noexcept {
181 return m_log.c_str();
182 }
183
184 /** Let the thread-variable innodb_interpreter_output point to the current
185 output. */
186 void update_thd_variable() noexcept;
187
188 private:
189 /** Initialize the internal state of the tester. */
190 void init() noexcept;
191
192 /** Open the specified table.
193 @param[in] tokens the given command line
194 @return RET_PASS on success, or the error code. */
195 [[nodiscard]] Ret_t open_table(std::vector<std::string> &tokens) noexcept;
196
197 /** Close the given table.
198 @param[in] table the table object */
199 void close_table(dict_table_t *table) noexcept;
200
201 /** Find the space_id of the given table.
202 @param[in] tokens the given command line
203 @return RET_PASS on success, or the error code. */
204 [[nodiscard]] Ret_t find_space_id(std::vector<std::string> &tokens) noexcept;
205
206 /** Find the root page of the given table.
207 @param[in] tokens the given command line
208 @return RET_PASS on success, or the error code. */
209 [[nodiscard]] Ret_t find_root_page_no(
210 std::vector<std::string> &tokens) noexcept;
211
212 /** Find the on-disk page type of the given page.
213 @param[in] tokens the given command line
214 @return RET_PASS on success, or the error code. */
215 [[nodiscard]] Ret_t find_ondisk_page_type(
216 std::vector<std::string> &tokens) noexcept;
217
218 /** Find the FIL_PAGE_LSN of the given page.
219 @param[in] tokens the given command line
220 @return RET_PASS on success, or the error code. */
221 [[nodiscard]] Ret_t find_fil_page_lsn(
222 std::vector<std::string> &tokens) noexcept;
223
224 /** Find the flush sync lsn from the buffer pool module.
225 @param[in] tokens the given command line
226 @return RET_PASS on success, or the error code. */
227 [[nodiscard]] Ret_t find_flush_sync_lsn(
228 std::vector<std::string> &tokens) noexcept;
229
230 /** Print the page type of pages in dblwr file to server error log.
231 @param[in] tokens the given command line
232 @return RET_PASS on success, or the error code. */
234 std::vector<std::string> &tokens) noexcept;
235
236 /** Obtain the file name of the given tablespace
237 @param[in] tokens the given command line
238 @return RET_PASS on success, or the error code. */
239 [[nodiscard]] Ret_t find_tablespace_file_name(
240 std::vector<std::string> &tokens) noexcept;
241
242 /** A macro to declare a dispatch function or a command function. They all
243 have the same signature.
244 @param[in] func_ the function that is being declared. */
245#define DISPATCH_FUNCTION(func_) \
246 /* @param[in] tokens the command line */ \
247 /* @return RET_PASS on success, or the error code. */ \
248 [[nodiscard]] Ret_t func_(std::vector<std::string> &tokens) noexcept
249
250 /** Count various page_types for given tablespace. */
251 DISPATCH_FUNCTION(count_page_type);
252
253 /** Count various page_types for given tablespace. */
254 DISPATCH_FUNCTION(count_used_and_free);
255
256 /** Obtain the page size of the given tablespace. */
257 DISPATCH_FUNCTION(find_tablespace_physical_page_size);
258
259 /** Fill the root page of the given table with zeroes. */
260 DISPATCH_FUNCTION(make_ondisk_root_page_zeroes);
261
262 /** Make the page dirty. It takes two arguments.
263 make_page_dirty space_id page_no */
264 DISPATCH_FUNCTION(make_page_dirty);
265
266 /** Corrupt the root page of the given table.
267 @param[in] tokens the given command line
268 @return RET_PASS on success, or the error code. */
269 [[nodiscard]] Ret_t corrupt_ondisk_root_page(
270 std::vector<std::string> &tokens) noexcept;
271
272 /** Corrupt the first page of the given tablespace.
273 @param[in] tokens the given command line
274 @return RET_PASS on success, or the error code. */
275 [[nodiscard]] Ret_t corrupt_ondisk_page0(
276 std::vector<std::string> &tokens) noexcept;
277
278 /** Set the dblwr::Force_crash to the desired page. This will
279 crash the server after flushing the page to dblwr.
280 @return RET_PASS on success, or the error code. */
281 DISPATCH_FUNCTION(dblwr_force_crash);
282
283 /** Destroy the tester object. */
284 void destroy() noexcept;
285
286 private:
287 /** Check if the given table is already opened.
288 @param[in] table_name name of the table to open.
289 @return if table is already open return its pointer.
290 @return if table is NOT already open return nullptr. */
291 [[nodiscard]] dict_table_t *is_table_open(
292 const std::string &table_name) const noexcept;
293
294 /** Set the output value of the interpreter.
295 @param[in] sout the output string stream containing the output string. */
296 void set_output(const std::ostringstream &sout) noexcept;
297
298 /** Set the output value of the interpreter to the given value.
299 @param[in] log the output string */
300 void set_output(const std::string &log) noexcept;
301
302 /** Append the given string to the output value of the interpreter.
303 @param[in] log the output string to be appended*/
304 void append_output(const std::string &log) noexcept;
305
306 /** Make the output empty. */
307 void clear_output() noexcept;
308
309 /** Make the first prefix_length bytes of the given page as zeroes.
310 @param[in] space_id the tablespace identifier of the page to be zeroed.
311 @param[in] page_no page number within the given tablespace.
312 @param[in] prefix_length the length of the page, from beginning, to be
313 zeroed.
314 @return RET_PASS on success, or error code on failure. */
315 Ret_t clear_page_prefix(const space_id_t space_id, page_no_t page_no,
316 const size_t prefix_length);
317
318 private:
319 /** List of open tables. */
321
322 /** Current thread object. */
324
325 /** The actual log data that is shared with the client via the thread-variable
326 innodb_interpreter_output. (Search for the variable interpreter_output in
327 the file ha_innodb.cc) */
328 std::string m_log{};
329
330 /** The latest command executed. */
331 std::string m_command{};
332
333 using Function_executor = Ret_t (Tester::*)(std::vector<std::string> &);
334 using Pair = std::pair<const std::string, Function_executor>;
336
337 /** Mapping b/w the command name and the function to execute. */
338 std::map<std::string, Function_executor, std::less<std::string>, Allocator>
340};
341
342/** The main function to execute the commands in the tester.
343@param[in] command the command to execute.
344@return the error code. */
345[[nodiscard]] int interpreter_run(const char *command) noexcept;
346
347} // namespace ib
348
349/** Update the innodb_interpreter_output system variable to let the user
350access the output generated by the tester. Refer to mysql_var_update_func() for
351details of the function signature.
352@param[in] thd thread handle
353@param[in] var dynamic variable being altered
354@param[in] var_ptr pointer to dynamic variable
355@param[in] save pointer to temporary storage. */
356void ib_interpreter_update(MYSQL_THD thd, SYS_VAR *var, void *var_ptr,
357 const void *save);
358
359/**Check whether given command is valid for the InnoDB interpreter
360Refer to mysql_var_check_func() for more details.
361@param[in] thd thread handle
362@param[in] var pointer to system variable
363@param[out] save immediate result for update function
364@param[in] value incoming string
365@return 0 for valid command. */
366int ib_interpreter_check(THD *thd, SYS_VAR *var, void *save,
367 struct st_mysql_value *value);
368
369#endif /* UNIV_DEBUG */
370#endif // ut0test_h
uint32_t space_id_t
Tablespace identifier.
Definition: api0api.h:52
uint32_t page_no_t
Page number.
Definition: api0api.h:50
#define MYSQL_THD
Definition: backup_page_tracker.h:38
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:34
Allocator that allows std::* containers to manage their memory through ut::malloc* and ut::free libra...
Definition: ut0new.h:2182
The low-level file system.
Definition: ut0core.h:49
int interpreter_run(const char *command) noexcept
The main function to execute the commands in the tester.
Definition: ut0test.cc:699
const char * table_name
Definition: rules_table_service.cc:56
Definition: gcs_xcom_synode.h:64
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2871
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2875
std::list< T, ut::allocator< T > > list
Specialization of list which uses ut_allocator.
Definition: ut0new.h:2879
Definition: plugin.h:67
Data structure for a database table.
Definition: dict0mem.h:1909
This class contains implementations of the commands that can be executed at server side by passing th...
Definition: ut0test.h:152
std::string m_log
The actual log data that is shared with the client via the thread-variable innodb_interpreter_output.
Definition: ut0test.h:328
std::list< dict_table_t *, ut::allocator< dict_table_t * > > m_open_tables
List of open tables.
Definition: ut0test.h:320
void clear_output() noexcept
Make the output empty.
Definition: ut0test.cc:695
Ret_t clear_page_prefix(const space_id_t space_id, page_no_t page_no, const size_t prefix_length)
Make the first prefix_length bytes of the given page as zeroes.
Definition: ut0test.cc:437
DISPATCH_FUNCTION(count_used_and_free)
Count various page_types for given tablespace.
Ret_t
The return status code used by the various commands in this module.
Definition: ut0test.h:155
@ RET_CMD_TBD
Definition: ut0test.h:160
@ RET_PASS
Definition: ut0test.h:156
@ RET_FAIL
Definition: ut0test.h:157
Ret_t corrupt_ondisk_root_page(std::vector< std::string > &tokens) noexcept
Corrupt the root page of the given table.
Definition: ut0test.cc:401
DISPATCH_FUNCTION(dblwr_force_crash)
Set the dblwr::Force_crash to the desired page.
void close_table(dict_table_t *table) noexcept
Close the given table.
Definition: ut0test.cc:602
std::pair< const std::string, Function_executor > Pair
Definition: ut0test.h:334
Tester() noexcept
Default constructor.
Definition: ut0test.cc:53
Ret_t find_ondisk_page_type(std::vector< std::string > &tokens) noexcept
Find the on-disk page type of the given page.
Definition: ut0test.cc:279
Ret_t corrupt_ondisk_page0(std::vector< std::string > &tokens) noexcept
Corrupt the first page of the given tablespace.
Definition: ut0test.cc:519
DISPATCH_FUNCTION(make_ondisk_root_page_zeroes)
Fill the root page of the given table with zeroes.
Ret_t find_tablespace_file_name(std::vector< std::string > &tokens) noexcept
Obtain the file name of the given tablespace.
Definition: ut0test.cc:350
Ret_t open_table(std::vector< std::string > &tokens) noexcept
Open the specified table.
Definition: ut0test.cc:174
void destroy() noexcept
Destroy the tester object.
Definition: ut0test.cc:614
THD * m_thd
Current thread object.
Definition: ut0test.h:323
Ret_t find_space_id(std::vector< std::string > &tokens) noexcept
Find the space_id of the given table.
Definition: ut0test.cc:199
std::string m_command
The latest command executed.
Definition: ut0test.h:331
const char * get_last_log() const noexcept
Get the last generated output.
Definition: ut0test.h:180
Ret_t find_flush_sync_lsn(std::vector< std::string > &tokens) noexcept
Find the flush sync lsn from the buffer pool module.
Definition: ut0test.cc:623
Ret_t find_root_page_no(std::vector< std::string > &tokens) noexcept
Find the root page of the given table.
Definition: ut0test.cc:226
void append_output(const std::string &log) noexcept
Append the given string to the output value of the interpreter.
Definition: ut0test.cc:697
DISPATCH_FUNCTION(make_page_dirty)
Make the page dirty.
Ret_t find_fil_page_lsn(std::vector< std::string > &tokens) noexcept
Find the FIL_PAGE_LSN of the given page.
Definition: ut0test.cc:253
std::map< std::string, Function_executor, std::less< std::string >, Allocator > m_dispatch
Mapping b/w the command name and the function to execute.
Definition: ut0test.h:339
void set_output(const std::ostringstream &sout) noexcept
Set the output value of the interpreter.
Definition: ut0test.cc:689
void update_thd_variable() noexcept
Let the thread-variable innodb_interpreter_output point to the current output.
Definition: ut0test.cc:681
Ret_t print_dblwr_has_encrypted_pages(std::vector< std::string > &tokens) noexcept
Print the page type of pages in dblwr file to server error log.
Definition: ut0test.cc:585
DISPATCH_FUNCTION(find_tablespace_physical_page_size)
Obtain the page size of the given tablespace.
Ret_t run(ulong cmd) noexcept
Run the given command.
void init() noexcept
Initialize the internal state of the tester.
Definition: ut0test.cc:73
dict_table_t * is_table_open(const std::string &table_name) const noexcept
Check if the given table is already opened.
Definition: ut0test.cc:161
Ret_t(Tester::*)(std::vector< std::string > &) Function_executor
Definition: ut0test.h:333
DISPATCH_FUNCTION(count_page_type)
Count various page_types for given tablespace.
Definition: system_variables_bits.h:94
void ib_interpreter_update(MYSQL_THD thd, SYS_VAR *var, void *var_ptr, const void *save)
Update the innodb_interpreter_output system variable to let the user access the output generated by t...
Definition: ut0test.cc:705
int ib_interpreter_check(THD *thd, SYS_VAR *var, void *save, struct st_mysql_value *value)
Check whether given command is valid for the InnoDB interpreter Refer to mysql_var_check_func() for m...
Definition: ut0test.cc:716
command
Definition: version_token.cc:280