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