1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include "mysqld.h"
24 #include "mysqld_daemon.h"
25 
26 #include <vector>
27 #include <algorithm>
28 #include <functional>
29 #include <list>
30 #include <set>
31 #include <string>
32 
33 #include <fenv.h>
34 #include <signal.h>
35 #ifdef HAVE_SYS_WAIT_H
36 #include <sys/wait.h>
37 #endif
38 #ifdef HAVE_PWD_H
39 #include <pwd.h>
40 #endif
41 #ifdef HAVE_GRP_H
42 #include <grp.h>
43 #endif
44 #ifdef HAVE_SYS_RESOURCE_H
45 #include <sys/resource.h>
46 #endif
47 #ifdef _WIN32
48 #include <crtdbg.h>
49 #endif
50 
51 #include <sys/types.h>
52 #ifdef HAVE_SYS_MMAN_H
53 #include <sys/mman.h>
54 #endif
55 
56 #include "sql_parse.h"    // test_if_data_home_dir
57 #include "sql_cache.h"    // query_cache, query_cache_*
58 #include "sql_locale.h"   // MY_LOCALES, my_locales, my_locale_by_name
59 #include "sql_show.h"     // free_status_vars, add_status_vars,
60                           // reset_status_vars
61 #include "strfunc.h"      // find_set_from_flags
62 #include "parse_file.h"   // File_parser_dummy_hook
63 #include "sql_db.h"       // my_dboptions_cache_free
64                           // my_dboptions_cache_init
65 #include "sql_table.h"    // release_ddl_log, execute_ddl_log_recovery
66 #include "sql_connect.h"  // free_max_user_conn, init_max_user_conn,
67                           // handle_one_connection
68 #include "sql_time.h"     // known_date_time_formats,
69                           // get_date_time_format_str
70 #include "tztime.h"       // my_tz_free, my_tz_init, my_tz_SYSTEM
71 #include "hostname.h"     // hostname_cache_free, hostname_cache_init
72 #include "auth_common.h"  // set_default_auth_plugin
73                           // acl_free, acl_init
74                           // grant_free, grant_init
75 #include "sql_base.h"     // table_def_free, table_def_init,
76                           // Table_cache,
77                           // cached_table_definitions
78 #include "sql_test.h"     // mysql_print_status
79 #include "item_create.h"  // item_create_cleanup, item_create_init
80 #include "sql_servers.h"  // servers_free, servers_init
81 #include "init.h"         // unireg_init
82 #include "derror.h"       // init_errmessage
83 #include "des_key_file.h" // load_des_key_file
84 #include "sql_manager.h"  // stop_handle_manager, start_handle_manager
85 #include "bootstrap.h"    // bootstrap
86 #include <m_ctype.h>
87 #include <my_dir.h>
88 #include <my_bit.h>
89 #include "rpl_gtid.h"
90 #include "rpl_gtid_persist.h"
91 #include "rpl_slave.h"
92 #include "rpl_msr.h"
93 #include "rpl_master.h"
94 #include "rpl_mi.h"
95 #include "rpl_filter.h"
96 #include <sql_common.h>
97 #include <my_stacktrace.h>
98 #include "mysqld_suffix.h"
99 #include "mysys_err.h"
100 #include "events.h"
101 #include "sql_audit.h"
102 #include "probes_mysql.h"
103 #include "debug_sync.h"
104 #ifdef WITH_WSREP
105 #include "wsrep_mysqld.h"
106 #include "wsrep_var.h"
107 #include "wsrep_thd.h"
108 #include "wsrep_sst.h"
109 #endif
110 #include "sql_callback.h"
111 #include "opt_trace_context.h"
112 #include "opt_costconstantcache.h"
113 #include "sql_plugin.h"                         // plugin_shutdown
114 #include "sql_initialize.h"
115 #include "log_event.h"
116 #include "log.h"
117 #include "binlog.h"
118 #include "rpl_rli.h"     // Relay_log_info
119 #include "replication.h" // thd_enter_cond
120 
121 #include "my_default.h"
122 #include "mysql_version.h"
123 
124 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
125 #include "../storage/perfschema/pfs_server.h"
126 #include <pfs_idle_provider.h>
127 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
128 
129 #include "pfs_file_provider.h"
130 #include "mysql/psi/mysql_file.h"
131 
132 #include <mysql/psi/mysql_idle.h>
133 #include <mysql/psi/mysql_socket.h>
134 #include <mysql/psi/mysql_memory.h>
135 #include <mysql/psi/mysql_statement.h>
136 
137 #include "migrate_keyring.h"            // Migrate_keyring
138 #include "mysql_com_server.h"
139 #include "keycaches.h"
140 #include "../storage/myisam/ha_myisam.h"
141 #include "set_var.h"
142 #include "sys_vars_shared.h"
143 #include "rpl_injector.h"
144 #include "rpl_handler.h"
145 #include <ft_global.h>
146 #include <errmsg.h>
147 #include "sp_rcontext.h"
148 #include "sql_reload.h"  // reload_acl_and_cache
149 #include "sp_head.h"  // init_sp_psi_keys
150 #include "event_data_objects.h" //init_scheduler_psi_keys
151 #include "my_timer.h"    // my_timer_init, my_timer_deinit
152 #include "table_cache.h"                // table_cache_manager
153 #include "connection_acceptor.h"        // Connection_acceptor
154 #include "connection_handler_impl.h"    // *_connection_handler
155 #include "connection_handler_manager.h" // Connection_handler_manager
156 #include "socket_connection.h"          // Mysqld_socket_listener
157 #include "mysqld_thd_manager.h"         // Global_THD_manager
158 #include "my_getopt.h"
159 #include "partitioning/partition_handler.h" // partitioning_init
160 #include "item_cmpfunc.h"               // arg_cmp_func
161 #include "item_strfunc.h"               // Item_func_uuid
162 #include "handler.h"
163 
164 #ifndef EMBEDDED_LIBRARY
165 #include "srv_session.h"
166 #endif
167 
168 #ifdef _WIN32
169 #include "named_pipe.h"
170 #include "named_pipe_connection.h"
171 #include "shared_memory_connection.h"
172 #endif
173 
174 using std::min;
175 using std::max;
176 using std::vector;
177 
178 #define mysqld_charset &my_charset_latin1
179 
180 #ifdef HAVE_FPU_CONTROL_H
181 # include <fpu_control.h>
182 #elif defined(__i386__)
183 # define fpu_control_t unsigned int
184 # define _FPU_EXTENDED 0x300
185 # define _FPU_DOUBLE 0x200
186 # if defined(__GNUC__) || defined(__SUNPRO_CC)
187 #  define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
188 #  define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
189 # else
190 #  define _FPU_GETCW(cw) (cw= 0)
191 #  define _FPU_SETCW(cw)
192 # endif
193 #endif
194 
setup_fpu()195 inline void setup_fpu()
196 {
197 #ifdef HAVE_FEDISABLEEXCEPT
198   fedisableexcept(FE_ALL_EXCEPT);
199 #endif
200 
201   /* Set FPU rounding mode to "round-to-nearest" */
202   fesetround(FE_TONEAREST);
203 
204   /*
205     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
206     (double precision) for portable results of floating point operations.
207     However, there is no need to do so if compiler is using SSE2 for floating
208     point, double values will be stored and processed in 64 bits anyway.
209   */
210 #if defined(__i386__) && !defined(__SSE2_MATH__)
211 #if defined(_WIN32)
212 #if !defined(_WIN64)
213   _control87(_PC_53, MCW_PC);
214 #endif /* !_WIN64 */
215 #else /* !_WIN32 */
216   fpu_control_t cw;
217   _FPU_GETCW(cw);
218   cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
219   _FPU_SETCW(cw);
220 #endif /* _WIN32 && */
221 #endif /* __i386__ */
222 
223 }
224 
225 #ifndef EMBEDDED_LIBRARY
226 extern "C" void handle_fatal_signal(int sig);
227 #endif
228 
229 /* Constants */
230 
231 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
232 
233 const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
234 
235 static const char *tc_heuristic_recover_names[]=
236 {
237   "OFF", "COMMIT", "ROLLBACK", NullS
238 };
239 static TYPELIB tc_heuristic_recover_typelib=
240 {
241   array_elements(tc_heuristic_recover_names)-1,"",
242   tc_heuristic_recover_names, NULL
243 };
244 
245 const char *first_keyword= "first", *binary_keyword= "BINARY";
246 const char *my_localhost= "localhost";
247 
248 bool opt_large_files= sizeof(my_off_t) > 4;
249 static my_bool opt_autocommit; ///< for --autocommit command-line option
250 
251 /*
252   Used with --help for detailed option
253 */
254 my_bool opt_help= 0, opt_verbose= 0;
255 
256 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
257 {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
258  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
259  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
260  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
261  {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
262 
263 #ifdef HAVE_PSI_INTERFACE
264 #ifndef EMBEDDED_LIBRARY
265 #if defined(_WIN32)
266 static PSI_thread_key key_thread_handle_con_namedpipes;
267 static PSI_thread_key key_thread_handle_con_sharedmem;
268 static PSI_thread_key key_thread_handle_con_sockets;
269 static PSI_mutex_key key_LOCK_handler_count;
270 static PSI_cond_key key_COND_handler_count;
271 static PSI_thread_key key_thread_handle_shutdown;
272 static PSI_rwlock_key key_rwlock_LOCK_named_pipe_full_access_group;
273 #else
274 static PSI_mutex_key key_LOCK_socket_listener_active;
275 static PSI_cond_key key_COND_socket_listener_active;
276 static PSI_mutex_key key_LOCK_start_signal_handler;
277 static PSI_cond_key key_COND_start_signal_handler;
278 #ifdef WITH_WSREP
279 PSI_thread_key key_thread_handle_wsrep;
280 #endif /* WITH_WSREP */
281 #endif // _WIN32
282 #endif // !EMBEDDED_LIBRARY
283 #endif /* HAVE_PSI_INTERFACE */
284 
285 /**
286   Statement instrumentation key for replication.
287 */
288 #ifdef HAVE_PSI_STATEMENT_INTERFACE
289 PSI_statement_info stmt_info_rpl;
290 #endif
291 
292 /* the default log output is log tables */
293 static bool lower_case_table_names_used= 0;
294 #if !defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
295 static bool socket_listener_active= false;
296 static int pipe_write_fd= -1;
297 static my_bool opt_daemonize= 0;
298 #endif
299 static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
300 static my_bool opt_short_log_format= 0;
301 static char *mysqld_user, *mysqld_chroot;
302 static char *default_character_set_name;
303 static char *character_set_filesystem_name;
304 static char *lc_messages;
305 static char *lc_time_names_name;
306 char *my_bind_addr_str;
307 static char *default_collation_name;
308 char *default_storage_engine;
309 char *default_tmp_storage_engine;
310 /**
311    Use to mark which engine should be choosen to create internal
312    temp table
313  */
314 ulong internal_tmp_disk_storage_engine;
315 static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
316 static bool binlog_format_used= false;
317 
318 LEX_STRING opt_init_connect, opt_init_slave;
319 
320 /* Global variables */
321 
322 bool opt_bin_log, opt_ignore_builtin_innodb= 0;
323 bool opt_general_log, opt_slow_log, opt_general_log_raw;
324 ulonglong log_output_options;
325 my_bool opt_log_queries_not_using_indexes= 0;
326 ulong opt_log_throttle_queries_not_using_indexes= 0;
327 bool opt_disable_networking=0, opt_skip_show_db=0;
328 bool opt_skip_name_resolve=0;
329 my_bool opt_character_set_client_handshake= 1;
330 bool server_id_supplied = false;
331 bool opt_endinfo, using_udf_functions;
332 my_bool locked_in_memory;
333 bool opt_using_transactions;
334 bool volatile abort_loop;
335 ulong opt_tc_log_size;
336 
337 static enum_server_operational_state server_operational_state= SERVER_BOOTING;
338 ulong log_warnings;
339 bool  opt_log_syslog_enable;
340 char *opt_log_syslog_tag= NULL;
341 char *opt_keyring_migration_user= NULL;
342 char *opt_keyring_migration_host= NULL;
343 char *opt_keyring_migration_password= NULL;
344 char *opt_keyring_migration_socket= NULL;
345 char *opt_keyring_migration_source= NULL;
346 char *opt_keyring_migration_destination= NULL;
347 ulong opt_keyring_migration_port= 0;
348 bool migrate_connect_options= 0;
349 #ifndef _WIN32
350 bool  opt_log_syslog_include_pid;
351 char *opt_log_syslog_facility;
352 
353 #else
354 /*
355   Thread handle of shutdown event handler thread.
356   It is used as argument during thread join.
357 */
358 my_thread_handle shutdown_thr_handle;
359 #endif
360 uint host_cache_size;
361 ulong log_error_verbosity= 3; // have a non-zero value during early start-up
362 
363 #if MYSQL_VERSION_ID >= 50800
364 #error "show_compatibility_56 is to be removed in MySQL 5.8"
365 #else
366 /*
367   Default value TRUE for the EMBEDDED_LIBRARY,
368   default value from Sys_show_compatibility_56 otherwise.
369 */
370 my_bool show_compatibility_56= TRUE;
371 #endif /* MYSQL_VERSION_ID >= 50800 */
372 
373 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
374 ulong slow_start_timeout;
375 #endif
376 
377 my_bool opt_bootstrap= 0;
378 my_bool opt_initialize= 0;
379 my_bool opt_disable_partition_check= TRUE;
380 my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
381 my_bool opt_reckless_slave = 0;
382 my_bool opt_enable_named_pipe= 0;
383 my_bool opt_local_infile, opt_slave_compressed_protocol;
384 my_bool opt_safe_user_create = 0;
385 my_bool opt_show_slave_auth_info;
386 my_bool opt_log_slave_updates= 0;
387 char *opt_slave_skip_errors;
388 my_bool opt_slave_allow_batching= 0;
389 
390 /**
391   compatibility option:
392     - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
393 */
394 my_bool old_mode;
395 
396 /*
397   Legacy global handlerton. These will be removed (please do not add more).
398 */
399 handlerton *heap_hton;
400 handlerton *myisam_hton;
401 handlerton *innodb_hton;
402 
403 char *opt_disabled_storage_engines;
404 uint opt_server_id_bits= 0;
405 ulong opt_server_id_mask= 0;
406 my_bool read_only= 0, opt_readonly= 0;
407 my_bool super_read_only= 0, opt_super_readonly= 0;
408 my_bool opt_require_secure_transport= 0;
409 my_bool use_temp_pool, relay_log_purge;
410 my_bool relay_log_recovery;
411 my_bool opt_sync_frm, opt_allow_suspicious_udfs;
412 my_bool opt_secure_auth= 0;
413 char* opt_secure_file_priv;
414 my_bool opt_log_slow_admin_statements= 0;
415 my_bool opt_log_slow_slave_statements= 0;
416 my_bool lower_case_file_system= 0;
417 my_bool opt_large_pages= 0;
418 my_bool opt_super_large_pages= 0;
419 my_bool opt_myisam_use_mmap= 0;
420 my_bool offline_mode= 0;
421 my_bool opt_log_builtin_as_identified_by_password= 0;
422 uint   opt_large_page_size= 0;
423 uint default_password_lifetime= 0;
424 
425 mysql_mutex_t LOCK_default_password_lifetime;
426 
427 #if defined(ENABLED_DEBUG_SYNC)
428 MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
429 #endif /* defined(ENABLED_DEBUG_SYNC) */
430 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
431 my_bool check_proxy_users= 0, mysql_native_password_proxy_users= 0, sha256_password_proxy_users= 0;
432 /*
433   True if there is at least one per-hour limit for some user, so we should
434   check them before each query (and possibly reset counters when hour is
435   changed). False otherwise.
436 */
437 volatile bool mqh_used = 0;
438 my_bool opt_noacl= 0;
439 my_bool sp_automatic_privileges= 1;
440 
441 ulong opt_binlog_rows_event_max_size;
442 const char *binlog_checksum_default= "NONE";
443 ulong binlog_checksum_options;
444 my_bool opt_master_verify_checksum= 0;
445 my_bool opt_slave_sql_verify_checksum= 1;
446 const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
447 #ifdef WITH_WSREP
448 const char *wsrep_binlog_format_names[]=
449                                    {"MIXED", "STATEMENT", "ROW", "NONE", NullS};
450 #endif /*WITH_WSREP */
451 my_bool binlog_gtid_simple_recovery;
452 ulong binlog_error_action;
453 const char *binlog_error_action_list[]= {"IGNORE_ERROR", "ABORT_SERVER", NullS};
454 uint32 gtid_executed_compression_period= 0;
455 my_bool opt_log_unsafe_statements;
456 
457 #ifdef HAVE_INITGROUPS
458 volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
459 #endif
460 const char *timestamp_type_names[]= {"UTC", "SYSTEM", NullS};
461 ulong opt_log_timestamps;
462 uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
463 uint mysqld_port_timeout;
464 ulong delay_key_write_options;
465 uint protocol_version;
466 uint lower_case_table_names;
467 long tc_heuristic_recover;
468 ulong back_log, connect_timeout, server_id;
469 ulong table_cache_size, table_def_size;
470 ulong table_cache_instances;
471 ulong table_cache_size_per_instance;
472 ulong what_to_log;
473 ulong slow_launch_time;
474 Atomic_int32 slave_open_temp_tables;
475 ulong open_files_limit, max_binlog_size, max_relay_log_size;
476 ulong slave_trans_retries;
477 uint  slave_net_timeout;
478 ulong slave_exec_mode_options;
479 ulonglong slave_type_conversions_options;
480 ulong opt_mts_slave_parallel_workers;
481 ulonglong opt_mts_pending_jobs_size_max;
482 ulonglong slave_rows_search_algorithms_options;
483 
484 #ifdef HAVE_REPLICATION
485 my_bool opt_slave_preserve_commit_order;
486 #endif
487 
488 #ifndef NDEBUG
489 uint slave_rows_last_search_algorithm_used;
490 #endif
491 ulong mts_parallel_option;
492 ulong binlog_cache_size=0;
493 ulonglong  max_binlog_cache_size=0;
494 ulong slave_max_allowed_packet= 0;
495 ulong binlog_stmt_cache_size=0;
496 int32 opt_binlog_max_flush_queue_time= 0;
497 long opt_binlog_group_commit_sync_delay= 0;
498 ulong opt_binlog_group_commit_sync_no_delay_count= 0;
499 ulonglong  max_binlog_stmt_cache_size=0;
500 ulong query_cache_size=0;
501 ulong refresh_version;  /* Increments on each reload */
502 query_id_t global_query_id;
503 ulong aborted_threads;
504 ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
505 ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
506 ulong delayed_insert_errors,flush_time;
507 ulong specialflag=0;
508 ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
509 ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
510 ulong max_connections, max_connect_errors;
511 ulong rpl_stop_slave_timeout= LONG_TIMEOUT;
512 my_bool log_bin_use_v1_row_events= 0;
513 bool thread_cache_size_specified= false;
514 bool host_cache_size_specified= false;
515 bool table_definition_cache_specified= false;
516 ulong locked_account_connection_count= 0;
517 bool opt_keyring_operations= TRUE;
518 
519 /**
520   Limit of the total number of prepared statements in the server.
521   Is necessary to protect the server against out-of-memory attacks.
522 */
523 ulong max_prepared_stmt_count;
524 /**
525   Current total number of prepared statements in the server. This number
526   is exact, and therefore may not be equal to the difference between
527   `com_stmt_prepare' and `com_stmt_close' (global status variables), as
528   the latter ones account for all registered attempts to prepare
529   a statement (including unsuccessful ones).  Prepared statements are
530   currently connection-local: if the same SQL query text is prepared in
531   two different connections, this counts as two distinct prepared
532   statements.
533 */
534 ulong prepared_stmt_count=0;
535 ulong current_pid;
536 uint sync_binlog_period= 0, sync_relaylog_period= 0,
537      sync_relayloginfo_period= 0, sync_masterinfo_period= 0,
538      opt_mts_checkpoint_period, opt_mts_checkpoint_group;
539 ulong expire_logs_days = 0;
540 /**
541   Soft upper limit for number of sp_head objects that can be stored
542   in the sp_cache for one connection.
543 */
544 ulong stored_program_cache_size= 0;
545 /**
546   Compatibility option to prevent auto upgrade of old temporals
547   during certain ALTER TABLE operations.
548 */
549 my_bool avoid_temporal_upgrade;
550 
551 const double log_10[] = {
552   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
553   1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
554   1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
555   1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
556   1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
557   1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
558   1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
559   1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
560   1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
561   1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
562   1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
563   1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
564   1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
565   1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
566   1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
567   1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
568   1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
569   1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
570   1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
571   1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
572   1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
573   1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
574   1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
575   1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
576   1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
577   1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
578   1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
579   1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
580   1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
581   1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
582   1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
583 };
584 
585 time_t server_start_time, flush_status_time;
586 
587 char server_uuid[UUID_LENGTH+1];
588 const char *server_uuid_ptr;
589 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
590 char default_logfile_name[FN_REFLEN];
591 char *default_tz_name;
592 static char errorlog_filename_buff[FN_REFLEN];
593 const char *log_error_dest;
594 char glob_hostname[FN_REFLEN];
595 char mysql_real_data_home[FN_REFLEN],
596      lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
597      mysql_charsets_dir[FN_REFLEN],
598      *opt_init_file, *opt_tc_log_file;
599 char *lc_messages_dir_ptr;
600 char mysql_unpacked_real_data_home[FN_REFLEN];
601 size_t mysql_unpacked_real_data_home_len;
602 size_t mysql_real_data_home_len, mysql_data_home_len= 1;
603 uint reg_ext_length;
604 const key_map key_map_empty(0);
605 key_map key_map_full(0);                        // Will be initialized later
606 char logname_path[FN_REFLEN];
607 char slow_logname_path[FN_REFLEN];
608 char secure_file_real_path[FN_REFLEN];
609 
610 Date_time_format global_date_format, global_datetime_format, global_time_format;
611 Time_zone *default_tz;
612 
613 char *mysql_data_home= const_cast<char*>(".");
614 const char *mysql_real_data_home_ptr= mysql_real_data_home;
615 char server_version[SERVER_VERSION_LENGTH];
616 char *mysqld_unix_port, *opt_mysql_tmpdir;
617 
618 /** name of reference on left expression in rewritten IN subquery */
619 const char *in_left_expr_name= "<left expr>";
620 /** name of additional condition */
621 const char *in_additional_cond= "<IN COND>";
622 const char *in_having_cond= "<IN HAVING>";
623 
624 my_decimal decimal_zero;
625 #ifndef EMBEDDED_LIBRARY
626 /** Number of connection errors from internal server errors. */
627 ulong connection_errors_internal= 0;
628 /** Number of errors when reading the peer address. */
629 ulong connection_errors_peer_addr= 0;
630 #endif
631 
632 /* classes for comparation parsing/processing */
633 Eq_creator eq_creator;
634 Ne_creator ne_creator;
635 Equal_creator equal_creator;
636 Gt_creator gt_creator;
637 Lt_creator lt_creator;
638 Ge_creator ge_creator;
639 Le_creator le_creator;
640 
641 Rpl_filter* rpl_filter;
642 Rpl_filter* binlog_filter;
643 
644 struct system_variables global_system_variables;
645 struct system_variables max_system_variables;
646 struct system_status_var global_status_var;
647 
648 MY_TMPDIR mysql_tmpdir_list;
649 MY_BITMAP temp_pool;
650 
651 CHARSET_INFO *system_charset_info, *files_charset_info ;
652 CHARSET_INFO *national_charset_info, *table_alias_charset;
653 CHARSET_INFO *character_set_filesystem;
654 CHARSET_INFO *error_message_charset_info;
655 
656 MY_LOCALE *my_default_lc_messages;
657 MY_LOCALE *my_default_lc_time_names;
658 
659 SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
660 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
661 SHOW_COMP_OPTION have_crypt, have_compress;
662 SHOW_COMP_OPTION have_profiling;
663 SHOW_COMP_OPTION have_statement_timeout= SHOW_OPTION_DISABLED;
664 
665 /* Thread specific variables */
666 
667 thread_local_key_t THR_MALLOC;
668 bool THR_MALLOC_initialized= false;
669 thread_local_key_t THR_THD;
670 bool THR_THD_initialized= false;
671 mysql_mutex_t
672   LOCK_status, LOCK_uuid_generator,
673   LOCK_crypt,
674   LOCK_global_system_variables,
675   LOCK_user_conn, LOCK_slave_list,
676   LOCK_error_messages;
677 mysql_mutex_t LOCK_sql_rand;
678 
679 /**
680   The below lock protects access to two global server variables:
681   max_prepared_stmt_count and prepared_stmt_count. These variables
682   set the limit and hold the current total number of prepared statements
683   in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
684   server may be fairly high, we need a dedicated lock.
685 */
686 mysql_mutex_t LOCK_prepared_stmt_count;
687 
688 /*
689  The below two locks are introudced as guards (second mutex) for
690   the global variables sql_slave_skip_counter and slave_net_timeout
691   respectively. See fix_slave_skip_counter/fix_slave_net_timeout
692   for more details
693 */
694 mysql_mutex_t LOCK_sql_slave_skip_counter;
695 mysql_mutex_t LOCK_slave_net_timeout;
696 mysql_mutex_t LOCK_slave_trans_dep_tracker;
697 mysql_mutex_t LOCK_log_throttle_qni;
698 mysql_mutex_t LOCK_offline_mode;
699 #ifdef HAVE_OPENSSL
700 mysql_mutex_t LOCK_des_key_file;
701 #endif
702 mysql_rwlock_t LOCK_sys_init_connect, LOCK_sys_init_slave;
703 mysql_rwlock_t LOCK_system_variables_hash;
704 my_thread_handle signal_thread_id;
705 my_thread_attr_t connection_attrib;
706 mysql_mutex_t LOCK_server_started;
707 mysql_cond_t COND_server_started;
708 mysql_mutex_t LOCK_reset_gtid_table;
709 mysql_mutex_t LOCK_compress_gtid_table;
710 mysql_cond_t COND_compress_gtid_table;
711 #if !defined (EMBEDDED_LIBRARY) && !defined(_WIN32)
712 mysql_mutex_t LOCK_socket_listener_active;
713 mysql_cond_t COND_socket_listener_active;
714 mysql_mutex_t LOCK_start_signal_handler;
715 mysql_cond_t COND_start_signal_handler;
716 #endif
717 #ifdef WITH_WSREP
718 mysql_mutex_t LOCK_wsrep_ready;
719 mysql_cond_t  COND_wsrep_ready;
720 mysql_mutex_t LOCK_wsrep_sst;
721 mysql_cond_t  COND_wsrep_sst;
722 mysql_mutex_t LOCK_wsrep_sst_init;
723 mysql_cond_t  COND_wsrep_sst_init;
724 mysql_mutex_t LOCK_wsrep_rollback;
725 mysql_cond_t  COND_wsrep_rollback;
726 wsrep_aborting_thd_t wsrep_aborting_thd= NULL;
727 mysql_mutex_t LOCK_wsrep_replaying;
728 mysql_cond_t  COND_wsrep_replaying;
729 mysql_mutex_t LOCK_wsrep_slave_threads;
730 mysql_mutex_t LOCK_wsrep_desync;
731 int wsrep_replaying= 0;
732 ulong wsrep_running_threads = 0; // # of currently running wsrep threads
733 static void wsrep_close_threads(THD* thd);
734 int mysqld_server_initialized= 0;
735 #endif /* WITH_WSREP */
736 
737 bool mysqld_server_started= false;
738 
739 /*
740   The below lock protects access to global server variable
741   keyring_operations.
742 */
743 mysql_mutex_t LOCK_keyring_operations;
744 
745 File_parser_dummy_hook file_parser_dummy_hook;
746 
747 /* replication parameters, if master_host is not NULL, we are a slave */
748 uint report_port= 0;
749 ulong master_retry_count=0;
750 char *master_info_file;
751 char *relay_log_info_file, *report_user, *report_password, *report_host;
752 char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
753 char *opt_general_logname, *opt_slow_logname, *opt_bin_logname;
754 
755 /* Static variables */
756 
757 static volatile sig_atomic_t kill_in_progress;
758 
759 static my_bool opt_myisam_log;
760 static int cleanup_done;
761 static ulong opt_specialflag;
762 static char *opt_update_logname;
763 char *opt_binlog_index_name;
764 char *mysql_home_ptr, *pidfile_name_ptr;
765 char *default_auth_plugin;
766 /** Initial command line arguments (count), after load_defaults().*/
767 static int defaults_argc;
768 /**
769   Initial command line arguments (arguments), after load_defaults().
770   This memory is allocated by @c load_defaults() and should be freed
771   using @c free_defaults().
772   Do not modify defaults_argc / defaults_argv,
773   use remaining_argc / remaining_argv instead to parse the command
774   line arguments in multiple steps.
775 */
776 static char **defaults_argv;
777 /** Remaining command line arguments (count), filtered by handle_options().*/
778 static int remaining_argc;
779 /** Remaining command line arguments (arguments), filtered by handle_options().*/
780 static char **remaining_argv;
781 
782 int orig_argc;
783 char **orig_argv;
784 
785 #if defined(HAVE_OPENSSL)
786 bool init_rsa_keys(void);
787 void deinit_rsa_keys(void);
788 int show_rsa_public_key(THD *thd, SHOW_VAR *var, char *buff);
789 #endif
790 
791 Connection_acceptor<Mysqld_socket_listener> *mysqld_socket_acceptor= NULL;
792 #ifdef _WIN32
793 static Named_pipe_listener *named_pipe_listener= NULL;
794 Connection_acceptor<Named_pipe_listener> *named_pipe_acceptor= NULL;
795 Connection_acceptor<Shared_mem_listener> *shared_mem_acceptor= NULL;
796 mysql_rwlock_t LOCK_named_pipe_full_access_group;
797 char *named_pipe_full_access_group;
798 #endif
799 
800 Checkable_rwlock *global_sid_lock= NULL;
801 Sid_map *global_sid_map= NULL;
802 Gtid_state *gtid_state= NULL;
803 Gtid_table_persistor *gtid_table_persistor= NULL;
804 
805 
set_remaining_args(int argc,char ** argv)806 void set_remaining_args(int argc, char **argv)
807 {
808   remaining_argc= argc;
809   remaining_argv= argv;
810 }
811 /*
812   Multiple threads of execution use the random state maintained in global
813   sql_rand to generate random numbers. sql_rnd_with_mutex use mutex
814   LOCK_sql_rand to protect sql_rand across multiple instantiations that use
815   sql_rand to generate random numbers.
816  */
sql_rnd_with_mutex()817 ulong sql_rnd_with_mutex()
818 {
819   mysql_mutex_lock(&LOCK_sql_rand);
820   ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
821   mysql_mutex_unlock(&LOCK_sql_rand);
822   return tmp;
823 }
824 
825 
826 C_MODE_START
827 
option_error_reporter(enum loglevel level,const char * format,...)828 static void option_error_reporter(enum loglevel level, const char *format, ...)
829 {
830   va_list args;
831   va_start(args, format);
832 
833   /* Don't print warnings for --loose options during bootstrap */
834   if (level == ERROR_LEVEL || !opt_bootstrap ||
835       (log_error_verbosity > 1))
836   {
837     error_log_print(level, format, args);
838   }
839   va_end(args);
840 }
841 
842 /**
843   Character set and collation error reporter that prints to sql error log.
844   @param level          log message level
845   @param format         log message format string
846 
847   This routine is used to print character set and collation
848   warnings and errors inside an already running mysqld server,
849   e.g. when a character set or collation is requested for the very first time
850   and its initialization does not go well for some reasons.
851 */
charset_error_reporter(enum loglevel level,const char * format,...)852 static void charset_error_reporter(enum loglevel level,
853                                    const char *format, ...)
854 {
855   va_list args;
856   va_start(args, format);
857   error_log_print(level, format, args);
858   va_end(args);
859 }
860 C_MODE_END
861 
862 struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
863 
864 #ifndef EMBEDDED_LIBRARY
865 struct passwd *user_info= NULL;
866 #ifndef _WIN32
867 static my_thread_t main_thread_id;
868 #endif // !_WIN32
869 #endif // !EMBEDDED_LIBRARY
870 
871 /* OS specific variables */
872 
873 #ifdef _WIN32
874 #include <process.h>
875 
876 static bool windows_service= false;
877 static bool use_opt_args;
878 static int opt_argc;
879 static char **opt_argv;
880 
881 #if !defined(EMBEDDED_LIBRARY)
882 static mysql_mutex_t LOCK_handler_count;
883 static mysql_cond_t COND_handler_count;
884 static HANDLE hEventShutdown;
885 char *shared_memory_base_name= default_shared_memory_base_name;
886 my_bool opt_enable_shared_memory;
887 static char shutdown_event_name[40];
888 #include "nt_servc.h"
889 static   NTService  Service;        ///< Service object for WinNT
890 #endif /* EMBEDDED_LIBRARY */
891 #endif /* _WIN32 */
892 
893 #ifndef EMBEDDED_LIBRARY
894 bool mysqld_embedded=0;
895 #else
896 bool mysqld_embedded=1;
897 #endif
898 
899 static my_bool plugins_are_initialized= FALSE;
900 
901 #ifndef NDEBUG
902 static const char* default_dbug_option;
903 #endif
904 ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
905 Query_cache query_cache;
906 
907 my_bool opt_use_ssl= 1;
908 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
909      *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL,
910      *opt_ssl_crlpath= NULL, *opt_tls_version= NULL;
911 
912 #ifdef HAVE_OPENSSL
913 char *des_key_file;
914 #ifndef EMBEDDED_LIBRARY
915 struct st_VioSSLFd *ssl_acceptor_fd;
916 SSL *ssl_acceptor;
917 #endif
918 #endif /* HAVE_OPENSSL */
919 
920 /* Function declarations */
921 
922 extern "C" void *signal_hand(void *arg);
923 static int mysql_init_variables(void);
924 static int get_options(int *argc_ptr, char ***argv_ptr);
925 static void add_terminator(vector<my_option> *options);
926 extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
927 static void set_server_version(void);
928 static int init_thread_environment();
929 static char *get_relative_path(const char *path);
930 static int fix_paths(void);
931 static bool read_init_file(char *file_name);
932 static void clean_up(bool print_message);
933 static int test_if_case_insensitive(const char *dir_name);
934 static void end_ssl();
935 static void start_processing_signals();
936 
937 #ifndef EMBEDDED_LIBRARY
938 static bool pid_file_created= false;
939 static void usage(void);
940 static void clean_up_mutexes(void);
941 static void create_pid_file();
942 static void mysqld_exit(int exit_code) MY_ATTRIBUTE((noreturn));
943 static void delete_pid_file(myf flags);
944 #endif
945 
946 
947 #ifndef EMBEDDED_LIBRARY
948 /****************************************************************************
949 ** Code to end mysqld
950 ****************************************************************************/
951 
952 /**
953   This class implements callback function used by close_connections()
954   to set KILL_CONNECTION flag on all thds in thd list.
955   If m_kill_dump_thread_flag is not set it kills all other threads
956   except dump threads. If this flag is set, it kills dump threads.
957 */
958 class Set_kill_conn : public Do_THD_Impl
959 {
960 private:
961   int m_dump_thread_count;
962   bool m_kill_dump_threads_flag;
963 public:
Set_kill_conn()964   Set_kill_conn()
965     : m_dump_thread_count(0),
966       m_kill_dump_threads_flag(false)
967   {}
968 
set_dump_thread_flag()969   void set_dump_thread_flag()
970   {
971     m_kill_dump_threads_flag= true;
972   }
973 
get_dump_thread_count() const974   int get_dump_thread_count() const
975   {
976     return m_dump_thread_count;
977   }
978 
operator ()(THD * killing_thd)979   virtual void operator()(THD *killing_thd)
980   {
981     DBUG_PRINT("quit",("Informing thread %u that it's time to die",
982                        killing_thd->thread_id()));
983     if (!m_kill_dump_threads_flag)
984     {
985       // We skip slave threads & scheduler on this first loop through.
986       if (killing_thd->slave_thread)
987         return;
988 #ifdef WITH_WSREP
989     /* skip wsrep system threads as well */
990       if (WSREP(killing_thd) &&
991           (killing_thd->wsrep_exec_mode==REPL_RECV || killing_thd->wsrep_applier))
992         return;
993 #endif /* WITH_WSREP */
994 
995       if (killing_thd->get_command() == COM_BINLOG_DUMP ||
996           killing_thd->get_command() == COM_BINLOG_DUMP_GTID)
997       {
998         ++m_dump_thread_count;
999         return;
1000       }
1001       DBUG_EXECUTE_IF("Check_dump_thread_is_alive",
1002                       {
1003                         assert(killing_thd->get_command() != COM_BINLOG_DUMP &&
1004                                killing_thd->get_command() != COM_BINLOG_DUMP_GTID);
1005                       };);
1006     }
1007     mysql_mutex_lock(&killing_thd->LOCK_thd_data);
1008     killing_thd->killed= THD::KILL_CONNECTION;
1009     MYSQL_CALLBACK(Connection_handler_manager::event_functions,
1010                    post_kill_notification, (killing_thd));
1011     if (killing_thd->is_killable)
1012     {
1013       mysql_mutex_lock(&killing_thd->LOCK_current_cond);
1014       if (killing_thd->current_cond)
1015       {
1016         mysql_mutex_lock(killing_thd->current_mutex);
1017         mysql_cond_broadcast(killing_thd->current_cond);
1018         mysql_mutex_unlock(killing_thd->current_mutex);
1019       }
1020       mysql_mutex_unlock(&killing_thd->LOCK_current_cond);
1021     }
1022     mysql_mutex_unlock(&killing_thd->LOCK_thd_data);
1023   }
1024 };
1025 
1026 /**
1027   This class implements callback function used by close_connections()
1028   to close vio connection for all thds in thd list
1029 */
1030 class Call_close_conn : public Do_THD_Impl
1031 {
1032 public:
Call_close_conn(bool server_shutdown)1033   Call_close_conn(bool server_shutdown) : is_server_shutdown(server_shutdown)
1034   {}
1035 
operator ()(THD * closing_thd)1036   virtual void operator()(THD *closing_thd)
1037   {
1038     if (closing_thd->get_protocol()->connection_alive())
1039     {
1040       LEX_CSTRING main_sctx_user= closing_thd->m_main_security_ctx.user();
1041       sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1042                         closing_thd->thread_id(),
1043                         (main_sctx_user.length ? main_sctx_user.str : ""));
1044       /*
1045         Do not generate MYSQL_AUDIT_CONNECTION_DISCONNECT event, when closing
1046         thread close sessions. Each session will generate DISCONNECT event by
1047         itself.
1048       */
1049       close_connection(closing_thd, 0, is_server_shutdown, false);
1050     }
1051 #ifdef WITH_WSREP
1052     /*
1053      * TODO: this code block may turn out redundant. wsrep->disconnect()
1054      *       should terminate slave threads gracefully, and we don't need
1055      *       to signal them here.
1056      *       The code here makes sure mysqld will not hang during shutdown
1057      *       even if wsrep provider has problems in shutting down.
1058      */
1059     if (WSREP(closing_thd) && closing_thd->wsrep_exec_mode==REPL_RECV)
1060     {
1061       sql_print_information("closing wsrep system thread");
1062 
1063       mysql_mutex_lock(&closing_thd->LOCK_thd_data);
1064       closing_thd->killed= THD::KILL_CONNECTION;
1065       if (closing_thd->current_cond)
1066       {
1067         mysql_mutex_lock(closing_thd->current_mutex);
1068         mysql_cond_broadcast(closing_thd->current_cond);
1069         mysql_mutex_unlock(closing_thd->current_mutex);
1070       }
1071       mysql_mutex_unlock(&closing_thd->LOCK_thd_data);
1072     }
1073 #endif /* WITH_WSREP */
1074   }
1075 private:
1076   bool is_server_shutdown;
1077 };
1078 
1079 #ifdef WITH_WSREP
1080 /**
1081   This class implements callback function used by close_connections()
1082   to set KILL_CONNECTION flag on all thds in thd list.
1083   If m_kill_dump_thread_flag is not set it kills all other threads
1084   except dump threads. If this flag is set, it kills dump threads.
1085 */
1086 class Set_wsrep_kill_conn : public Do_THD_Impl
1087 {
1088 private:
1089   int m_dump_thread_count;
1090   bool m_kill_dump_threads_flag;
1091 public:
Set_wsrep_kill_conn()1092   Set_wsrep_kill_conn()
1093     : m_dump_thread_count(0),
1094       m_kill_dump_threads_flag(false)
1095   {}
1096 
set_dump_thread_flag()1097   void set_dump_thread_flag()
1098   {
1099     m_kill_dump_threads_flag= true;
1100   }
1101 
get_dump_thread_count() const1102   int get_dump_thread_count() const
1103   {
1104     return m_dump_thread_count;
1105   }
1106 
operator ()(THD * killing_thd)1107   virtual void operator()(THD *killing_thd)
1108   {
1109     DBUG_PRINT("quit",("Informing thread %u that it's time to die",
1110                        killing_thd->thread_id()));
1111     if (!m_kill_dump_threads_flag)
1112     {
1113       // We skip slave threads & scheduler on this first loop through.
1114       if (killing_thd->slave_thread)
1115         return;
1116     /* skip wsrep system threads as well */
1117       if (WSREP(killing_thd) &&
1118           (killing_thd->wsrep_exec_mode==REPL_RECV || killing_thd->wsrep_applier))
1119         return;
1120 
1121       if (killing_thd->get_command() == COM_BINLOG_DUMP ||
1122           killing_thd->get_command() == COM_BINLOG_DUMP_GTID)
1123       {
1124         ++m_dump_thread_count;
1125         return;
1126       }
1127       DBUG_EXECUTE_IF("Check_dump_thread_is_alive",
1128                       {
1129                         assert(killing_thd->get_command() != COM_BINLOG_DUMP &&
1130                                     killing_thd->get_command() != COM_BINLOG_DUMP_GTID);
1131                       };);
1132     }
1133     mysql_mutex_lock(&killing_thd->LOCK_thd_data);
1134     killing_thd->killed= THD::KILL_CONNECTION;
1135     MYSQL_CALLBACK(Connection_handler_manager::event_functions,
1136                    post_kill_notification, (killing_thd));
1137     mysql_mutex_lock(&killing_thd->LOCK_current_cond);
1138     if (killing_thd->current_cond)
1139     {
1140       mysql_mutex_lock(killing_thd->current_mutex);
1141       mysql_cond_broadcast(killing_thd->current_cond);
1142       mysql_mutex_unlock(killing_thd->current_mutex);
1143     }
1144     mysql_mutex_unlock(&killing_thd->LOCK_current_cond);
1145     mysql_mutex_unlock(&killing_thd->LOCK_thd_data);
1146   }
1147 };
1148 
1149 /**
1150   This class implements callback function used by close_connections()
1151   to close vio connection for all thds in thd list
1152 */
1153 class Call_wsrep_close_client_conn : public Do_THD_Impl
1154 {
1155 public:
Call_wsrep_close_client_conn()1156   Call_wsrep_close_client_conn()
1157   {}
1158 
operator ()(THD * closing_thd)1159   virtual void operator()(THD *closing_thd)
1160   {
1161     if (closing_thd->get_protocol()->connection_alive() &&
1162         (WSREP(closing_thd) || closing_thd->wsrep_exec_mode == LOCAL_STATE) &&
1163         closing_thd != current_thd)
1164     {
1165       LEX_CSTRING main_sctx_user= closing_thd->m_main_security_ctx.user();
1166       sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1167                         closing_thd->thread_id(),
1168                         (main_sctx_user.length ? main_sctx_user.str : ""));
1169       close_connection(closing_thd);
1170     }
1171   }
1172 };
1173 
1174 /**
1175   This class implements callback function used by close_connections()
1176   to close all wsrep system threads
1177 */
1178 class Call_wsrep_close_wsrep_threads : public Do_THD_Impl
1179 {
1180 public:
Call_wsrep_close_wsrep_threads()1181   Call_wsrep_close_wsrep_threads()
1182   {}
1183 
operator ()(THD * thd)1184   virtual void operator()(THD *thd)
1185   {
1186     if (thd->wsrep_applier)
1187     {
1188       WSREP_DEBUG("Closing applier thread %u", thd->thread_id());
1189       mysql_mutex_lock(&thd->LOCK_thd_data);
1190       thd->killed= THD::KILL_CONNECTION;
1191       if (thd->current_cond)
1192       {
1193         mysql_mutex_lock(thd->current_mutex);
1194         mysql_cond_broadcast(thd->current_cond);
1195         mysql_mutex_unlock(thd->current_mutex);
1196       }
1197       mysql_mutex_unlock(&thd->LOCK_thd_data);
1198     }
1199   }
1200 };
1201 
1202 /**
1203   This class implements callback function used by close_connections()
1204   to wait for committing transactions
1205 */
1206 class Find_thd_committing: public Find_THD_Impl
1207 {
1208 public:
Find_thd_committing()1209   Find_thd_committing()
1210   {}
1211 
operator ()(THD * thd)1212   virtual bool operator()(THD *thd)
1213   {
1214     if (WSREP(thd) && thd->wsrep_exec_mode == LOCAL_STATE &&
1215         thd->wsrep_query_state == QUERY_COMMITTING)
1216     {
1217       return true;
1218     }
1219     return false;
1220   }
1221 };
1222 
1223 enum wsrep_thd_type   {APPLIER, COMMITTING};
1224 
1225 class Count_wsrep_thd: public Do_THD_Impl
1226 {
1227 public:
Count_wsrep_thd(enum wsrep_thd_type type)1228   Count_wsrep_thd(enum wsrep_thd_type type)
1229     : m_type(type)
1230     , m_count(0)
1231   {}
operator ()(THD * thd)1232   virtual void operator()(THD *thd)
1233   {
1234     switch (m_type)
1235     {
1236       case APPLIER:
1237       {
1238         if (thd->wsrep_applier)
1239           m_count++;
1240       }
1241       break;
1242       case COMMITTING:
1243       {
1244         if (thd->wsrep_query_state == QUERY_COMMITTING)
1245           m_count++;
1246       }
1247       break;
1248     }
1249   }
get_thd_count() const1250   int get_thd_count() const
1251   {
1252     return m_count;
1253   }
1254 private:
1255   enum wsrep_thd_type m_type;
1256   int m_count;
1257 };
1258 #endif /* WITH_WSREP */
1259 
close_connections(void)1260 static void close_connections(void)
1261 {
1262   DBUG_ENTER("close_connections");
1263 #ifdef WITH_WSREP
1264   WSREP_DEBUG("close_connections");
1265 #endif /* WITH_WSREP */
1266   (void) RUN_HOOK(server_state, before_server_shutdown, (NULL));
1267 
1268   Per_thread_connection_handler::kill_blocked_pthreads();
1269 
1270   uint dump_thread_count= 0;
1271   uint dump_thread_kill_retries= 8;
1272 
1273   // Close listeners.
1274   if (mysqld_socket_acceptor != NULL)
1275     mysqld_socket_acceptor->close_listener();
1276 #ifdef _WIN32
1277   if (named_pipe_acceptor != NULL)
1278     named_pipe_acceptor->close_listener();
1279 
1280   if (shared_mem_acceptor != NULL)
1281     shared_mem_acceptor->close_listener();
1282 #endif
1283 
1284   /*
1285     First signal all threads that it's time to die
1286     This will give the threads some time to gracefully abort their
1287     statements and inform their clients that the server is about to die.
1288   */
1289 
1290   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
1291   sql_print_information("Giving %d client threads a chance to die gracefully",
1292                         static_cast<int>(thd_manager->get_thd_count()));
1293 
1294   Set_kill_conn set_kill_conn;
1295   thd_manager->do_for_all_thd(&set_kill_conn);
1296   sql_print_information("Shutting down slave threads");
1297   end_slave();
1298 
1299   if (set_kill_conn.get_dump_thread_count())
1300   {
1301     /*
1302       Replication dump thread should be terminated after the clients are
1303       terminated. Wait for few more seconds for other sessions to end.
1304      */
1305     while (thd_manager->get_thd_count() > dump_thread_count &&
1306            dump_thread_kill_retries)
1307     {
1308       sleep(1);
1309       dump_thread_kill_retries--;
1310     }
1311     set_kill_conn.set_dump_thread_flag();
1312     thd_manager->do_for_all_thd(&set_kill_conn);
1313   }
1314   if (thd_manager->get_thd_count() > 0)
1315     sleep(2);         // Give threads time to die
1316 
1317   /*
1318     Force remaining threads to die by closing the connection to the client
1319     This will ensure that threads that are waiting for a command from the
1320     client on a blocking read call are aborted.
1321   */
1322 
1323   sql_print_information("Forcefully disconnecting %d remaining clients",
1324                         static_cast<int>(thd_manager->get_thd_count()));
1325 
1326   Call_close_conn call_close_conn(true);
1327   thd_manager->do_for_all_thd(&call_close_conn);
1328 
1329   (void) RUN_HOOK(server_state, after_server_shutdown, (NULL));
1330 
1331   /*
1332     All threads have now been aborted. Stop event scheduler thread
1333     after aborting all client connections, otherwise user may
1334     start/stop event scheduler after Events::deinit() deallocates
1335     scheduler object(static member in Events class)
1336   */
1337   Events::deinit();
1338   DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",
1339                      thd_manager->get_thd_count()));
1340   thd_manager->wait_till_no_thd();
1341 
1342   /*
1343     Connection threads might take a little while to go down after removing from
1344     global thread list. Give it some time.
1345   */
1346   Connection_handler_manager::wait_till_no_connection();
1347 
1348   delete_slave_info_objects();
1349   DBUG_PRINT("quit",("close_connections thread"));
1350 
1351   DBUG_VOID_RETURN;
1352 }
1353 
1354 
kill_mysql(void)1355 void kill_mysql(void)
1356 {
1357   DBUG_ENTER("kill_mysql");
1358 
1359 #if defined(_WIN32)
1360   {
1361     if (!SetEvent(hEventShutdown))
1362     {
1363       DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
1364     }
1365     /*
1366       or:
1367       HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
1368       SetEvent(hEventShutdown);
1369       CloseHandle(hEvent);
1370     */
1371   }
1372 #else
1373   if (pthread_kill(signal_thread_id.thread, SIGTERM))
1374   {
1375     DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
1376   }
1377 #endif
1378   DBUG_PRINT("quit",("After pthread_kill"));
1379   DBUG_VOID_RETURN;
1380 }
1381 
1382 
unireg_abort(int exit_code)1383 extern "C" void unireg_abort(int exit_code)
1384 {
1385   DBUG_ENTER("unireg_abort");
1386 
1387   // At this point it does not make sense to buffer more messages.
1388   // Just flush what we have and write directly to stderr.
1389   flush_error_log_messages();
1390 
1391   if (opt_help)
1392     usage();
1393   if (exit_code)
1394     sql_print_error("Aborting\n");
1395 
1396 #ifdef WITH_WSREP
1397   if (wsrep)
1398   {
1399     WSREP_DEBUG("unireg_abort");
1400     /* This is an abort situation, we cannot expect to gracefully close all
1401      * wsrep threads here, we can only diconnect from service */
1402     wsrep_close_client_connections(FALSE);
1403     wsrep_close_threads(NULL);
1404     wsrep->disconnect(wsrep);
1405 
1406     THD* thd = current_thd;
1407     if (thd)
1408     {
1409       Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
1410       WSREP_DEBUG("closing aborting applier THD: %u", thd->thread_id());
1411       thd->release_resources();
1412       thd_manager->remove_thd(thd);
1413 
1414       delete thd;
1415     }
1416 
1417     wsrep_wait_appliers_close(NULL);
1418     WSREP_INFO("Service disconnected.");
1419 
1420     sleep(1); /* so give some time to exit for those which can */
1421     WSREP_INFO("Some threads may fail to exit.");
1422     /* Signal possible SE initialization waiters with error. */
1423     wsrep_SE_initialized(WSREP_SE_INIT_RESULT_FAILURE);
1424     wsrep_deinit();
1425   }
1426 #endif // WITH_WSREP
1427   mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
1428                      MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT, exit_code);
1429 #ifndef _WIN32
1430   if (signal_thread_id.thread != 0)
1431   {
1432     start_processing_signals();
1433 
1434     pthread_kill(signal_thread_id.thread, SIGTERM);
1435     my_thread_join(&signal_thread_id, NULL);
1436   }
1437   signal_thread_id.thread= 0;
1438 
1439   if (opt_daemonize)
1440   {
1441     mysqld::runtime::signal_parent(pipe_write_fd,0);
1442   }
1443 #endif
1444 
1445   clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1446   DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
1447   mysqld_exit(exit_code);
1448 }
1449 
mysqld_exit(int exit_code)1450 static void mysqld_exit(int exit_code)
1451 {
1452   assert(exit_code >= MYSQLD_SUCCESS_EXIT
1453          && exit_code <= MYSQLD_FAILURE_EXIT);
1454   mysql_audit_finalize();
1455 #ifndef EMBEDDED_LIBRARY
1456   Srv_session::module_deinit();
1457 #endif
1458   delete_optimizer_cost_module();
1459   clean_up_mutexes();
1460   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
1461   destroy_error_log();
1462 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
1463   shutdown_performance_schema();
1464 #endif
1465 #if defined(_WIN32)
1466   if (Service.IsNT() && windows_service)
1467   {
1468     Service.Stop();
1469   }
1470   else
1471   {
1472     Service.SetShutdownEvent(0);
1473     if (hEventShutdown)
1474       CloseHandle(hEventShutdown);
1475   }
1476 #endif
1477   exit(exit_code); /* purecov: inspected */
1478 }
1479 
1480 #endif /* !EMBEDDED_LIBRARY */
1481 
1482 /**
1483    GTID cleanup destroys objects and reset their pointer.
1484    Function is reentrant.
1485 */
gtid_server_cleanup()1486 void gtid_server_cleanup()
1487 {
1488   if (gtid_state != NULL)
1489   {
1490     delete gtid_state;
1491     gtid_state= NULL;
1492   }
1493   if (global_sid_map != NULL)
1494   {
1495     delete global_sid_map;
1496     global_sid_map= NULL;
1497   }
1498   if (global_sid_lock != NULL)
1499   {
1500     delete global_sid_lock;
1501     global_sid_lock= NULL;
1502   }
1503   if (gtid_table_persistor != NULL)
1504   {
1505     delete gtid_table_persistor;
1506     gtid_table_persistor= NULL;
1507   }
1508   if (gtid_mode_lock)
1509   {
1510     delete gtid_mode_lock;
1511     gtid_mode_lock= NULL;
1512   }
1513 }
1514 
1515 /**
1516    GTID initialization.
1517 
1518    @return true if allocation does not succeed
1519            false if OK
1520 */
gtid_server_init()1521 bool gtid_server_init()
1522 {
1523   bool res=
1524     (!(global_sid_lock= new Checkable_rwlock(
1525 #ifdef HAVE_PSI_INTERFACE
1526                                              key_rwlock_global_sid_lock
1527 #endif
1528                                             )) ||
1529      !(gtid_mode_lock= new Checkable_rwlock(
1530 #ifdef HAVE_PSI_INTERFACE
1531                                             key_rwlock_gtid_mode_lock
1532 #endif
1533                                            )) ||
1534      !(global_sid_map= new Sid_map(global_sid_lock)) ||
1535      !(gtid_state= new Gtid_state(global_sid_lock, global_sid_map))||
1536      !(gtid_table_persistor= new Gtid_table_persistor()));
1537   if (res)
1538   {
1539     gtid_server_cleanup();
1540   }
1541   return res;
1542 }
1543 
1544 #ifndef EMBEDDED_LIBRARY
1545 // Free connection acceptors
free_connection_acceptors()1546 static void free_connection_acceptors()
1547 {
1548   delete mysqld_socket_acceptor;
1549   mysqld_socket_acceptor= NULL;
1550 
1551 #ifdef _WIN32
1552   delete named_pipe_acceptor;
1553   named_pipe_acceptor= NULL;
1554   delete shared_mem_acceptor;
1555   shared_mem_acceptor= NULL;
1556 #endif
1557 }
1558 #endif
1559 
1560 
clean_up(bool print_message)1561 void clean_up(bool print_message)
1562 {
1563   DBUG_PRINT("exit",("clean_up"));
1564   if (cleanup_done++)
1565     return; /* purecov: inspected */
1566 
1567   stop_handle_manager();
1568   release_ddl_log();
1569 
1570   memcached_shutdown();
1571 
1572   /*
1573     make sure that handlers finish up
1574     what they have that is dependent on the binlog
1575   */
1576   if ((opt_help == 0) || (opt_verbose > 0))
1577     sql_print_information("Binlog end");
1578   ha_binlog_end(current_thd);
1579 
1580   injector::free_instance();
1581   mysql_bin_log.cleanup();
1582   gtid_server_cleanup();
1583 
1584 #ifdef HAVE_REPLICATION
1585   if (use_slave_mask)
1586     bitmap_free(&slave_error_mask);
1587 #endif
1588   my_tz_free();
1589   my_dboptions_cache_free();
1590   ignore_db_dirs_free();
1591   servers_free(1);
1592 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1593   acl_free(1);
1594   grant_free();
1595 #endif
1596   query_cache.destroy();
1597   hostname_cache_free();
1598   item_func_sleep_free();
1599   lex_free();       /* Free some memory */
1600   item_create_cleanup();
1601   if (!opt_noacl)
1602   {
1603 #ifdef HAVE_DLOPEN
1604     udf_free();
1605 #endif
1606   }
1607   table_def_start_shutdown();
1608   delegates_shutdown();
1609   plugin_shutdown();
1610   delete_optimizer_cost_module();
1611   ha_end();
1612   if (tc_log)
1613   {
1614     tc_log->close();
1615     tc_log= NULL;
1616   }
1617   delegates_destroy();
1618   transaction_cache_free();
1619   table_def_free();
1620   mdl_destroy();
1621   key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
1622   multi_keycache_free();
1623   free_status_vars();
1624   query_logger.cleanup();
1625   my_free_open_file_info();
1626   if (defaults_argv)
1627     free_defaults(defaults_argv);
1628   free_tmpdir(&mysql_tmpdir_list);
1629   my_free(opt_bin_logname);
1630   bitmap_free(&temp_pool);
1631   free_max_user_conn();
1632 #ifdef HAVE_REPLICATION
1633   end_slave_list();
1634 #endif
1635   delete binlog_filter;
1636   delete rpl_filter;
1637   end_ssl();
1638   vio_end();
1639   my_regex_end();
1640 #if defined(ENABLED_DEBUG_SYNC)
1641   /* End the debug sync facility. See debug_sync.cc. */
1642   debug_sync_end();
1643 #endif /* defined(ENABLED_DEBUG_SYNC) */
1644 
1645 #ifndef EMBEDDED_LIBRARY
1646   delete_pid_file(MYF(0));
1647 #endif
1648 
1649   if (print_message && my_default_lc_messages && server_start_time)
1650     sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
1651   cleanup_errmsgs();
1652 
1653 #ifndef EMBEDDED_LIBRARY
1654   free_connection_acceptors();
1655   Connection_handler_manager::destroy_instance();
1656 #endif
1657 
1658   mysql_client_plugin_deinit();
1659   finish_client_errs();
1660   deinit_errmessage(); // finish server errs
1661   DBUG_PRINT("quit", ("Error messages freed"));
1662 
1663   free_charsets();
1664   sys_var_end();
1665   Global_THD_manager::destroy_instance();
1666 
1667   my_free(const_cast<char*>(log_bin_basename));
1668   my_free(const_cast<char*>(log_bin_index));
1669 #ifndef EMBEDDED_LIBRARY
1670   my_free(const_cast<char*>(relay_log_basename));
1671   my_free(const_cast<char*>(relay_log_index));
1672 #endif
1673   free_list(opt_early_plugin_load_list_ptr);
1674   free_list(opt_plugin_load_list_ptr);
1675 
1676   if (THR_THD_initialized)
1677   {
1678     THR_THD_initialized= false;
1679     (void) my_delete_thread_local_key(THR_THD);
1680   }
1681 
1682   if (THR_MALLOC_initialized)
1683   {
1684     THR_MALLOC_initialized= false;
1685     (void) my_delete_thread_local_key(THR_MALLOC);
1686   }
1687 
1688   if (have_statement_timeout == SHOW_OPTION_YES)
1689     my_timer_deinitialize();
1690 
1691   have_statement_timeout= SHOW_OPTION_DISABLED;
1692 
1693   log_syslog_exit();
1694 
1695   /*
1696     The following lines may never be executed as the main thread may have
1697     killed us
1698   */
1699   DBUG_PRINT("quit", ("done with cleanup"));
1700 } /* clean_up */
1701 
1702 
1703 #ifndef EMBEDDED_LIBRARY
1704 
clean_up_mutexes()1705 static void clean_up_mutexes()
1706 {
1707   mysql_mutex_destroy(&LOCK_log_throttle_qni);
1708   mysql_mutex_destroy(&LOCK_status);
1709   mysql_mutex_destroy(&LOCK_manager);
1710   mysql_mutex_destroy(&LOCK_crypt);
1711   mysql_mutex_destroy(&LOCK_user_conn);
1712 #ifdef HAVE_OPENSSL
1713   mysql_mutex_destroy(&LOCK_des_key_file);
1714 #endif
1715   mysql_rwlock_destroy(&LOCK_sys_init_connect);
1716   mysql_rwlock_destroy(&LOCK_sys_init_slave);
1717   mysql_mutex_destroy(&LOCK_global_system_variables);
1718   mysql_rwlock_destroy(&LOCK_system_variables_hash);
1719   mysql_mutex_destroy(&LOCK_uuid_generator);
1720   mysql_mutex_destroy(&LOCK_sql_rand);
1721   mysql_mutex_destroy(&LOCK_prepared_stmt_count);
1722   mysql_mutex_destroy(&LOCK_sql_slave_skip_counter);
1723   mysql_mutex_destroy(&LOCK_slave_net_timeout);
1724   mysql_mutex_destroy(&LOCK_slave_trans_dep_tracker);
1725   mysql_mutex_destroy(&LOCK_error_messages);
1726   mysql_mutex_destroy(&LOCK_offline_mode);
1727   mysql_mutex_destroy(&LOCK_default_password_lifetime);
1728   mysql_cond_destroy(&COND_manager);
1729 #ifdef _WIN32
1730   mysql_cond_destroy(&COND_handler_count);
1731   mysql_mutex_destroy(&LOCK_handler_count);
1732   mysql_rwlock_destroy(&LOCK_named_pipe_full_access_group);
1733 #endif
1734 #ifndef _WIN32
1735   mysql_cond_destroy(&COND_socket_listener_active);
1736   mysql_mutex_destroy(&LOCK_socket_listener_active);
1737   mysql_cond_destroy(&COND_start_signal_handler);
1738   mysql_mutex_destroy(&LOCK_start_signal_handler);
1739 #endif
1740   mysql_mutex_destroy(&LOCK_keyring_operations);
1741 #ifdef WITH_WSREP
1742   mysql_mutex_destroy(&LOCK_wsrep_ready);
1743   mysql_cond_destroy(&COND_wsrep_ready);
1744   mysql_mutex_destroy(&LOCK_wsrep_sst);
1745   mysql_cond_destroy(&COND_wsrep_sst);
1746   mysql_mutex_destroy(&LOCK_wsrep_sst_init);
1747   mysql_cond_destroy(&COND_wsrep_sst_init);
1748   mysql_mutex_destroy(&LOCK_wsrep_rollback);
1749   mysql_cond_destroy(&COND_wsrep_rollback);
1750   mysql_mutex_destroy(&LOCK_wsrep_replaying);
1751   mysql_cond_destroy(&COND_wsrep_replaying);
1752   mysql_mutex_destroy(&LOCK_wsrep_slave_threads);
1753   mysql_mutex_destroy(&LOCK_wsrep_desync);
1754 #endif
1755 }
1756 
1757 
1758 /****************************************************************************
1759 ** Init IP and UNIX socket
1760 ****************************************************************************/
1761 
set_ports()1762 static void set_ports()
1763 {
1764   char  *env;
1765   if (!mysqld_port && !opt_disable_networking)
1766   {         // Get port if not from commandline
1767     mysqld_port= MYSQL_PORT;
1768 
1769     /*
1770       if builder specifically requested a default port, use that
1771       (even if it coincides with our factory default).
1772       only if they didn't do we check /etc/services (and, failing
1773       on that, fall back to the factory default of 3306).
1774       either default can be overridden by the environment variable
1775       MYSQL_TCP_PORT, which in turn can be overridden with command
1776       line options.
1777     */
1778 
1779 #if MYSQL_PORT_DEFAULT == 0
1780     struct  servent *serv_ptr;
1781     if ((serv_ptr= getservbyname("mysql", "tcp")))
1782       mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
1783 #endif
1784     if ((env = getenv("MYSQL_TCP_PORT")))
1785       mysqld_port= (uint) atoi(env);    /* purecov: inspected */
1786   }
1787   if (!mysqld_unix_port)
1788   {
1789 #ifdef _WIN32
1790     mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
1791 #else
1792     mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
1793 #endif
1794     if ((env = getenv("MYSQL_UNIX_PORT")))
1795       mysqld_unix_port= env;      /* purecov: inspected */
1796   }
1797 }
1798 
1799 
1800 #if !defined(_WIN32)
1801 /* Change to run as another user if started with --user */
1802 
check_user(const char * user)1803 static struct passwd *check_user(const char *user)
1804 {
1805   struct passwd *tmp_user_info;
1806   uid_t user_id= geteuid();
1807 
1808   // Don't bother if we aren't superuser
1809   if (user_id)
1810   {
1811     if (user)
1812     {
1813       /* Don't give a warning, if real user is same as given with --user */
1814       tmp_user_info= getpwnam(user);
1815       if ((!tmp_user_info || user_id != tmp_user_info->pw_uid))
1816         sql_print_warning(
1817                     "One can only use the --user switch if running as root\n");
1818     }
1819     return NULL;
1820   }
1821   if (!user)
1822   {
1823     if (!opt_bootstrap && !opt_help)
1824     {
1825       sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
1826       unireg_abort(MYSQLD_ABORT_EXIT);
1827     }
1828     return NULL;
1829   }
1830   /* purecov: begin tested */
1831   if (!strcmp(user,"root"))
1832     return NULL;                        // Avoid problem with dynamic libraries
1833 
1834   if (!(tmp_user_info= getpwnam(user)))
1835   {
1836     // Allow a numeric uid to be used
1837     const char *pos;
1838     for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
1839     if (*pos)                                   // Not numeric id
1840       goto err;
1841     if (!(tmp_user_info= getpwuid(atoi(user))))
1842       goto err;
1843   }
1844   return tmp_user_info;
1845   /* purecov: end */
1846 
1847 err:
1848   sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
1849   unireg_abort(MYSQLD_ABORT_EXIT);
1850 
1851 #ifdef PR_SET_DUMPABLE
1852   if (test_flags & TEST_CORE_ON_SIGNAL)
1853   {
1854     /* inform kernel that process is dumpable */
1855     (void) prctl(PR_SET_DUMPABLE, 1);
1856   }
1857 #endif
1858 
1859   return NULL;
1860 }
1861 
set_user(const char * user,struct passwd * user_info_arg)1862 static void set_user(const char *user, struct passwd *user_info_arg)
1863 {
1864   /* purecov: begin tested */
1865   assert(user_info_arg != 0);
1866 #ifdef HAVE_INITGROUPS
1867   /*
1868     We can get a SIGSEGV when calling initgroups() on some systems when NSS
1869     is configured to use LDAP and the server is statically linked.  We set
1870     calling_initgroups as a flag to the SIGSEGV handler that is then used to
1871     output a specific message to help the user resolve this problem.
1872   */
1873   calling_initgroups= 1;
1874   initgroups((char*) user, user_info_arg->pw_gid);
1875   calling_initgroups= 0;
1876 #endif
1877   if (setgid(user_info_arg->pw_gid) == -1)
1878   {
1879     sql_print_error("setgid: %s", strerror(errno));
1880     unireg_abort(MYSQLD_ABORT_EXIT);
1881   }
1882   if (setuid(user_info_arg->pw_uid) == -1)
1883   {
1884     sql_print_error("setuid: %s", strerror(errno));
1885     unireg_abort(MYSQLD_ABORT_EXIT);
1886   }
1887   /* purecov: end */
1888 }
1889 
1890 
set_effective_user(struct passwd * user_info_arg)1891 static void set_effective_user(struct passwd *user_info_arg)
1892 {
1893   assert(user_info_arg != 0);
1894   if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
1895   {
1896     sql_print_error("setregid: %s", strerror(errno));
1897     unireg_abort(MYSQLD_ABORT_EXIT);
1898   }
1899   if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
1900   {
1901     sql_print_error("setreuid: %s", strerror(errno));
1902     unireg_abort(MYSQLD_ABORT_EXIT);
1903   }
1904 }
1905 
1906 
1907 /** Change root user if started with @c --chroot . */
set_root(const char * path)1908 static void set_root(const char *path)
1909 {
1910   if (chroot(path) == -1)
1911   {
1912     sql_print_error("chroot: %s", strerror(errno));
1913     unireg_abort(MYSQLD_ABORT_EXIT);
1914   }
1915   my_setwd("/", MYF(0));
1916 }
1917 #endif // !_WIN32
1918 
1919 
network_init(void)1920 static bool network_init(void)
1921 {
1922   if (opt_bootstrap)
1923     return false;
1924 
1925   set_ports();
1926 
1927 #ifdef HAVE_SYS_UN_H
1928   std::string const unix_sock_name(mysqld_unix_port ? mysqld_unix_port : "");
1929 #else
1930   std::string const unix_sock_name("");
1931 #endif
1932 
1933   if (!opt_disable_networking || unix_sock_name != "")
1934   {
1935     std::string const bind_addr_str(my_bind_addr_str ? my_bind_addr_str : "");
1936 
1937     Mysqld_socket_listener *mysqld_socket_listener=
1938       new (std::nothrow) Mysqld_socket_listener(bind_addr_str,
1939                                                 mysqld_port, back_log,
1940                                                 mysqld_port_timeout,
1941                                                 unix_sock_name);
1942     if (mysqld_socket_listener == NULL)
1943       return true;
1944 
1945     mysqld_socket_acceptor=
1946       new (std::nothrow) Connection_acceptor<Mysqld_socket_listener>(mysqld_socket_listener);
1947     if (mysqld_socket_acceptor == NULL)
1948     {
1949       delete mysqld_socket_listener;
1950       mysqld_socket_listener= NULL;
1951       return true;
1952     }
1953 
1954     if (mysqld_socket_acceptor->init_connection_acceptor())
1955       return true; // mysqld_socket_acceptor would be freed in unireg_abort.
1956 
1957     if (report_port == 0)
1958       report_port= mysqld_port;
1959 
1960     if (!opt_disable_networking)
1961       assert(report_port != 0);
1962   }
1963 #ifdef _WIN32
1964   // Create named pipe
1965   if (opt_enable_named_pipe)
1966   {
1967     std::string pipe_name= mysqld_unix_port ? mysqld_unix_port : "";
1968 
1969     named_pipe_listener= new (std::nothrow) Named_pipe_listener(&pipe_name);
1970     if (named_pipe_listener == NULL)
1971       return true;
1972 
1973     named_pipe_acceptor=
1974       new (std::nothrow) Connection_acceptor<Named_pipe_listener>(named_pipe_listener);
1975     if (named_pipe_acceptor == NULL)
1976     {
1977       delete named_pipe_listener;
1978       named_pipe_listener= NULL;
1979       return true;
1980     }
1981 
1982     if (named_pipe_acceptor->init_connection_acceptor())
1983       return true; // named_pipe_acceptor would be freed in unireg_abort.
1984   }
1985 
1986   // Setup shared_memory acceptor
1987   if (opt_enable_shared_memory)
1988   {
1989     std::string shared_mem_base_name= shared_memory_base_name ? shared_memory_base_name : "";
1990 
1991     Shared_mem_listener *shared_mem_listener=
1992       new (std::nothrow) Shared_mem_listener(&shared_mem_base_name);
1993     if (shared_mem_listener == NULL)
1994       return true;
1995 
1996     shared_mem_acceptor=
1997       new (std::nothrow) Connection_acceptor<Shared_mem_listener>(shared_mem_listener);
1998     if (shared_mem_acceptor == NULL)
1999     {
2000       delete shared_mem_listener;
2001       shared_mem_listener= NULL;
2002       return true;
2003     }
2004 
2005     if (shared_mem_acceptor->init_connection_acceptor())
2006       return true; // shared_mem_acceptor would be freed in unireg_abort.
2007   }
2008 #endif // _WIN32
2009   return false;
2010 }
2011 
2012 #ifdef _WIN32
2013 static uint handler_count= 0;
2014 
2015 
decrement_handler_count()2016 static inline void decrement_handler_count()
2017 {
2018   mysql_mutex_lock(&LOCK_handler_count);
2019   handler_count--;
2020   mysql_cond_signal(&COND_handler_count);
2021   mysql_mutex_unlock(&LOCK_handler_count);
2022 }
2023 
2024 
socket_conn_event_handler(void * arg)2025 extern "C" void *socket_conn_event_handler(void *arg)
2026 {
2027   my_thread_init();
2028 
2029   Connection_acceptor<Mysqld_socket_listener> *conn_acceptor=
2030     static_cast<Connection_acceptor<Mysqld_socket_listener>*>(arg);
2031   conn_acceptor->connection_event_loop();
2032 
2033   decrement_handler_count();
2034   my_thread_end();
2035   return 0;
2036 }
2037 
2038 
named_pipe_conn_event_handler(void * arg)2039 extern "C" void *named_pipe_conn_event_handler(void *arg)
2040 {
2041   my_thread_init();
2042 
2043   Connection_acceptor<Named_pipe_listener> *conn_acceptor=
2044     static_cast<Connection_acceptor<Named_pipe_listener>*>(arg);
2045   conn_acceptor->connection_event_loop();
2046 
2047   decrement_handler_count();
2048   my_thread_end();
2049   return 0;
2050 }
2051 
2052 
shared_mem_conn_event_handler(void * arg)2053 extern "C" void *shared_mem_conn_event_handler(void *arg)
2054 {
2055   my_thread_init();
2056 
2057   Connection_acceptor<Shared_mem_listener> *conn_acceptor=
2058     static_cast<Connection_acceptor<Shared_mem_listener>*>(arg);
2059   conn_acceptor->connection_event_loop();
2060 
2061   decrement_handler_count();
2062   my_thread_end();
2063   return 0;
2064 }
2065 
2066 
setup_conn_event_handler_threads()2067 void setup_conn_event_handler_threads()
2068 {
2069   my_thread_handle hThread;
2070 
2071   DBUG_ENTER("handle_connections_methods");
2072 
2073   if ((!have_tcpip || opt_disable_networking) &&
2074       !opt_enable_shared_memory && !opt_enable_named_pipe)
2075   {
2076     sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
2077     unireg_abort(MYSQLD_ABORT_EXIT);        // Will not return
2078   }
2079 
2080   mysql_mutex_lock(&LOCK_handler_count);
2081   handler_count=0;
2082 
2083   if (opt_enable_named_pipe)
2084   {
2085     int error= mysql_thread_create(key_thread_handle_con_namedpipes,
2086                                    &hThread, &connection_attrib,
2087                                    named_pipe_conn_event_handler,
2088                                    named_pipe_acceptor);
2089     if (!error)
2090       handler_count++;
2091     else
2092       sql_print_warning("Can't create thread to handle named pipes"
2093                         " (errno= %d)", error);
2094   }
2095 
2096   if (have_tcpip && !opt_disable_networking)
2097   {
2098     int error= mysql_thread_create(key_thread_handle_con_sockets,
2099                                    &hThread, &connection_attrib,
2100                                    socket_conn_event_handler,
2101                                    mysqld_socket_acceptor);
2102     if (!error)
2103       handler_count++;
2104     else
2105       sql_print_warning("Can't create thread to handle TCP/IP (errno= %d)",
2106                         error);
2107   }
2108 
2109   if (opt_enable_shared_memory)
2110   {
2111     int error= mysql_thread_create(key_thread_handle_con_sharedmem,
2112                                    &hThread, &connection_attrib,
2113                                    shared_mem_conn_event_handler,
2114                                    shared_mem_acceptor);
2115     if (!error)
2116       handler_count++;
2117     else
2118       sql_print_warning("Can't create thread to handle shared memory"
2119                         " (errno= %d)", error);
2120   }
2121 
2122   // Block until all connection listener threads have exited.
2123   while (handler_count > 0)
2124     mysql_cond_wait(&COND_handler_count, &LOCK_handler_count);
2125   mysql_mutex_unlock(&LOCK_handler_count);
2126   DBUG_VOID_RETURN;
2127 }
2128 
2129 
2130 /*
2131   On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
2132   with graceful shutdown.
2133   Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
2134   provides possibility to pass the exception to just-in-time debugger, collect
2135   dumps and potentially also the exception and thread context used to output
2136   callstack.
2137 */
2138 
console_event_handler(DWORD type)2139 static BOOL WINAPI console_event_handler( DWORD type )
2140 {
2141   DBUG_ENTER("console_event_handler");
2142   if(type == CTRL_C_EVENT)
2143   {
2144      /*
2145        Do not shutdown before startup is finished and shutdown
2146        thread is initialized. Otherwise there is a race condition
2147        between main thread doing initialization and CTRL-C thread doing
2148        cleanup, which can result into crash.
2149      */
2150      if(hEventShutdown)
2151        kill_mysql();
2152      else
2153        sql_print_warning("CTRL-C ignored during startup");
2154      DBUG_RETURN(TRUE);
2155   }
2156   DBUG_RETURN(FALSE);
2157 }
2158 
2159 
2160 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
2161 #define DEBUGGER_ATTACH_TIMEOUT 120
2162 /*
2163   Wait for debugger to attach and break into debugger. If debugger is not attached,
2164   resume after timeout.
2165 */
wait_for_debugger(int timeout_sec)2166 static void wait_for_debugger(int timeout_sec)
2167 {
2168    if(!IsDebuggerPresent())
2169    {
2170      int i;
2171      printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
2172      fflush(stdout);
2173      for(i= 0; i < timeout_sec; i++)
2174      {
2175        Sleep(1000);
2176        if(IsDebuggerPresent())
2177        {
2178          /* Break into debugger */
2179          __debugbreak();
2180          return;
2181        }
2182      }
2183      printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),
2184        timeout_sec);
2185      fflush(stdout);
2186    }
2187 }
2188 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
2189 
my_unhandler_exception_filter(EXCEPTION_POINTERS * ex_pointers)2190 LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
2191 {
2192    static BOOL first_time= TRUE;
2193    if(!first_time)
2194    {
2195      /*
2196        This routine can be called twice, typically
2197        when detaching in JIT debugger.
2198        Return EXCEPTION_EXECUTE_HANDLER to terminate process.
2199      */
2200      return EXCEPTION_EXECUTE_HANDLER;
2201    }
2202    first_time= FALSE;
2203 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
2204    /*
2205     Unfortunately there is no clean way to debug unhandled exception filters,
2206     as debugger does not stop there(also documented in MSDN)
2207     To overcome, one could put a MessageBox, but this will not work in service.
2208     Better solution is to print error message and sleep some minutes
2209     until debugger is attached
2210   */
2211   wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
2212 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
2213   __try
2214   {
2215     my_set_exception_pointers(ex_pointers);
2216     handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
2217   }
2218   __except(EXCEPTION_EXECUTE_HANDLER)
2219   {
2220     DWORD written;
2221     const char msg[] = "Got exception in exception handler!\n";
2222     WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1,
2223       &written,NULL);
2224   }
2225   /*
2226     Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
2227     (drwtsn32 or vsjitdebugger) possibility to attach,
2228     if JIT debugger is configured.
2229     Windows Error reporting might generate a dump here.
2230   */
2231   return EXCEPTION_CONTINUE_SEARCH;
2232 }
2233 
2234 
my_init_signals()2235 void my_init_signals()
2236 {
2237   if(opt_console)
2238     SetConsoleCtrlHandler(console_event_handler,TRUE);
2239 
2240     /* Avoid MessageBox()es*/
2241   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2242   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
2243   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
2244   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
2245   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
2246   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2247 
2248    /*
2249      Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
2250      because it would prevent JIT debugger and Windows error reporting
2251      from working. We need WER or JIT-debugging, since our own unhandled
2252      exception filter is not guaranteed to work in all situation
2253      (like heap corruption or stack overflow)
2254    */
2255   SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
2256                                | SEM_NOOPENFILEERRORBOX);
2257   SetUnhandledExceptionFilter(my_unhandler_exception_filter);
2258 }
2259 
2260 #else // !_WIN32
2261 
2262 extern "C" {
empty_signal_handler(int sig MY_ATTRIBUTE ((unused)))2263 static void empty_signal_handler(int sig MY_ATTRIBUTE((unused)))
2264 { }
2265 }
2266 
2267 
my_init_signals()2268 void my_init_signals()
2269 {
2270   DBUG_ENTER("my_init_signals");
2271   struct sigaction sa;
2272   (void) sigemptyset(&sa.sa_mask);
2273 
2274   if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
2275   {
2276 #ifdef HAVE_STACKTRACE
2277     my_init_stacktrace();
2278 #endif
2279 
2280     if (test_flags & TEST_CORE_ON_SIGNAL)
2281     {
2282       // Change limits so that we will get a core file.
2283       struct rlimit rl;
2284       rl.rlim_cur= rl.rlim_max= RLIM_INFINITY;
2285       if (setrlimit(RLIMIT_CORE, &rl))
2286         sql_print_warning("setrlimit could not change the size of core files to"
2287                           " 'infinity';  We may not be able to generate a"
2288                           " core file on signals");
2289     }
2290 
2291     /*
2292       SA_RESETHAND resets handler action to default when entering handler.
2293       SA_NODEFER allows receiving the same signal during handler.
2294       E.g. SIGABRT during our signal handler will dump core (default action).
2295     */
2296     sa.sa_flags= SA_RESETHAND | SA_NODEFER;
2297     sa.sa_handler= handle_fatal_signal;
2298     // Treat all these as fatal and handle them.
2299     (void) sigaction(SIGSEGV, &sa, NULL);
2300     (void) sigaction(SIGABRT, &sa, NULL);
2301     (void) sigaction(SIGBUS, &sa, NULL);
2302     (void) sigaction(SIGILL, &sa, NULL);
2303     (void) sigaction(SIGFPE, &sa, NULL);
2304   }
2305 
2306   // Ignore SIGPIPE and SIGALRM
2307   sa.sa_flags= 0;
2308   sa.sa_handler= SIG_IGN;
2309   (void) sigaction(SIGPIPE, &sa, NULL);
2310   (void) sigaction(SIGALRM, &sa, NULL);
2311 
2312   // SIGUSR1 is used to interrupt the socket listener.
2313   sa.sa_handler= empty_signal_handler;
2314   (void) sigaction(SIGUSR1, &sa, NULL);
2315 
2316   // Fix signals if ignored by parents (can happen on Mac OS X).
2317   sa.sa_handler= SIG_DFL;
2318   (void) sigaction(SIGTERM, &sa, NULL);
2319   (void) sigaction(SIGHUP, &sa, NULL);
2320 
2321   sigset_t set;
2322   (void) sigemptyset(&set);
2323   /*
2324     Block SIGQUIT, SIGHUP and SIGTERM.
2325     The signal handler thread does sigwait() on these.
2326   */
2327   (void) sigaddset(&set, SIGQUIT);
2328   (void) sigaddset(&set, SIGHUP);
2329   (void) sigaddset(&set, SIGTERM);
2330   (void) sigaddset(&set, SIGTSTP);
2331   /*
2332     Block SIGINT unless debugging to prevent Ctrl+C from causing
2333     unclean shutdown of the server.
2334   */
2335   if (!(test_flags & TEST_SIGINT))
2336     (void) sigaddset(&set, SIGINT);
2337   pthread_sigmask(SIG_SETMASK, &set, NULL);
2338   DBUG_VOID_RETURN;
2339 }
2340 
2341 
start_signal_handler()2342 static void start_signal_handler()
2343 {
2344   int error;
2345   my_thread_attr_t thr_attr;
2346   DBUG_ENTER("start_signal_handler");
2347 
2348   (void) my_thread_attr_init(&thr_attr);
2349   (void) pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
2350   (void) my_thread_attr_setdetachstate(&thr_attr, MY_THREAD_CREATE_JOINABLE);
2351 
2352   size_t guardize= 0;
2353   (void) pthread_attr_getguardsize(&thr_attr, &guardize);
2354 #if defined(__ia64__) || defined(__ia64)
2355   /*
2356     Peculiar things with ia64 platforms - it seems we only have half the
2357     stack size in reality, so we have to double it here
2358   */
2359   guardize= my_thread_stack_size;
2360 #endif
2361   (void) my_thread_attr_setstacksize(&thr_attr, my_thread_stack_size + guardize);
2362 
2363   /*
2364     Set main_thread_id so that SIGTERM/SIGQUIT/SIGKILL can interrupt
2365     the socket listener successfully.
2366   */
2367   main_thread_id= my_thread_self();
2368 
2369   mysql_mutex_lock(&LOCK_start_signal_handler);
2370   if ((error=
2371        mysql_thread_create(key_thread_signal_hand,
2372                            &signal_thread_id, &thr_attr, signal_hand, 0)))
2373   {
2374     sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
2375                     error, errno);
2376     flush_error_log_messages();
2377     exit(MYSQLD_ABORT_EXIT);
2378   }
2379   mysql_cond_wait(&COND_start_signal_handler, &LOCK_start_signal_handler);
2380   mysql_mutex_unlock(&LOCK_start_signal_handler);
2381 
2382   (void) my_thread_attr_destroy(&thr_attr);
2383   DBUG_VOID_RETURN;
2384 }
2385 
2386 
2387 /** This thread handles SIGTERM, SIGQUIT and SIGHUP signals. */
2388 /* ARGSUSED */
signal_hand(void * arg MY_ATTRIBUTE ((unused)))2389 extern "C" void *signal_hand(void *arg MY_ATTRIBUTE((unused)))
2390 {
2391   my_thread_init();
2392 
2393   sigset_t set;
2394   (void) sigemptyset(&set);
2395   (void) sigaddset(&set, SIGTERM);
2396   (void) sigaddset(&set, SIGQUIT);
2397   (void) sigaddset(&set, SIGHUP);
2398 
2399   /*
2400     Signal to start_signal_handler that we are ready.
2401     This works by waiting for start_signal_handler to free mutex,
2402     after which we signal it that we are ready.
2403   */
2404   mysql_mutex_lock(&LOCK_start_signal_handler);
2405   mysql_cond_broadcast(&COND_start_signal_handler);
2406   mysql_mutex_unlock(&LOCK_start_signal_handler);
2407 
2408   /*
2409     Waiting until mysqld_server_started == true to ensure that all server
2410     components have been successfully initialized. This step is mandatory
2411     since signal processing can be done safely only when all server components
2412     have been initialized.
2413   */
2414   mysql_mutex_lock(&LOCK_server_started);
2415   while (!mysqld_server_started)
2416     mysql_cond_wait(&COND_server_started, &LOCK_server_started);
2417   mysql_mutex_unlock(&LOCK_server_started);
2418 
2419   for (;;)
2420   {
2421     int sig;
2422     while (sigwait(&set, &sig) == EINTR)
2423     {}
2424     if (cleanup_done)
2425     {
2426       my_thread_end();
2427       my_thread_exit(0);      // Safety
2428       return NULL;            // Avoid compiler warnings
2429     }
2430     switch (sig) {
2431     case SIGTERM:
2432     case SIGQUIT:
2433       // Switch to the file log message processing.
2434       query_logger.set_handlers((log_output_options != LOG_NONE) ?
2435                                 LOG_FILE : LOG_NONE);
2436       DBUG_PRINT("info", ("Got signal: %d  abort_loop: %d", sig, abort_loop));
2437       if (!abort_loop)
2438       {
2439         abort_loop= true;       // Mark abort for threads.
2440 #ifdef HAVE_PSI_THREAD_INTERFACE
2441         // Delete the instrumentation for the signal thread.
2442         PSI_THREAD_CALL(delete_current_thread)();
2443 #endif
2444         /*
2445           Kill the socket listener.
2446           The main thread will then set socket_listener_active= false,
2447           and wait for us to finish all the cleanup below.
2448         */
2449         mysql_mutex_lock(&LOCK_socket_listener_active);
2450         while (socket_listener_active)
2451         {
2452           DBUG_PRINT("info",("Killing socket listener"));
2453           if (pthread_kill(main_thread_id, SIGUSR1))
2454           {
2455             assert(false);
2456             break;
2457           }
2458           mysql_cond_wait(&COND_socket_listener_active,
2459                           &LOCK_socket_listener_active);
2460         }
2461         mysql_mutex_unlock(&LOCK_socket_listener_active);
2462 
2463 #ifdef WITH_WSREP
2464         /* Stop wsrep threads in case they are running. */
2465         if (wsrep_running_threads > 0)
2466         {
2467           wsrep_stop_replication(NULL);
2468         }
2469 #endif
2470         close_connections();
2471 #ifdef WITH_WSREP
2472         if (WSREP_ON) wsrep_deinit();
2473 #endif
2474       }
2475       my_thread_end();
2476       my_thread_exit(0);
2477       return NULL;  // Avoid compiler warnings
2478       break;
2479     case SIGHUP:
2480       if (!abort_loop)
2481       {
2482         int not_used;
2483         mysql_print_status();   // Print some debug info
2484         reload_acl_and_cache(NULL,
2485                              (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
2486                               REFRESH_GRANT | REFRESH_THREADS | REFRESH_HOSTS),
2487                              NULL, &not_used); // Flush logs
2488         // Reenable query logs after the options were reloaded.
2489         query_logger.set_handlers(log_output_options);
2490       }
2491       break;
2492     default:
2493       break;          /* purecov: tested */
2494     }
2495   }
2496   return NULL;        /* purecov: deadcode */
2497 }
2498 
2499 #endif // !_WIN32
2500 #endif // !EMBEDDED_LIBRARY
2501 
2502 /**
2503   Starts processing signals initialized in the signal_hand function.
2504 
2505   @see signal_hand
2506 */
start_processing_signals()2507 static void start_processing_signals()
2508 {
2509   mysql_mutex_lock(&LOCK_server_started);
2510   mysqld_server_started= true;
2511   mysql_cond_broadcast(&COND_server_started);
2512   mysql_mutex_unlock(&LOCK_server_started);
2513 }
2514 
2515 #if HAVE_BACKTRACE && HAVE_ABI_CXA_DEMANGLE
2516 #include <cxxabi.h>
my_demangle(const char * mangled_name,int * status)2517 extern "C" char *my_demangle(const char *mangled_name, int *status)
2518 {
2519   return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
2520 }
2521 #endif
2522 
2523 
2524 /**
2525   All global error messages are sent here where the first one is stored
2526   for the client.
2527 */
2528 /* ARGSUSED */
2529 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
2530 
my_message_sql(uint error,const char * str,myf MyFlags)2531 void my_message_sql(uint error, const char *str, myf MyFlags)
2532 {
2533   THD *thd= current_thd;
2534   DBUG_ENTER("my_message_sql");
2535   DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
2536 
2537   assert(str != NULL);
2538   /*
2539     An error should have a valid error number (!= 0), so it can be caught
2540     in stored procedures by SQL exception handlers.
2541     Calling my_error() with error == 0 is a bug.
2542     Remaining known places to fix:
2543     - storage/myisam/mi_create.c, my_printf_error()
2544     TODO:
2545     assert(error != 0);
2546   */
2547 
2548   if (error == 0)
2549   {
2550     /* At least, prevent new abuse ... */
2551     assert(strncmp(str, "MyISAM table", 12) == 0);
2552     error= ER_UNKNOWN_ERROR;
2553   }
2554 
2555   if (thd)
2556   {
2557     Sql_condition::enum_severity_level level= Sql_condition::SL_ERROR;
2558 
2559     /**
2560       Reporting an error invokes audit API call that notifies the error
2561       to the plugin. Audit API that generate the error adds a protection
2562       (condition handler) that prevents entering infinite recursion, when
2563       a plugin signals error, when already handling the error.
2564 
2565       handle_condition is normally invoked from within raise_condition,
2566       but we need to prevent recursion befere notifying error to the plugin.
2567 
2568       Additionaly, handle_condition must be called once during reporting
2569       an error, so the raise_condition is called depending on the result of
2570       the handle_condition call.
2571     */
2572     bool handle= thd->handle_condition(error,
2573                                        mysql_errno_to_sqlstate(error),
2574                                        &level,
2575                                        str ? str : ER(error));
2576 #ifndef EMBEDDED_LIBRARY
2577     if (!handle)
2578       mysql_audit_notify(thd, AUDIT_EVENT(MYSQL_AUDIT_GENERAL_ERROR),
2579                          error, str, strlen(str));
2580 #endif
2581 
2582     if (MyFlags & ME_FATALERROR)
2583       thd->is_fatal_error= 1;
2584 
2585     if (!handle)
2586       (void) thd->raise_condition(error, NULL, level, str, false);
2587   }
2588 
2589   /* When simulating OOM, skip writing to error log to avoid mtr errors */
2590   DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
2591 
2592   if (!thd || MyFlags & ME_ERRORLOG)
2593     sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
2594   DBUG_VOID_RETURN;
2595 }
2596 
2597 
2598 #ifndef EMBEDDED_LIBRARY
2599 extern "C" void *my_str_malloc_mysqld(size_t size);
2600 extern "C" void my_str_free_mysqld(void *ptr);
2601 extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
2602 
my_str_malloc_mysqld(size_t size)2603 void *my_str_malloc_mysqld(size_t size)
2604 {
2605   return my_malloc(key_memory_my_str_malloc,
2606                    size, MYF(MY_FAE));
2607 }
2608 
2609 
my_str_free_mysqld(void * ptr)2610 void my_str_free_mysqld(void *ptr)
2611 {
2612   my_free(ptr);
2613 }
2614 
my_str_realloc_mysqld(void * ptr,size_t size)2615 void *my_str_realloc_mysqld(void *ptr, size_t size)
2616 {
2617   return my_realloc(key_memory_my_str_malloc,
2618                     ptr, size, MYF(MY_FAE));
2619 }
2620 #endif // !EMBEDDED_LIBRARY
2621 
2622 const char *load_default_groups[]= {
2623 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2624 "mysql_cluster",
2625 #endif
2626 "mysqld","server", MYSQL_BASE_VERSION, 0, 0};
2627 
2628 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
2629 static const int load_default_groups_sz=
2630 sizeof(load_default_groups)/sizeof(load_default_groups[0]);
2631 #endif
2632 
2633 #ifndef EMBEDDED_LIBRARY
2634 /**
2635   This function is used to check for stack overrun for pathological
2636   cases of regular expressions and 'like' expressions.
2637   The call to current_thd is quite expensive, so we try to avoid it
2638   for the normal cases.
2639   The size of each stack frame for the wildcmp() routines is ~128 bytes,
2640   so checking *every* recursive call is not necessary.
2641  */
2642 extern "C" int
check_enough_stack_size(int recurse_level)2643 check_enough_stack_size(int recurse_level)
2644 {
2645   uchar stack_top;
2646   if (recurse_level % 16 != 0)
2647     return 0;
2648 
2649   THD *my_thd= current_thd;
2650   if (my_thd != NULL)
2651     return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top);
2652   return 0;
2653 }
2654 #endif
2655 
2656 
2657 /**
2658   Initialize one of the global date/time format variables.
2659 
2660   @param format_type    What kind of format should be supported
2661   @param var_ptr    Pointer to variable that should be updated
2662 
2663   @retval
2664     0 ok
2665   @retval
2666     1 error
2667 */
2668 
init_global_datetime_format(timestamp_type format_type,Date_time_format * format)2669 static bool init_global_datetime_format(timestamp_type format_type,
2670                                         Date_time_format *format)
2671 {
2672   /*
2673     Get command line option
2674     format->format.str is already set by my_getopt
2675   */
2676   format->format.length= strlen(format->format.str);
2677 
2678   if (parse_date_time_format(format_type, format))
2679   {
2680     sql_print_error("Wrong date/time format specifier: %s",
2681                     format->format.str);
2682     return true;
2683   }
2684   return false;
2685 }
2686 
2687 SHOW_VAR com_status_vars[]= {
2688   {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other),                                          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2689   {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]),         SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2690   {"alter_db",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2691   {"alter_db_upgrade",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2692   {"alter_event",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2693   {"alter_function",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2694   {"alter_instance",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_INSTANCE]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2695   {"alter_procedure",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2696   {"alter_server",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2697   {"alter_table",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2698   {"alter_tablespace",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2699   {"alter_user",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_USER]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2700   {"analyze",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2701   {"begin",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2702   {"binlog",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]),        SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2703   {"call_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]),                       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2704   {"change_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2705   {"change_master",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2706   {"change_repl_filter",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_REPLICATION_FILTER]),  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2707   {"check",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2708   {"checksum",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2709   {"commit",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2710   {"create_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2711   {"create_event",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2712   {"create_function",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]),          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2713   {"create_index",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2714   {"create_procedure",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2715   {"create_server",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2716   {"create_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2717   {"create_trigger",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2718   {"create_udf",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2719   {"create_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2720   {"create_view",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2721   {"dealloc_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]),         SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2722   {"delete",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2723   {"delete_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2724   {"do",                   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]),                         SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2725   {"drop_db",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2726   {"drop_event",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2727   {"drop_function",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2728   {"drop_index",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2729   {"drop_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2730   {"drop_server",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2731   {"drop_table",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2732   {"drop_trigger",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2733   {"drop_user",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2734   {"drop_view",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2735   {"empty_query",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2736   {"execute_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2737   {"explain_other",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXPLAIN_OTHER]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2738   {"flush",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2739   {"get_diagnostics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2740   {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2741   {"ha_close",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2742   {"ha_open",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2743   {"ha_read",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2744   {"help",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]),                       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2745   {"insert",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2746   {"insert_select",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2747   {"install_plugin",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2748   {"kill",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]),                       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2749   {"load",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]),                       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2750   {"lock_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2751   {"optimize",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2752   {"preload_keys",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2753   {"prepare_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2754   {"purge",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2755   {"purge_before_date",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2756   {"release_savepoint",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]),          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2757   {"rename_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2758   {"rename_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2759   {"repair",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2760   {"replace",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]),                    SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2761   {"replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2762   {"reset",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]),                      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2763   {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2764   {"revoke",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2765   {"revoke_all",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2766   {"rollback",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2767   {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]),      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2768   {"savepoint",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2769   {"select",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2770   {"set_option",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2771   {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2772   {"show_binlog_events",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]),         SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2773   {"show_binlogs",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2774   {"show_charsets",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2775   {"show_collations",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2776   {"show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2777   {"show_create_event",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]),          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2778   {"show_create_func",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2779   {"show_create_proc",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2780   {"show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2781   {"show_create_trigger",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]),        SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2782   {"show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2783   {"show_engine_logs",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2784   {"show_engine_mutex",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]),          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2785   {"show_engine_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]),         SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2786   {"show_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2787   {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2788   {"show_fields",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2789   {"show_function_code",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2790   {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2791   {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2792   {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2793   {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2794   {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2795   {"show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2796   {"show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2797   {"show_procedure_code",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2798   {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2799   {"show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2800   {"show_profile",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2801   {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2802   {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]),       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2803   {"show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2804   {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]),            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2805   {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2806   {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]),       SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2807   {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]),          SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2808   {"show_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2809   {"show_triggers",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2810   {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]),             SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2811   {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2812   {"show_create_user",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_USER]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2813   {"shutdown",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHUTDOWN]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2814   {"slave_start",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2815   {"slave_stop",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2816   {"group_replication_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_START_GROUP_REPLICATION]), SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2817   {"group_replication_stop",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_STOP_GROUP_REPLICATION]),  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2818   {"stmt_execute",         (char*) offsetof(STATUS_VAR, com_stmt_execute),                                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2819   {"stmt_close",           (char*) offsetof(STATUS_VAR, com_stmt_close),                                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2820   {"stmt_fetch",           (char*) offsetof(STATUS_VAR, com_stmt_fetch),                                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2821   {"stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare),                                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2822   {"stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset),                                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2823   {"stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data),                            SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2824   {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2825   {"uninstall_plugin",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]),           SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2826   {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]),              SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2827   {"update",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2828   {"update_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]),               SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2829   {"xa_commit",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),                  SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2830   {"xa_end",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),                     SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2831   {"xa_prepare",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2832   {"xa_recover",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),                 SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2833   {"xa_rollback",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),                SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2834   {"xa_start",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),                   SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
2835   {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}
2836 };
2837 
2838 
2839 #ifndef EMBEDDED_LIBRARY
2840 LEX_CSTRING sql_statement_names[(uint) SQLCOM_END + 1];
2841 
init_sql_statement_names()2842 static void init_sql_statement_names()
2843 {
2844   static LEX_CSTRING empty= { C_STRING_WITH_LEN("") };
2845 
2846   char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]);
2847   char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
2848   int record_size= (char*) offsetof(STATUS_VAR, com_stat[1])
2849                    - (char*) offsetof(STATUS_VAR, com_stat[0]);
2850   char *ptr;
2851   uint i;
2852   uint com_index;
2853 
2854   for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
2855     sql_statement_names[i]= empty;
2856 
2857   SHOW_VAR *var= &com_status_vars[0];
2858   while (var->name != NULL)
2859   {
2860     ptr= var->value;
2861     if ((first_com <= ptr) && (ptr <= last_com))
2862     {
2863       com_index= ((int)(ptr - first_com))/record_size;
2864       assert(com_index < (uint) SQLCOM_END);
2865       sql_statement_names[com_index].str= var->name;
2866       /* TODO: Change SHOW_VAR::name to a LEX_STRING, to avoid strlen() */
2867       sql_statement_names[com_index].length= strlen(var->name);
2868     }
2869     var++;
2870   }
2871 
2872   assert(strcmp(sql_statement_names[(uint) SQLCOM_SELECT].str, "select") == 0);
2873   assert(strcmp(sql_statement_names[(uint) SQLCOM_SIGNAL].str, "signal") == 0);
2874 
2875   sql_statement_names[(uint) SQLCOM_END].str= "error";
2876 }
2877 #endif // !EMBEDDED_LIBRARY
2878 
2879 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2880 PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1];
2881 PSI_statement_info com_statement_info[(uint) COM_END + 1];
2882 PSI_statement_info stmt_info_new_packet;
2883 
2884 /**
2885   Initialize the command names array.
2886   Since we do not want to maintain a separate array,
2887   this is populated from data mined in com_status_vars,
2888   which already has one name for each command.
2889 */
init_sql_statement_info()2890 void init_sql_statement_info()
2891 {
2892   uint i;
2893 
2894   for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
2895   {
2896     sql_statement_info[i].m_name= sql_statement_names[i].str;
2897     sql_statement_info[i].m_flags= 0;
2898   }
2899 
2900   /* "statement/sql/error" represents broken queries (syntax error). */
2901   sql_statement_info[(uint) SQLCOM_END].m_name= "error";
2902   sql_statement_info[(uint) SQLCOM_END].m_flags= 0;
2903 }
2904 
init_com_statement_info()2905 void init_com_statement_info()
2906 {
2907   uint index;
2908 
2909   for (index= 0; index < (uint) COM_END + 1; index++)
2910   {
2911     com_statement_info[index].m_name= command_name[index].str;
2912     com_statement_info[index].m_flags= 0;
2913   }
2914 
2915   /* "statement/abstract/query" can mutate into "statement/sql/..." */
2916   com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE;
2917 }
2918 #endif
2919 
2920 /**
2921   Create a replication file name or base for file names.
2922 
2923   @param[in] opt Value of option, or NULL
2924   @param[in] def Default value if option value is not set.
2925   @param[in] ext Extension to use for the path
2926 
2927   @returns Pointer to string containing the full file path, or NULL if
2928   it was not possible to create the path.
2929  */
2930 static inline const char *
rpl_make_log_name(PSI_memory_key key,const char * opt,const char * def,const char * ext)2931 rpl_make_log_name(PSI_memory_key key,
2932                   const char *opt,
2933                   const char *def,
2934                   const char *ext)
2935 {
2936   DBUG_ENTER("rpl_make_log_name");
2937   DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", (opt && opt[0])? opt : "", def, ext));
2938   char buff[FN_REFLEN];
2939   /*
2940     opt[0] needs to be checked to make sure opt name is not an empty
2941     string, incase it is an empty string default name will be considered
2942   */
2943   const char *base= (opt && opt[0]) ? opt : def;
2944   unsigned int options=
2945     MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH;
2946 
2947   /* mysql_real_data_home_ptr may be null if no value of datadir has been
2948      specified through command-line or througha cnf file. If that is the
2949      case we make mysql_real_data_home_ptr point to mysql_real_data_home
2950      which, in that case holds the default path for data-dir.
2951   */
2952 
2953   DBUG_EXECUTE_IF("emulate_empty_datadir_param",
2954                   {
2955                     mysql_real_data_home_ptr= NULL;
2956                   };
2957                  );
2958 
2959   if(mysql_real_data_home_ptr == NULL)
2960     mysql_real_data_home_ptr= mysql_real_data_home;
2961 
2962   if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
2963     DBUG_RETURN(my_strdup(key, buff, MYF(0)));
2964   else
2965     DBUG_RETURN(NULL);
2966 }
2967 
2968 
init_common_variables()2969 int init_common_variables()
2970 {
2971   umask(((~my_umask) & 0666));
2972   my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
2973   tzset();      // Set tzname
2974 
2975   max_system_variables.pseudo_thread_id= (my_thread_id) ~0;
2976   server_start_time= flush_status_time= my_time(0);
2977 
2978   rpl_filter= new Rpl_filter;
2979   binlog_filter= new Rpl_filter;
2980   if (!rpl_filter || !binlog_filter)
2981   {
2982     sql_print_error("Could not allocate replication and binlog filters: %s",
2983                     strerror(errno));
2984     return 1;
2985   }
2986 
2987   if (init_thread_environment() ||
2988       mysql_init_variables())
2989     return 1;
2990 
2991   ignore_db_dirs_init();
2992 
2993   {
2994     struct tm tm_tmp;
2995     localtime_r(&server_start_time,&tm_tmp);
2996 #ifdef _WIN32
2997     strmake(system_time_zone, _tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
2998             sizeof(system_time_zone) - 1);
2999 #else
3000     strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
3001             sizeof(system_time_zone)-1);
3002 #endif
3003 
3004  }
3005 
3006   /*
3007     We set SYSTEM time zone as reasonable default and
3008     also for failure of my_tz_init() and bootstrap mode.
3009     If user explicitly set time zone with --default-time-zone
3010     option we will change this value in my_tz_init().
3011   */
3012   global_system_variables.time_zone= my_tz_SYSTEM;
3013 
3014 #ifdef HAVE_PSI_INTERFACE
3015   /*
3016     Complete the mysql_bin_log initialization.
3017     Instrumentation keys are known only after the performance schema initialization,
3018     and can not be set in the MYSQL_BIN_LOG constructor (called before main()).
3019   */
3020   mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
3021                              key_BINLOG_LOCK_commit,
3022                              key_BINLOG_LOCK_commit_queue,
3023                              key_BINLOG_LOCK_done,
3024                              key_BINLOG_LOCK_flush_queue,
3025                              key_BINLOG_LOCK_log,
3026                              key_BINLOG_LOCK_binlog_end_pos,
3027                              key_BINLOG_LOCK_sync,
3028                              key_BINLOG_LOCK_sync_queue,
3029                              key_BINLOG_LOCK_xids,
3030                              key_BINLOG_COND_done,
3031                              key_BINLOG_update_cond,
3032                              key_BINLOG_prep_xids_cond,
3033                              key_file_binlog,
3034                              key_file_binlog_index,
3035                              key_file_binlog_cache,
3036                              key_file_binlog_index_cache);
3037 #endif
3038 
3039   /*
3040     Init mutexes for the global MYSQL_BIN_LOG objects.
3041     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3042     global MYSQL_BIN_LOGs in their constructors, because then they would be
3043     inited before MY_INIT(). So we do it here.
3044   */
3045   mysql_bin_log.init_pthread_objects();
3046 
3047   /* TODO: remove this when my_time_t is 64 bit compatible */
3048   if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
3049   {
3050     sql_print_error("This MySQL server doesn't support dates later than 2038");
3051     return 1;
3052   }
3053 
3054   if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
3055   {
3056     strmake(glob_hostname, STRING_WITH_LEN("localhost"));
3057     sql_print_warning("gethostname failed, using '%s' as hostname",
3058                       glob_hostname);
3059     strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
3060   }
3061   else
3062     strmake(default_logfile_name, glob_hostname,
3063       sizeof(default_logfile_name)-5);
3064 
3065 #ifdef WITH_WSREP
3066   if (0 == wsrep_node_name || 0 == wsrep_node_name[0])
3067   {
3068     my_free((void *)wsrep_node_name);
3069     wsrep_node_name= my_strdup(key_memory_wsrep, glob_hostname, MYF(MY_WME));
3070   }
3071 #endif /* WITH_WSREP */
3072   strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name)-5);
3073   my_stpcpy(fn_ext(pidfile_name),".pid");    // Add proper extension
3074 
3075 
3076   /*
3077     The default-storage-engine entry in my_long_options should have a
3078     non-null default value. It was earlier intialized as
3079     (longlong)"MyISAM" in my_long_options but this triggered a
3080     compiler error in the Sun Studio 12 compiler. As a work-around we
3081     set the def_value member to 0 in my_long_options and initialize it
3082     to the correct value here.
3083 
3084     From MySQL 5.5 onwards, the default storage engine is InnoDB
3085     (except in the embedded server, where the default continues to
3086     be MyISAM)
3087   */
3088 #ifdef EMBEDDED_LIBRARY
3089   default_storage_engine= const_cast<char *>("MyISAM");
3090 #else
3091   default_storage_engine= const_cast<char *>("InnoDB");
3092 #endif
3093   default_tmp_storage_engine= default_storage_engine;
3094 
3095 
3096   /*
3097     Add server status variables to the dynamic list of
3098     status variables that is shown by SHOW STATUS.
3099     Later, in plugin_init, and mysql_install_plugin
3100     new entries could be added to that list.
3101   */
3102   if (add_status_vars(status_vars))
3103     return 1; // an error was already reported
3104 
3105 #ifndef NDEBUG
3106   /*
3107     We have few debug-only commands in com_status_vars, only visible in debug
3108     builds. for simplicity we enable the assert only in debug builds
3109 
3110     There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
3111     (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
3112     that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
3113 
3114       Com_admin_commands       => com_other
3115       Com_stmt_close           => com_stmt_close
3116       Com_stmt_execute         => com_stmt_execute
3117       Com_stmt_fetch           => com_stmt_fetch
3118       Com_stmt_prepare         => com_stmt_prepare
3119       Com_stmt_reprepare       => com_stmt_reprepare
3120       Com_stmt_reset           => com_stmt_reset
3121       Com_stmt_send_long_data  => com_stmt_send_long_data
3122 
3123     With this correction the number of Com_ variables (number of elements in
3124     the array, excluding the last element - terminator) must match the number
3125     of SQLCOM_ constants.
3126   */
3127   compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
3128                      SQLCOM_END + 7);
3129 #endif
3130 #ifdef WITH_WSREP
3131   /* This is a protection against mutually incompatible option values. */
3132   if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv))
3133     return 1;
3134 #endif /* WITH_WSREP */
3135 
3136   if (get_options(&remaining_argc, &remaining_argv))
3137     return 1;
3138 
3139   update_parser_max_mem_size();
3140 
3141   if (log_syslog_init())
3142     opt_log_syslog_enable= 0;
3143 
3144   if (set_default_auth_plugin(default_auth_plugin, strlen(default_auth_plugin)))
3145   {
3146     sql_print_error("Can't start server: "
3147 		    "Invalid value for --default-authentication-plugin");
3148     return 1;
3149   }
3150   set_server_version();
3151 
3152   log_warnings= log_error_verbosity - 1; // backward compatibility
3153 
3154   sql_print_information("%s (mysqld %s) starting as process %lu ...",
3155                         my_progname, server_version, (ulong) getpid());
3156 
3157 
3158 #ifndef EMBEDDED_LIBRARY
3159   if (opt_help && !opt_verbose)
3160     unireg_abort(MYSQLD_SUCCESS_EXIT);
3161 #endif /*!EMBEDDED_LIBRARY*/
3162 
3163   DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
3164          server_version, SYSTEM_TYPE,MACHINE_TYPE));
3165 
3166 #ifdef HAVE_LINUX_LARGE_PAGES
3167   /* Initialize large page size */
3168   if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
3169   {
3170       DBUG_PRINT("info", ("Large page set, large_page_size = %d",
3171                  opt_large_page_size));
3172       my_use_large_pages= 1;
3173       my_large_page_size= opt_large_page_size;
3174   }
3175   else
3176   {
3177     opt_large_pages= 0;
3178     /*
3179        Either not configured to use large pages or Linux haven't
3180        been compiled with large page support
3181     */
3182   }
3183 #endif /* HAVE_LINUX_LARGE_PAGES */
3184 #ifdef HAVE_SOLARIS_LARGE_PAGES
3185 #define LARGE_PAGESIZE (4*1024*1024)  /* 4MB */
3186 #define SUPER_LARGE_PAGESIZE (256*1024*1024)  /* 256MB */
3187   if (opt_large_pages)
3188   {
3189   /*
3190     tell the kernel that we want to use 4/256MB page for heap storage
3191     and also for the stack. We use 4 MByte as default and if the
3192     super-large-page is set we increase it to 256 MByte. 256 MByte
3193     is for server installations with GBytes of RAM memory where
3194     the MySQL Server will have page caches and other memory regions
3195     measured in a number of GBytes.
3196     We use as big pages as possible which isn't bigger than the above
3197     desired page sizes.
3198   */
3199    int nelem;
3200    size_t max_desired_page_size;
3201    if (opt_super_large_pages)
3202      max_desired_page_size= SUPER_LARGE_PAGESIZE;
3203    else
3204      max_desired_page_size= LARGE_PAGESIZE;
3205    nelem = getpagesizes(NULL, 0);
3206    if (nelem > 0)
3207    {
3208      size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
3209      if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
3210      {
3211        size_t max_page_size= 0;
3212        for (int i= 0; i < nelem; i++)
3213        {
3214          if (pagesize[i] > max_page_size &&
3215              pagesize[i] <= max_desired_page_size)
3216             max_page_size= pagesize[i];
3217        }
3218        free(pagesize);
3219        if (max_page_size > 0)
3220        {
3221          struct memcntl_mha mpss;
3222 
3223          mpss.mha_cmd= MHA_MAPSIZE_BSSBRK;
3224          mpss.mha_pagesize= max_page_size;
3225          mpss.mha_flags= 0;
3226          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
3227          mpss.mha_cmd= MHA_MAPSIZE_STACK;
3228          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
3229        }
3230      }
3231    }
3232   }
3233 #endif /* HAVE_SOLARIS_LARGE_PAGES */
3234 
3235   longlong default_value;
3236   sys_var *var;
3237 #ifndef EMBEDDED_LIBRARY
3238   /* Calculate and update default value for thread_cache_size. */
3239   if ((default_value= 8 + max_connections / 100) > 100)
3240     default_value= 100;
3241   var= intern_find_sys_var(STRING_WITH_LEN("thread_cache_size"));
3242   var->update_default(default_value);
3243 #endif
3244 
3245   /* Calculate and update default value for host_cache_size. */
3246   if ((default_value= 128 + max_connections) > 628 &&
3247       (default_value= 628 + ((max_connections - 500) / 20)) > 2000)
3248     default_value= 2000;
3249   var= intern_find_sys_var(STRING_WITH_LEN("host_cache_size"));
3250   var->update_default(default_value);
3251 
3252 #ifndef EMBEDDED_LIBRARY
3253   /* Fix thread_cache_size. */
3254   if (!thread_cache_size_specified &&
3255       (Per_thread_connection_handler::max_blocked_pthreads=
3256        8 + max_connections / 100) > 100)
3257     Per_thread_connection_handler::max_blocked_pthreads= 100;
3258 #endif // !EMBEDDED_LIBRARY
3259 
3260   /* Fix host_cache_size. */
3261   if (!host_cache_size_specified &&
3262       (host_cache_size= 128 + max_connections) > 628 &&
3263       (host_cache_size= 628 + ((max_connections - 500) / 20)) > 2000)
3264     host_cache_size= 2000;
3265 
3266   /* Fix back_log */
3267   if (back_log == 0 && (back_log= 50 + max_connections / 5) > 900)
3268     back_log= 900;
3269 
3270   unireg_init(opt_specialflag); /* Set up extern variabels */
3271   if (!(my_default_lc_messages=
3272         my_locale_by_name(lc_messages)))
3273   {
3274     sql_print_error("Unknown locale: '%s'", lc_messages);
3275     return 1;
3276   }
3277   global_system_variables.lc_messages= my_default_lc_messages;
3278   if (init_errmessage())  /* Read error messages from file */
3279     return 1;
3280   init_client_errs();
3281 
3282   mysql_client_plugin_init();
3283   if (item_create_init())
3284     return 1;
3285   item_init();
3286 #ifndef EMBEDDED_LIBRARY
3287   my_regex_init(&my_charset_latin1, check_enough_stack_size);
3288   my_string_stack_guard= check_enough_stack_size;
3289 #else
3290   my_regex_init(&my_charset_latin1, NULL);
3291 #endif
3292   /*
3293     Process a comma-separated character set list and choose
3294     the first available character set. This is mostly for
3295     test purposes, to be able to start "mysqld" even if
3296     the requested character set is not available (see bug#18743).
3297   */
3298   for (;;)
3299   {
3300     char *next_character_set_name= strchr(default_character_set_name, ',');
3301     if (next_character_set_name)
3302       *next_character_set_name++= '\0';
3303     if (!(default_charset_info=
3304           get_charset_by_csname(default_character_set_name,
3305                                 MY_CS_PRIMARY, MYF(MY_WME))))
3306     {
3307       if (next_character_set_name)
3308       {
3309         default_character_set_name= next_character_set_name;
3310         default_collation_name= 0;          // Ignore collation
3311       }
3312       else
3313         return 1;                           // Eof of the list
3314     }
3315     else
3316       break;
3317   }
3318 
3319   if (default_collation_name)
3320   {
3321     CHARSET_INFO *default_collation;
3322     default_collation= get_charset_by_name(default_collation_name, MYF(0));
3323     if (!default_collation)
3324     {
3325       sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
3326       return 1;
3327     }
3328     if (!my_charset_same(default_charset_info, default_collation))
3329     {
3330       sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
3331           default_collation_name,
3332           default_charset_info->csname);
3333       return 1;
3334     }
3335     default_charset_info= default_collation;
3336   }
3337   /* Set collactions that depends on the default collation */
3338   global_system_variables.collation_server=  default_charset_info;
3339   global_system_variables.collation_database=  default_charset_info;
3340 
3341   if (is_supported_parser_charset(default_charset_info))
3342   {
3343     global_system_variables.collation_connection= default_charset_info;
3344     global_system_variables.character_set_results= default_charset_info;
3345     global_system_variables.character_set_client= default_charset_info;
3346   }
3347   else
3348   {
3349     sql_print_information("'%s' can not be used as client character set. "
3350                           "'%s' will be used as default client character set.",
3351                           default_charset_info->csname,
3352                           my_charset_latin1.csname);
3353     global_system_variables.collation_connection= &my_charset_latin1;
3354     global_system_variables.character_set_results= &my_charset_latin1;
3355     global_system_variables.character_set_client= &my_charset_latin1;
3356   }
3357 
3358   if (!(character_set_filesystem=
3359         get_charset_by_csname(character_set_filesystem_name,
3360                               MY_CS_PRIMARY, MYF(MY_WME))))
3361     return 1;
3362   global_system_variables.character_set_filesystem= character_set_filesystem;
3363 
3364   if (lex_init())
3365   {
3366     sql_print_error("Out of memory");
3367     return 1;
3368   }
3369 
3370   if (!(my_default_lc_time_names=
3371         my_locale_by_name(lc_time_names_name)))
3372   {
3373     sql_print_error("Unknown locale: '%s'", lc_time_names_name);
3374     return 1;
3375   }
3376   global_system_variables.lc_time_names= my_default_lc_time_names;
3377 
3378   /* check log options and issue warnings if needed */
3379   if (opt_general_log && opt_general_logname && !(log_output_options & LOG_FILE) &&
3380       !(log_output_options & LOG_NONE))
3381     sql_print_warning("Although a path was specified for the "
3382                       "--general-log-file option, log tables are used. "
3383                       "To enable logging to files use the --log-output=file option.");
3384 
3385   if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
3386       && !(log_output_options & LOG_NONE))
3387     sql_print_warning("Although a path was specified for the "
3388                       "--slow-query-log-file option, log tables are used. "
3389                       "To enable logging to files use the --log-output=file option.");
3390 
3391   if (opt_general_logname &&
3392       !is_valid_log_name(opt_general_logname, strlen(opt_general_logname)))
3393   {
3394     sql_print_error("Invalid value for --general_log_file: %s",
3395                     opt_general_logname);
3396     return 1;
3397   }
3398 
3399   if (opt_slow_logname &&
3400       !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname)))
3401   {
3402     sql_print_error("Invalid value for --slow_query_log_file: %s",
3403                     opt_slow_logname);
3404     return 1;
3405   }
3406 
3407   /* We set the atomic field m_opt_tracking_mode to the value of the sysvar
3408      variable m_opt_tracking_mode_value here, as it now has the user given
3409      value
3410   */
3411   set_mysqld_opt_tracking_mode();
3412   if (global_system_variables.transaction_write_set_extraction == HASH_ALGORITHM_OFF
3413       && mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode != DEPENDENCY_TRACKING_COMMIT_ORDER)
3414   {
3415     sql_print_error("The transaction_write_set_extraction must be set to XXHASH64 or MURMUR32"
3416                     " when binlog_transaction_dependency_tracking is WRITESET or WRITESET_SESSION.");
3417     return 1;
3418   }
3419   else
3420     mysql_bin_log.m_dependency_tracker.tracking_mode_changed();
3421 
3422   my_atomic_store64(&mysql_bin_log.m_dependency_tracker.get_writeset()->m_opt_max_history_size,
3423                     static_cast<int64>(mysql_bin_log.m_dependency_tracker.
3424                         get_writeset()->m_opt_max_history_size_base_var));
3425 
3426 
3427 #define FIX_LOG_VAR(VAR, ALT)                                   \
3428   if (!VAR || !*VAR)                                            \
3429     VAR= ALT;
3430 
3431   FIX_LOG_VAR(opt_general_logname,
3432               make_query_log_name(logname_path, QUERY_LOG_GENERAL));
3433   FIX_LOG_VAR(opt_slow_logname,
3434               make_query_log_name(slow_logname_path, QUERY_LOG_SLOW));
3435 
3436 #if defined(ENABLED_DEBUG_SYNC)
3437   /* Initialize the debug sync facility. See debug_sync.cc. */
3438   if (debug_sync_init())
3439     return 1; /* purecov: tested */
3440 #endif /* defined(ENABLED_DEBUG_SYNC) */
3441 
3442 #if defined(__linux__)
3443   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
3444     return 1;
3445 #else
3446   use_temp_pool= 0;
3447 #endif
3448 
3449   if (my_dboptions_cache_init())
3450     return 1;
3451 
3452   if (ignore_db_dirs_process_additions())
3453   {
3454     sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
3455     return 1;
3456   }
3457 
3458   /* create the data directory if requested */
3459   if (unlikely(opt_initialize) &&
3460       initialize_create_data_directory(mysql_real_data_home))
3461       return 1;
3462 
3463 
3464   /*
3465     Ensure that lower_case_table_names is set on system where we have case
3466     insensitive names.  If this is not done the users MyISAM tables will
3467     get corrupted if accesses with names of different case.
3468   */
3469   DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
3470   lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
3471   if (!lower_case_table_names && lower_case_file_system == 1)
3472   {
3473     if (lower_case_table_names_used)
3474     {
3475       sql_print_error("The server option 'lower_case_table_names' is "
3476                       "configured to use case sensitive table names but the "
3477                       "data directory is on a case-insensitive file system "
3478                       "which is an unsupported combination. Please consider "
3479                       "either using a case sensitive file system for your data "
3480                       "directory or switching to a case-insensitive table name "
3481                       "mode.");
3482       return 1;
3483     }
3484     else
3485     {
3486       sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
3487       lower_case_table_names= 2;
3488     }
3489   }
3490   else if (lower_case_table_names == 2 &&
3491            !(lower_case_file_system=
3492              (test_if_case_insensitive(mysql_real_data_home) == 1)))
3493   {
3494     sql_print_warning("lower_case_table_names was set to 2, even though your "
3495                         "the file system '%s' is case sensitive.  Now setting "
3496                         "lower_case_table_names to 0 to avoid future problems.",
3497       mysql_real_data_home);
3498     lower_case_table_names= 0;
3499   }
3500   else
3501   {
3502     lower_case_file_system=
3503       (test_if_case_insensitive(mysql_real_data_home) == 1);
3504   }
3505 
3506   /* Reset table_alias_charset, now that lower_case_table_names is set. */
3507   table_alias_charset= (lower_case_table_names ?
3508       &my_charset_utf8_tolower_ci :
3509       &my_charset_bin);
3510 
3511   /*
3512     Build do_table and ignore_table rules to hush
3513     after the resetting of table_alias_charset
3514   */
3515   if (rpl_filter->build_do_table_hash() ||
3516       rpl_filter->build_ignore_table_hash())
3517   {
3518     sql_print_error("An error occurred while building do_table"
3519                     "and ignore_table rules to hush.");
3520     return 1;
3521   }
3522 
3523   return 0;
3524 }
3525 
3526 
init_thread_environment()3527 static int init_thread_environment()
3528 {
3529   mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
3530   mysql_mutex_init(key_LOCK_manager,
3531                    &LOCK_manager, MY_MUTEX_INIT_FAST);
3532   mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
3533   mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
3534   mysql_mutex_init(key_LOCK_global_system_variables,
3535                    &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
3536   mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
3537                     &LOCK_system_variables_hash);
3538   mysql_mutex_init(key_LOCK_prepared_stmt_count,
3539                    &LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
3540   mysql_mutex_init(key_LOCK_sql_slave_skip_counter,
3541                    &LOCK_sql_slave_skip_counter, MY_MUTEX_INIT_FAST);
3542   mysql_mutex_init(key_LOCK_slave_net_timeout,
3543                    &LOCK_slave_net_timeout, MY_MUTEX_INIT_FAST);
3544   mysql_mutex_init(key_LOCK_slave_trans_dep_tracker,
3545                    &LOCK_slave_trans_dep_tracker, MY_MUTEX_INIT_FAST);
3546   mysql_mutex_init(key_LOCK_error_messages,
3547                    &LOCK_error_messages, MY_MUTEX_INIT_FAST);
3548   mysql_mutex_init(key_LOCK_uuid_generator,
3549                    &LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
3550   mysql_mutex_init(key_LOCK_sql_rand,
3551                    &LOCK_sql_rand, MY_MUTEX_INIT_FAST);
3552   mysql_mutex_init(key_LOCK_log_throttle_qni,
3553                    &LOCK_log_throttle_qni, MY_MUTEX_INIT_FAST);
3554   mysql_mutex_init(key_LOCK_offline_mode,
3555                    &LOCK_offline_mode, MY_MUTEX_INIT_FAST);
3556   mysql_mutex_init(key_LOCK_default_password_lifetime,
3557                    &LOCK_default_password_lifetime, MY_MUTEX_INIT_FAST);
3558 #ifdef HAVE_OPENSSL
3559   mysql_mutex_init(key_LOCK_des_key_file,
3560                    &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
3561 #endif
3562   mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
3563   mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
3564   mysql_cond_init(key_COND_manager, &COND_manager);
3565   mysql_mutex_init(key_LOCK_server_started,
3566                    &LOCK_server_started, MY_MUTEX_INIT_FAST);
3567   mysql_mutex_init(key_LOCK_keyring_operations,
3568                    &LOCK_keyring_operations, MY_MUTEX_INIT_FAST);
3569   mysql_cond_init(key_COND_server_started, &COND_server_started);
3570   mysql_mutex_init(key_LOCK_reset_gtid_table,
3571                    &LOCK_reset_gtid_table, MY_MUTEX_INIT_FAST);
3572   mysql_mutex_init(key_LOCK_compress_gtid_table,
3573                    &LOCK_compress_gtid_table, MY_MUTEX_INIT_FAST);
3574   mysql_cond_init(key_COND_compress_gtid_table,
3575                   &COND_compress_gtid_table);
3576 #ifndef EMBEDDED_LIBRARY
3577   Events::init_mutexes();
3578 #if defined(_WIN32)
3579   mysql_mutex_init(key_LOCK_handler_count,
3580                    &LOCK_handler_count, MY_MUTEX_INIT_FAST);
3581   mysql_cond_init(key_COND_handler_count, &COND_handler_count);
3582   mysql_rwlock_init(key_rwlock_LOCK_named_pipe_full_access_group,
3583                     &LOCK_named_pipe_full_access_group);
3584 #else
3585   mysql_mutex_init(key_LOCK_socket_listener_active,
3586                    &LOCK_socket_listener_active, MY_MUTEX_INIT_FAST);
3587   mysql_cond_init(key_COND_socket_listener_active,
3588                   &COND_socket_listener_active);
3589   mysql_mutex_init(key_LOCK_start_signal_handler,
3590                    &LOCK_start_signal_handler, MY_MUTEX_INIT_FAST);
3591   mysql_cond_init(key_COND_start_signal_handler,
3592                   &COND_start_signal_handler);
3593 #endif // _WIN32
3594 #endif // !EMBEDDED_LIBRARY
3595   /* Parameter for threads created for connections */
3596   (void) my_thread_attr_init(&connection_attrib);
3597   my_thread_attr_setdetachstate(&connection_attrib, MY_THREAD_CREATE_DETACHED);
3598 #ifndef _WIN32
3599   pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
3600 #endif
3601 
3602   assert(! THR_THD_initialized);
3603   assert(! THR_MALLOC_initialized);
3604   if (my_create_thread_local_key(&THR_THD,NULL) ||
3605       my_create_thread_local_key(&THR_MALLOC,NULL))
3606   {
3607     sql_print_error("Can't create thread-keys");
3608     return 1;
3609   }
3610   THR_THD_initialized= true;
3611   THR_MALLOC_initialized= true;
3612   return 0;
3613 }
3614 
3615 #ifndef EMBEDDED_LIBRARY
auto_detect_ssl()3616 ssl_artifacts_status auto_detect_ssl()
3617 {
3618   MY_STAT cert_stat, cert_key, ca_stat;
3619   uint result= 1;
3620   ssl_artifacts_status ret_status= SSL_ARTIFACTS_VIA_OPTIONS;
3621 
3622   if ((!opt_ssl_cert || !opt_ssl_cert[0]) &&
3623       (!opt_ssl_key || !opt_ssl_key[0]) &&
3624       (!opt_ssl_ca || !opt_ssl_ca[0]) &&
3625       (!opt_ssl_capath || !opt_ssl_capath[0]) &&
3626       (!opt_ssl_crl || !opt_ssl_crl[0]) &&
3627       (!opt_ssl_crlpath || !opt_ssl_crlpath[0]))
3628   {
3629     result= result << (my_stat(DEFAULT_SSL_SERVER_CERT, &cert_stat, MYF(0)) ? 1 : 0)
3630                    << (my_stat(DEFAULT_SSL_SERVER_KEY, &cert_key, MYF(0)) ? 1 : 0)
3631                    << (my_stat(DEFAULT_SSL_CA_CERT, &ca_stat, MYF(0)) ? 1 : 0);
3632 
3633     switch(result)
3634     {
3635       case 8:
3636         opt_ssl_ca= (char *)DEFAULT_SSL_CA_CERT;
3637         opt_ssl_cert= (char *)DEFAULT_SSL_SERVER_CERT;
3638         opt_ssl_key= (char *)DEFAULT_SSL_SERVER_KEY;
3639         ret_status= SSL_ARTIFACTS_AUTO_DETECTED;
3640         break;
3641       case 4:
3642       case 2:
3643         ret_status= SSL_ARTIFACT_TRACES_FOUND;
3644         break;
3645       default:
3646         ret_status= SSL_ARTIFACTS_NOT_FOUND;
3647         break;
3648     };
3649   }
3650 
3651   return ret_status;
3652 }
3653 
warn_one(const char * file_name)3654 int warn_one(const char *file_name)
3655 {
3656   FILE *fp;
3657   char *issuer= NULL;
3658   char *subject= NULL;
3659 
3660   if (!(fp= my_fopen(file_name, O_RDONLY | O_BINARY, MYF(MY_WME))))
3661   {
3662     sql_print_error("Error opening CA certificate file");
3663     return 1;
3664   }
3665 
3666   X509 *ca_cert= PEM_read_X509(fp, 0, 0, 0);
3667 
3668   if (!ca_cert)
3669   {
3670     /* We are not interested in anything other than X509 certificates */
3671     my_fclose(fp, MYF(MY_WME));
3672     return 0;
3673   }
3674 
3675   issuer= X509_NAME_oneline(X509_get_issuer_name(ca_cert), 0, 0);
3676   subject= X509_NAME_oneline(X509_get_subject_name(ca_cert), 0, 0);
3677 
3678   if (!strcmp(issuer, subject))
3679   {
3680     sql_print_warning("CA certificate %s is self signed.", file_name);
3681   }
3682 
3683   OPENSSL_free(issuer);
3684   OPENSSL_free(subject);
3685   X509_free(ca_cert);
3686   my_fclose(fp, MYF(MY_WME));
3687   return 0;
3688 
3689 }
3690 
warn_self_signed_ca()3691 int warn_self_signed_ca()
3692 {
3693   int ret_val= 0;
3694   if (opt_ssl_ca && opt_ssl_ca[0])
3695   {
3696     if (warn_one(opt_ssl_ca))
3697       return 1;
3698   }
3699   if (opt_ssl_capath && opt_ssl_capath[0])
3700   {
3701     /* We have ssl-capath. So search all files in the dir */
3702     MY_DIR *ca_dir;
3703     uint file_count;
3704     DYNAMIC_STRING file_path;
3705     char dir_separator[FN_REFLEN];
3706     size_t dir_path_length;
3707 
3708     init_dynamic_string(&file_path, opt_ssl_capath, FN_REFLEN, FN_REFLEN);
3709     dir_separator[0]= FN_LIBCHAR;
3710     dir_separator[1]= 0;
3711     dynstr_append(&file_path, dir_separator);
3712     dir_path_length= file_path.length;
3713 
3714     if (!(ca_dir= my_dir(opt_ssl_capath,MY_WANT_STAT|MY_DONT_SORT|MY_WME)))
3715     {
3716       sql_print_error("Error accessing directory pointed by --ssl-capath");
3717       return 1;
3718     }
3719 
3720     for (file_count = 0; file_count < ca_dir->number_off_files; file_count++)
3721     {
3722       if (!MY_S_ISDIR(ca_dir->dir_entry[file_count].mystat->st_mode))
3723       {
3724         file_path.length= dir_path_length;
3725         dynstr_append(&file_path, ca_dir->dir_entry[file_count].name);
3726         if ((ret_val= warn_one(file_path.str)))
3727           break;
3728       }
3729     }
3730     my_dirend(ca_dir);
3731     dynstr_free(&file_path);
3732 
3733     ca_dir= 0;
3734     memset(&file_path, 0, sizeof(file_path));
3735   }
3736   return ret_val;
3737 }
3738 
push_deprecated_tls_option_no_replacement(const char * tls_version)3739 static void push_deprecated_tls_option_no_replacement(const char *tls_version) {
3740   sql_print_warning(ER_DEFAULT(ER_WARN_DEPRECATED_TLS_VERSION), tls_version);
3741 }
3742 
3743 #endif /* EMBEDDED_LIBRARY */
3744 
init_ssl()3745 static int init_ssl()
3746 {
3747 #ifdef HAVE_OPENSSL
3748 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
3749   CRYPTO_malloc_init();
3750 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
3751   OPENSSL_malloc_init();
3752 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
3753   ssl_start();
3754 #ifndef EMBEDDED_LIBRARY
3755 
3756   if (opt_use_ssl)
3757   {
3758     ssl_artifacts_status auto_detection_status= auto_detect_ssl();
3759     if (auto_detection_status == SSL_ARTIFACTS_AUTO_DETECTED)
3760       sql_print_information("Found %s, %s and %s in data directory. "
3761                             "Trying to enable SSL support using them.",
3762                             DEFAULT_SSL_CA_CERT, DEFAULT_SSL_SERVER_CERT,
3763                             DEFAULT_SSL_SERVER_KEY);
3764     if (do_auto_cert_generation(auto_detection_status) == false)
3765       return 1;
3766 
3767     enum enum_ssl_init_error error= SSL_INITERR_NOERROR;
3768     long ssl_ctx_flags= process_tls_version(opt_tls_version);
3769 
3770     if (!(ssl_ctx_flags & SSL_OP_NO_TLSv1))
3771       push_deprecated_tls_option_no_replacement("TLSv1");
3772     if (!(ssl_ctx_flags & SSL_OP_NO_TLSv1_1))
3773       push_deprecated_tls_option_no_replacement("TLSv1.1");
3774 
3775     /* having ssl_acceptor_fd != 0 signals the use of SSL */
3776     ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
3777 					  opt_ssl_ca, opt_ssl_capath,
3778 					  opt_ssl_cipher, &error,
3779                                           opt_ssl_crl, opt_ssl_crlpath, ssl_ctx_flags);
3780     DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
3781 #if OPENSSL_VERSION_NUMBER < 0x10100000L
3782     ERR_remove_thread_state(0);
3783 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
3784     if (!ssl_acceptor_fd)
3785     {
3786       /*
3787         No real need for opt_use_ssl to be enabled in bootstrap mode,
3788         but we want the SSL materal generation and/or validation (if supplied).
3789         So we keep it on.
3790       */
3791       sql_print_warning("Failed to set up SSL because of the"
3792                         " following SSL library error: %s",
3793                         sslGetErrString(error));
3794       opt_use_ssl = 0;
3795       have_ssl= SHOW_OPTION_DISABLED;
3796     }
3797     else
3798     {
3799       /* Check if CA certificate is self signed */
3800       if (warn_self_signed_ca())
3801         return 1;
3802       /* create one SSL that we can use to read information from */
3803       if (!(ssl_acceptor= SSL_new(ssl_acceptor_fd->ssl_context)))
3804         return 1;
3805     }
3806   }
3807   else
3808   {
3809     have_ssl= SHOW_OPTION_DISABLED;
3810   }
3811 #else
3812   have_ssl= SHOW_OPTION_DISABLED;
3813 #endif /* ! EMBEDDED_LIBRARY */
3814   if (des_key_file)
3815     load_des_key_file(des_key_file);
3816   if (init_rsa_keys())
3817     return 1;
3818 #endif /* HAVE_OPENSSL */
3819   return 0;
3820 }
3821 
3822 
end_ssl()3823 static void end_ssl()
3824 {
3825 #ifdef HAVE_OPENSSL
3826 #ifndef EMBEDDED_LIBRARY
3827   if (ssl_acceptor_fd)
3828   {
3829     if (ssl_acceptor)
3830       SSL_free(ssl_acceptor);
3831     free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
3832     ssl_acceptor_fd= 0;
3833   }
3834 #endif /* ! EMBEDDED_LIBRARY */
3835   deinit_rsa_keys();
3836 #endif /* HAVE_OPENSSL */
3837 }
3838 
3839 /**
3840   Generate a UUID and save it into server_uuid variable.
3841 
3842   @return Retur 0 or 1 if an error occurred.
3843  */
generate_server_uuid()3844 static int generate_server_uuid()
3845 {
3846   THD *thd;
3847   Item_func_uuid *func_uuid;
3848   String uuid;
3849 
3850   /*
3851     To be able to run this from boot, we allocate a temporary THD
3852    */
3853   if (!(thd=new THD))
3854   {
3855     sql_print_error("Failed to generate a server UUID because it is failed"
3856                     " to allocate the THD.");
3857     return 1;
3858   }
3859 
3860   thd->thread_stack= (char*) &thd;
3861   thd->store_globals();
3862 
3863   /*
3864     Initialize the variables which are used during "uuid generator
3865     initialization" with values that should normally differ between
3866     mysqlds on the same host. This avoids that another mysqld started
3867     at the same time on the same host get the same "server_uuid".
3868   */
3869   sql_print_information("Salting uuid generator variables, current_pid: %lu, "
3870                         "server_start_time: %lu, bytes_sent: %llu, ",
3871                         current_pid,
3872                         (ulong)server_start_time, thd->status_var.bytes_sent);
3873 
3874   const time_t save_server_start_time= server_start_time;
3875   server_start_time+= ((ulonglong)current_pid << 48) + current_pid;
3876   thd->status_var.bytes_sent= (ulonglong)thd;
3877 
3878   lex_start(thd);
3879   func_uuid= new (thd->mem_root) Item_func_uuid();
3880   func_uuid->fixed= 1;
3881   func_uuid->val_str(&uuid);
3882 
3883   sql_print_information("Generated uuid: '%s', "
3884                         "server_start_time: %lu, bytes_sent: %llu",
3885                         uuid.c_ptr(),
3886                         (ulong)server_start_time, thd->status_var.bytes_sent);
3887   // Restore global variables used for salting
3888   server_start_time = save_server_start_time;
3889 
3890   delete thd;
3891 
3892   strncpy(server_uuid, uuid.c_ptr(), UUID_LENGTH);
3893   DBUG_EXECUTE_IF("server_uuid_deterministic",
3894                   memcpy(server_uuid, "00000000-1111-0000-1111-000000000000",
3895                          UUID_LENGTH););
3896   server_uuid[UUID_LENGTH]= '\0';
3897   return 0;
3898 }
3899 
3900 /**
3901   Save all options which was auto-generated by server-self into the given file.
3902 
3903   @param fname The name of the file in which the auto-generated options will b
3904   e saved.
3905 
3906   @return Return 0 or 1 if an error occurred.
3907  */
flush_auto_options(const char * fname)3908 int flush_auto_options(const char* fname)
3909 {
3910   File fd;
3911   IO_CACHE io_cache;
3912   int result= 0;
3913 
3914   if ((fd= my_open(fname, O_CREAT|O_RDWR, MYF(MY_WME))) < 0)
3915   {
3916     sql_print_error("Failed to create file(file: '%s', errno %d)", fname, my_errno());
3917     return 1;
3918   }
3919 
3920   if (init_io_cache(&io_cache, fd, IO_SIZE*2, WRITE_CACHE, 0L, 0, MYF(MY_WME)))
3921   {
3922     sql_print_error("Failed to create a cache on (file: %s', errno %d)", fname, my_errno());
3923     my_close(fd, MYF(MY_WME));
3924     return 1;
3925   }
3926 
3927   my_b_seek(&io_cache, 0L);
3928   my_b_printf(&io_cache, "%s\n", "[auto]");
3929   my_b_printf(&io_cache, "server-uuid=%s\n", server_uuid);
3930 
3931   if (flush_io_cache(&io_cache) || my_sync(fd, MYF(MY_WME)))
3932     result= 1;
3933 
3934   my_close(fd, MYF(MY_WME));
3935   end_io_cache(&io_cache);
3936   return result;
3937 }
3938 
3939 /**
3940   File 'auto.cnf' resides in the data directory to hold values of options that
3941   server evaluates itself and that needs to be durable to sustain the server
3942   restart. There is only a section ['auto'] in the file. All these options are
3943   in the section. Only one option exists now, it is server_uuid.
3944   Note, the user may not supply any literal value to these auto-options, and
3945   only allowed to trigger (re)evaluation.
3946   For instance, 'server_uuid' value will be evaluated and stored if there is
3947   no corresponding line in the file.
3948   Because of the specifics of the auto-options, they need a seperate storage.
3949   Meanwhile, it is the 'auto.cnf' that has the same structure as 'my.cnf'.
3950 
3951   @todo consider to implement sql-query-able persistent storage by WL#5279.
3952   @return Return 0 or 1 if an error occurred.
3953  */
init_server_auto_options()3954 static int init_server_auto_options()
3955 {
3956   bool flush= false;
3957   char fname[FN_REFLEN];
3958   char *name= (char *)"auto";
3959   const char *groups[]= {"auto", NULL};
3960   char *uuid= 0;
3961   my_option auto_options[]= {
3962     {"server-uuid", 0, "", &uuid, &uuid,
3963       0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
3964     {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
3965   };
3966 
3967   DBUG_ENTER("init_server_auto_options");
3968 
3969   if (NULL == fn_format(fname, "auto.cnf", mysql_data_home, "",
3970                         MY_UNPACK_FILENAME | MY_SAFE_PATH))
3971     DBUG_RETURN(1);
3972 
3973   /* load_defaults require argv[0] is not null */
3974   char **argv= &name;
3975   int argc= 1;
3976   if (!check_file_permissions(fname, false))
3977   {
3978     /*
3979       Found a world writable file hence removing it as it is dangerous to write
3980       a new UUID into the same file.
3981      */
3982     my_delete(fname,MYF(MY_WME));
3983     sql_print_warning("World-writable config file '%s' has been removed.\n",
3984                       fname);
3985   }
3986 
3987   /* load all options in 'auto.cnf'. */
3988   if (my_load_defaults(fname, groups, &argc, &argv, NULL))
3989     DBUG_RETURN(1);
3990 
3991   /*
3992     Record the origial pointer allocated by my_load_defaults for free,
3993     because argv will be changed by handle_options
3994    */
3995   char **old_argv= argv;
3996   if (handle_options(&argc, &argv, auto_options, mysqld_get_one_option))
3997     DBUG_RETURN(1);
3998 
3999   DBUG_PRINT("info", ("uuid=%p=%s server_uuid=%s", uuid, uuid, server_uuid));
4000   if (uuid)
4001   {
4002     if (!Uuid::is_valid(uuid))
4003     {
4004       sql_print_error("The server_uuid stored in auto.cnf file is not a valid UUID.");
4005       goto err;
4006     }
4007     /*
4008       Uuid::is_valid() cannot do strict check on the length as it will be
4009       called by GTID::is_valid() as well (GTID = UUID:seq_no). We should
4010       explicitly add the *length check* here in this function.
4011 
4012       If UUID length is less than '36' (UUID_LENGTH), that error case would have
4013       got caught in above is_valid check. The below check is to make sure that
4014       length is not greater than UUID_LENGTH i.e., there are no extra characters
4015       (Garbage) at the end of the valid UUID.
4016     */
4017     if (strlen(uuid) > UUID_LENGTH)
4018     {
4019       sql_print_error("Garbage characters found at the end of the server_uuid "
4020                       "value in auto.cnf file. It should be of length '%d' "
4021                       "(UUID_LENGTH). Clear it and restart the server. ",
4022                       UUID_LENGTH);
4023       goto err;
4024     }
4025     strcpy(server_uuid, uuid);
4026   }
4027   else
4028   {
4029     DBUG_PRINT("info", ("generating server_uuid"));
4030     flush= TRUE;
4031     /* server_uuid will be set in the function */
4032     if (generate_server_uuid())
4033       goto err;
4034     DBUG_PRINT("info", ("generated server_uuid=%s", server_uuid));
4035     sql_print_warning("No existing UUID has been found, so we assume that this"
4036                       " is the first time that this server has been started."
4037                       " Generating a new UUID: %s.",
4038                       server_uuid);
4039   }
4040   /*
4041     The uuid has been copied to server_uuid, so the memory allocated by
4042     my_load_defaults can be freed now.
4043    */
4044   free_defaults(old_argv);
4045 
4046   if (flush)
4047     DBUG_RETURN(flush_auto_options(fname));
4048   DBUG_RETURN(0);
4049 err:
4050   free_defaults(argv);
4051   DBUG_RETURN(1);
4052 }
4053 
4054 
4055 static bool
initialize_storage_engine(char * se_name,const char * se_kind,plugin_ref * dest_plugin)4056 initialize_storage_engine(char *se_name, const char *se_kind,
4057                           plugin_ref *dest_plugin)
4058 {
4059   LEX_STRING name= { se_name, strlen(se_name) };
4060   plugin_ref plugin;
4061   handlerton *hton;
4062   if ((plugin= ha_resolve_by_name(0, &name, FALSE)))
4063     hton= plugin_data<handlerton*>(plugin);
4064   else
4065   {
4066     sql_print_error("Unknown/unsupported storage engine: %s", se_name);
4067     return true;
4068   }
4069   if (!ha_storage_engine_is_enabled(hton))
4070   {
4071     if (!opt_bootstrap)
4072     {
4073       sql_print_error("Default%s storage engine (%s) is not available",
4074                       se_kind, se_name);
4075       return true;
4076     }
4077     assert(*dest_plugin);
4078   }
4079   else
4080   {
4081     /*
4082       Need to unlock as global_system_variables.table_plugin
4083       was acquired during plugin_init()
4084     */
4085     plugin_ref old_dest_plugin = *dest_plugin;
4086     *dest_plugin = plugin;
4087     plugin_unlock(0, old_dest_plugin);
4088   }
4089   return false;
4090 }
4091 
4092 
init_server_query_cache()4093 static void init_server_query_cache()
4094 {
4095   ulong set_cache_size;
4096 
4097   query_cache.set_min_res_unit(query_cache_min_res_unit);
4098   query_cache.init();
4099 
4100   set_cache_size= query_cache.resize(query_cache_size);
4101   if (set_cache_size != query_cache_size)
4102   {
4103     sql_print_warning(ER_DEFAULT(ER_WARN_QC_RESIZE), query_cache_size,
4104                       set_cache_size);
4105     query_cache_size= set_cache_size;
4106   }
4107 }
4108 
4109 
init_server_components()4110 static int init_server_components()
4111 {
4112   DBUG_ENTER("init_server_components");
4113   /*
4114     We need to call each of these following functions to ensure that
4115     all things are initialized so that unireg_abort() doesn't fail
4116   */
4117   mdl_init();
4118   partitioning_init();
4119   if (table_def_init() | hostname_cache_init(host_cache_size))
4120     unireg_abort(MYSQLD_ABORT_EXIT);
4121 
4122   if (my_timer_initialize())
4123     sql_print_error("Failed to initialize timer component (errno %d).", errno);
4124   else
4125     have_statement_timeout= SHOW_OPTION_YES;
4126 
4127   init_server_query_cache();
4128 
4129   randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
4130   setup_fpu();
4131 #ifdef HAVE_REPLICATION
4132   init_slave_list();
4133 #endif
4134 
4135   /* Setup logs */
4136 
4137   /*
4138     Enable old-fashioned error log, except when the user has requested
4139     help information. Since the implementation of plugin server
4140     variables the help output is now written much later.
4141 
4142     log_error_dest can be:
4143     disabled_my_option     --log-error was not used or --log-error=
4144     ""                     --log-error without arguments (no '=')
4145     filename               --log-error=filename
4146   */
4147 #ifdef _WIN32
4148   /*
4149     Enable the error log file only if console option is not specified
4150     and --help is not used.
4151   */
4152   bool log_errors_to_file= !opt_help && !opt_console;
4153 #else
4154   /*
4155     Enable the error log file only if --log-error=filename or --log-error
4156     was used. Logging to file is disabled by default unlike on Windows.
4157   */
4158   bool log_errors_to_file= !opt_help && (log_error_dest != disabled_my_option);
4159 #endif
4160 
4161   if (log_errors_to_file)
4162   {
4163     // Construct filename if no filename was given by the user.
4164     if (!log_error_dest[0] || log_error_dest == disabled_my_option)
4165       fn_format(errorlog_filename_buff, pidfile_name, mysql_data_home, ".err",
4166                 MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
4167     else
4168       fn_format(errorlog_filename_buff, log_error_dest, mysql_data_home, ".err",
4169                 MY_UNPACK_FILENAME);
4170     /*
4171       log_error_dest may have been set to disabled_my_option or "" if no
4172       argument was passed, but we need to show the real name in SHOW VARIABLES.
4173     */
4174     log_error_dest= errorlog_filename_buff;
4175 
4176     if (open_error_log(errorlog_filename_buff, false))
4177       unireg_abort(MYSQLD_ABORT_EXIT);
4178 
4179   }
4180   else
4181   {
4182     // We are logging to stderr and SHOW VARIABLES should reflect that.
4183     log_error_dest= "stderr";
4184     // Flush messages buffered so far.
4185     flush_error_log_messages();
4186   }
4187 
4188   enter_cond_hook= thd_enter_cond;
4189   exit_cond_hook= thd_exit_cond;
4190   is_killed_hook= (int(*)(const void*))thd_killed;
4191   if (transaction_cache_init())
4192   {
4193     sql_print_error("Out of memory");
4194     unireg_abort(MYSQLD_ABORT_EXIT);
4195   }
4196 
4197   /*
4198     initialize delegates for extension observers, errors have already
4199     been reported in the function
4200   */
4201   if (delegates_init())
4202     unireg_abort(MYSQLD_ABORT_EXIT);
4203 
4204   /* need to configure logging before initializing storage engines */
4205   if (opt_log_slave_updates && !opt_bin_log)
4206   {
4207     sql_print_warning("You need to use --log-bin to make "
4208                     "--log-slave-updates work.");
4209   }
4210 #ifdef WITH_WSREP
4211   if (!WSREP_ON && binlog_format_used && !opt_bin_log)
4212 #else
4213   if (binlog_format_used && !opt_bin_log)
4214 #endif /* WITH_WSREP */
4215     sql_print_warning("You need to use --log-bin to make "
4216                       "--binlog-format work.");
4217 
4218   /* Check that we have not let the format to unspecified at this point */
4219   assert((uint)global_system_variables.binlog_format <=
4220          array_elements(binlog_format_names)-1);
4221 
4222 #ifdef HAVE_REPLICATION
4223   if (opt_log_slave_updates && replicate_same_server_id)
4224   {
4225     if (opt_bin_log)
4226     {
4227       sql_print_error("using --replicate-same-server-id in conjunction with \
4228 --log-slave-updates is impossible, it would lead to infinite loops in this \
4229 server.");
4230       unireg_abort(MYSQLD_ABORT_EXIT);
4231     }
4232     else
4233       sql_print_warning("using --replicate-same-server-id in conjunction with \
4234 --log-slave-updates would lead to infinite loops in this server. However this \
4235 will be ignored as the --log-bin option is not defined.");
4236   }
4237 #endif
4238 
4239   opt_server_id_mask = ~ulong(0);
4240 #ifdef HAVE_REPLICATION
4241   opt_server_id_mask = (opt_server_id_bits == 32)?
4242     ~ ulong(0) : (1 << opt_server_id_bits) -1;
4243   if (server_id != (server_id & opt_server_id_mask))
4244   {
4245     sql_print_error("server-id configured is too large to represent with"
4246                     "server-id-bits configured.");
4247     unireg_abort(MYSQLD_ABORT_EXIT);
4248   }
4249 #endif
4250 
4251 #ifdef WITH_WSREP /* WSREP BEFORE SE */
4252     /*
4253       Wsrep initialization must happen at this point, because:
4254       - opt_bin_logname must be known when starting replication
4255         since SST may need it
4256       - SST may modify binlog index file, so it must be opened
4257         after SST has happened
4258      */
4259   /* It's now safe to use thread specific memory */
4260   mysqld_server_initialized= 1;
4261 
4262   if (!wsrep_recovery)
4263   {
4264     if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
4265     {
4266       wsrep_provider_init(WSREP_NONE);
4267       if (wsrep_init()) unireg_abort(1);
4268     }
4269     else // full wsrep initialization
4270     {
4271       // add basedir/bin to PATH to resolve wsrep script names
4272       char* const tmp_path((char*)alloca(strlen(mysql_home) +
4273                                            strlen("/bin") + 1));
4274       if (tmp_path)
4275       {
4276         strcpy(tmp_path, mysql_home);
4277         strcat(tmp_path, "/bin");
4278         wsrep_prepend_PATH(tmp_path);
4279       }
4280       else
4281       {
4282         WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
4283       }
4284       if (wsrep_before_SE())
4285       {
4286         if (gtid_server_init())
4287         {
4288           sql_print_error("Failed to initialize GTID structures.");
4289           unireg_abort(MYSQLD_ABORT_EXIT);
4290         }
4291 
4292         set_ports(); // this is also called in network_init() later but we need
4293                      // to know mysqld_port now - lp:1071882
4294         wsrep_init_startup(true);
4295       }
4296     }
4297   }
4298 #endif /* WITH_WSREP */
4299   if (opt_bin_log)
4300   {
4301     /* Reports an error and aborts, if the --log-bin's path
4302        is a directory.*/
4303     if (opt_bin_logname &&
4304         opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
4305     {
4306       sql_print_error("Path '%s' is a directory name, please specify \
4307 a file name for --log-bin option", opt_bin_logname);
4308       unireg_abort(MYSQLD_ABORT_EXIT);
4309     }
4310 
4311     /* Reports an error and aborts, if the --log-bin-index's path
4312        is a directory.*/
4313     if (opt_binlog_index_name &&
4314         opt_binlog_index_name[strlen(opt_binlog_index_name) - 1]
4315         == FN_LIBCHAR)
4316     {
4317       sql_print_error("Path '%s' is a directory name, please specify \
4318 a file name for --log-bin-index option", opt_binlog_index_name);
4319       unireg_abort(MYSQLD_ABORT_EXIT);
4320     }
4321 
4322     char buf[FN_REFLEN];
4323     const char *ln;
4324     ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", buf);
4325     if (!opt_bin_logname && !opt_binlog_index_name)
4326     {
4327       /*
4328         User didn't give us info to name the binlog index file.
4329         Picking `hostname`-bin.index like did in 4.x, causes replication to
4330         fail if the hostname is changed later. So, we would like to instead
4331         require a name. But as we don't want to break many existing setups, we
4332         only give warning, not error.
4333       */
4334       sql_print_warning("No argument was provided to --log-bin, and "
4335                         "--log-bin-index was not used; so replication "
4336                         "may break when this MySQL server acts as a "
4337                         "master and has his hostname changed!! Please "
4338                         "use '--log-bin=%s' to avoid this problem.", ln);
4339     }
4340     if (ln == buf)
4341     {
4342       my_free(opt_bin_logname);
4343       opt_bin_logname=my_strdup(key_memory_opt_bin_logname,
4344                                 buf, MYF(0));
4345     }
4346 
4347     /*
4348       Skip opening the index file if we start with --help. This is necessary
4349       to avoid creating the file in an otherwise empty datadir, which will
4350       cause a succeeding 'mysqld --initialize' to fail.
4351     */
4352     if (!opt_help && mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
4353     {
4354       unireg_abort(MYSQLD_ABORT_EXIT);
4355     }
4356   }
4357 
4358   if (opt_bin_log)
4359   {
4360     /*
4361       opt_bin_logname[0] needs to be checked to make sure opt binlog name is
4362       not an empty string, incase it is an empty string default file
4363       extension will be passed
4364      */
4365     log_bin_basename=
4366       rpl_make_log_name(key_memory_MYSQL_BIN_LOG_basename,
4367                         opt_bin_logname, default_logfile_name,
4368                         (opt_bin_logname && opt_bin_logname[0]) ? "" : "-bin");
4369     log_bin_index=
4370       rpl_make_log_name(key_memory_MYSQL_BIN_LOG_index,
4371                         opt_binlog_index_name, log_bin_basename, ".index");
4372     if (log_bin_basename == NULL || log_bin_index == NULL)
4373     {
4374       sql_print_error("Unable to create replication path names:"
4375                       " out of memory or path names too long"
4376                       " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
4377                       " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
4378       unireg_abort(MYSQLD_ABORT_EXIT);
4379     }
4380   }
4381 
4382 #ifndef EMBEDDED_LIBRARY
4383   DBUG_PRINT("debug",
4384              ("opt_bin_logname: %s, opt_relay_logname: %s, pidfile_name: %s",
4385               opt_bin_logname, opt_relay_logname, pidfile_name));
4386   /*
4387     opt_relay_logname[0] needs to be checked to make sure opt relaylog name is
4388     not an empty string, incase it is an empty string default file
4389     extension will be passed
4390    */
4391   relay_log_basename=
4392     rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_basename,
4393                       opt_relay_logname, default_logfile_name,
4394                       (opt_relay_logname && opt_relay_logname[0]) ? "" : "-relay-bin");
4395 
4396   if (relay_log_basename != NULL)
4397     relay_log_index=
4398       rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_index,
4399                         opt_relaylog_index_name, relay_log_basename, ".index");
4400 
4401   if (relay_log_basename == NULL || relay_log_index == NULL)
4402   {
4403     sql_print_error("Unable to create replication path names:"
4404                     " out of memory or path names too long"
4405                     " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
4406                     " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
4407     unireg_abort(MYSQLD_ABORT_EXIT);
4408   }
4409 #endif /* !EMBEDDED_LIBRARY */
4410 
4411   /* call ha_init_key_cache() on all key caches to init them */
4412   process_key_caches(&ha_init_key_cache);
4413 
4414   /* Allow storage engine to give real error messages */
4415   if (ha_init_errors())
4416     DBUG_RETURN(1);
4417 
4418   if (opt_ignore_builtin_innodb)
4419     sql_print_warning("ignore-builtin-innodb is ignored "
4420                       "and will be removed in future releases.");
4421 #ifdef WITH_WSREP
4422     if (!wsrep_before_SE())
4423     {
4424 #endif /* WITH_WSREP */
4425   if (gtid_server_init())
4426   {
4427     sql_print_error("Failed to initialize GTID structures.");
4428     unireg_abort(MYSQLD_ABORT_EXIT);
4429   }
4430 #ifdef WITH_WSREP
4431   }
4432 #endif /* WITH_WSREP */
4433   /*
4434     Set tc_log to point to TC_LOG_DUMMY early in order to allow plugin_init()
4435     to commit attachable transaction after reading from mysql.plugin table.
4436     If necessary tc_log will be adjusted to point to correct TC_LOG instance
4437     later.
4438   */
4439   tc_log= &tc_log_dummy;
4440 
4441   /*Load early plugins */
4442   if (plugin_register_early_plugins(&remaining_argc, remaining_argv,
4443                                     opt_help ?
4444                                       PLUGIN_INIT_SKIP_INITIALIZATION : 0))
4445   {
4446     sql_print_error("Failed to initialize early plugins.");
4447     unireg_abort(MYSQLD_ABORT_EXIT);
4448   }
4449   /* Load builtin plugins, initialize MyISAM, CSV and InnoDB */
4450   if (plugin_register_builtin_and_init_core_se(&remaining_argc,
4451                                                remaining_argv))
4452   {
4453     sql_print_error("Failed to initialize builtin plugins.");
4454     unireg_abort(MYSQLD_ABORT_EXIT);
4455   }
4456   /*
4457     Skip reading the plugin table when starting with --help in order
4458     to also skip initializing InnoDB. This provides a simpler and more
4459     uniform handling of various startup use cases, e.g. when the data
4460     directory does not exist, exists but is empty, exists with InnoDB
4461     system tablespaces present etc.
4462   */
4463 #ifdef WITH_WSREP
4464 /* innodb plugin initializes in the following
4465    plugin_register_dynamic_and_init_all() */
4466 #endif
4467   if (plugin_register_dynamic_and_init_all(&remaining_argc, remaining_argv,
4468                   (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
4469                   (opt_help ? (PLUGIN_INIT_SKIP_INITIALIZATION |
4470                                PLUGIN_INIT_SKIP_PLUGIN_TABLE) : 0)))
4471   {
4472     sql_print_error("Failed to initialize dynamic plugins.");
4473     unireg_abort(MYSQLD_ABORT_EXIT);
4474   }
4475   plugins_are_initialized= TRUE;  /* Don't separate from init function */
4476 
4477   Session_tracker session_track_system_variables_check;
4478   LEX_STRING var_list;
4479   char *tmp_str;
4480   size_t len= strlen(global_system_variables.track_sysvars_ptr);
4481   tmp_str= (char *)my_malloc(PSI_NOT_INSTRUMENTED, len*sizeof(char)+2,
4482                              MYF(MY_WME));
4483   strcpy(tmp_str,global_system_variables.track_sysvars_ptr);
4484   var_list.length= len;
4485   var_list.str= tmp_str;
4486   if (session_track_system_variables_check.server_boot_verify(system_charset_info,
4487 	                                                      var_list))
4488   {
4489     sql_print_error("The variable session_track_system_variables either has "
4490 	            "duplicate values or invalid values.");
4491     if (tmp_str)
4492       my_free(tmp_str);
4493     unireg_abort(MYSQLD_ABORT_EXIT);
4494   }
4495   if (tmp_str)
4496     my_free(tmp_str);
4497   /* we do want to exit if there are any other unknown options */
4498   if (remaining_argc > 1)
4499   {
4500     int ho_error;
4501     struct my_option no_opts[]=
4502     {
4503       {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4504     };
4505     /*
4506       We need to eat any 'loose' arguments first before we conclude
4507       that there are unprocessed options.
4508     */
4509     my_getopt_skip_unknown= 0;
4510 
4511     if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
4512                                   mysqld_get_one_option)))
4513       unireg_abort(MYSQLD_ABORT_EXIT);
4514     /* Add back the program name handle_options removes */
4515     remaining_argc++;
4516     remaining_argv--;
4517     my_getopt_skip_unknown= TRUE;
4518 
4519     if (remaining_argc > 1)
4520     {
4521       sql_print_error("Too many arguments (first extra is '%s').",
4522                       remaining_argv[1]);
4523       sql_print_information("Use --verbose --help to get a list "
4524                             "of available options!");
4525       unireg_abort(MYSQLD_ABORT_EXIT);
4526 
4527     }
4528   }
4529 
4530   if (opt_help)
4531     unireg_abort(MYSQLD_SUCCESS_EXIT);
4532 
4533   /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
4534   if (!my_default_lc_messages->errmsgs->is_loaded())
4535   {
4536     sql_print_error("Unable to read errmsg.sys file");
4537     unireg_abort(MYSQLD_ABORT_EXIT);
4538   }
4539 
4540   /* We have to initialize the storage engines before CSV logging */
4541   if (ha_init())
4542   {
4543     sql_print_error("Can't init databases");
4544     unireg_abort(MYSQLD_ABORT_EXIT);
4545   }
4546 
4547   if (opt_bootstrap)
4548     log_output_options= LOG_FILE;
4549 
4550   /*
4551     Issue a warning if there were specified additional options to the
4552     log-output along with NONE. Probably this wasn't what user wanted.
4553   */
4554   if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
4555     sql_print_warning("There were other values specified to "
4556                       "log-output besides NONE. Disabling slow "
4557                       "and general logs anyway.");
4558 
4559   if (log_output_options & LOG_TABLE)
4560   {
4561     /* Fall back to log files if the csv engine is not loaded. */
4562     LEX_CSTRING csv_name={C_STRING_WITH_LEN("csv")};
4563     if (!plugin_is_ready(csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
4564     {
4565       sql_print_error("CSV engine is not present, falling back to the "
4566                       "log files");
4567       log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
4568     }
4569   }
4570 
4571   query_logger.set_handlers(log_output_options);
4572 
4573   // Open slow log file if enabled.
4574   if (opt_slow_log && query_logger.reopen_log_file(QUERY_LOG_SLOW))
4575     opt_slow_log= false;
4576 
4577   // Open general log file if enabled.
4578   if (opt_general_log && query_logger.reopen_log_file(QUERY_LOG_GENERAL))
4579     opt_general_log= false;
4580 
4581   /*
4582     Set the default storage engines
4583   */
4584   if (initialize_storage_engine(default_storage_engine, "",
4585                                 &global_system_variables.table_plugin))
4586     unireg_abort(MYSQLD_ABORT_EXIT);
4587   if (initialize_storage_engine(default_tmp_storage_engine, " temp",
4588                                 &global_system_variables.temp_table_plugin))
4589     unireg_abort(MYSQLD_ABORT_EXIT);
4590 
4591 #ifdef WITH_WSREP
4592   if (!opt_bin_log)
4593   {
4594     wsrep_emulate_bin_log= 1;
4595   }
4596 #endif
4597   if (!opt_bootstrap && !opt_noacl)
4598   {
4599     std::string disabled_se_str(opt_disabled_storage_engines);
4600     ha_set_normalized_disabled_se_str(disabled_se_str);
4601 
4602     // Log warning if default_storage_engine is a disabled storage engine.
4603     handlerton *default_se_handle=
4604       plugin_data<handlerton*>(global_system_variables.table_plugin);
4605     if (ha_is_storage_engine_disabled(default_se_handle))
4606       sql_print_warning("default_storage_engine is set to a "
4607                         "disabled storage engine %s.", default_storage_engine);
4608 
4609     // Log warning if default_tmp_storage_engine is a disabled storage engine.
4610     handlerton *default_tmp_se_handle=
4611       plugin_data<handlerton*>(global_system_variables.temp_table_plugin);
4612     if (ha_is_storage_engine_disabled(default_tmp_se_handle))
4613       sql_print_warning("default_tmp_storage_engine is set to a "
4614                         "disabled storage engine %s.",
4615                         default_tmp_storage_engine);
4616 
4617   }
4618 
4619   if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log))
4620   {
4621     if (opt_bin_log)
4622       tc_log= &mysql_bin_log;
4623     else
4624 #ifdef WITH_WSREP
4625       if (WSREP_ON)
4626         tc_log=  &tc_log_dummy;
4627       else
4628         /*
4629          * wsrep hton grows total_ha_2pc count to 2, even in native mysql mode.
4630          * Have to force using tc_log_dummy here, as tc_log_mmap segfaults
4631          */
4632         tc_log=  &tc_log_dummy;
4633 #else
4634       tc_log= &tc_log_mmap;
4635 #endif /* WITH_WSREP */
4636   }
4637 
4638 #ifdef WITH_WSREP
4639   WSREP_DEBUG("Initial TC log open: %s",
4640               (tc_log == &mysql_bin_log) ? "binlog" :
4641               (tc_log == &tc_log_mmap) ? "mmap" :
4642               (tc_log == &tc_log_dummy) ? "dummy" : "unknown"
4643               );
4644 #endif
4645   if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
4646   {
4647     sql_print_error("Can't init tc log");
4648     unireg_abort(MYSQLD_ABORT_EXIT);
4649   }
4650   (void)RUN_HOOK(server_state, before_recovery, (NULL));
4651 
4652   if (ha_recover(0))
4653   {
4654     unireg_abort(MYSQLD_ABORT_EXIT);
4655   }
4656 
4657 #ifdef WITH_WSREP
4658   if (!wsrep_recovery)
4659   {
4660 #endif /* WITH_WSREP */
4661   /// @todo: this looks suspicious, revisit this /sven
4662   enum_gtid_mode gtid_mode= get_gtid_mode(GTID_MODE_LOCK_NONE);
4663 
4664   if (gtid_mode == GTID_MODE_ON &&
4665       _gtid_consistency_mode != GTID_CONSISTENCY_MODE_ON)
4666   {
4667     sql_print_error("GTID_MODE = ON requires ENFORCE_GTID_CONSISTENCY = ON.");
4668     unireg_abort(MYSQLD_ABORT_EXIT);
4669   }
4670 
4671   if (opt_bin_log)
4672   {
4673     /*
4674       Configures what object is used by the current log to store processed
4675       gtid(s). This is necessary in the MYSQL_BIN_LOG::MYSQL_BIN_LOG to
4676       corretly compute the set of previous gtids.
4677     */
4678     assert(!mysql_bin_log.is_relay_log);
4679     mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock();
4680     mysql_mutex_lock(log_lock);
4681 
4682     if (mysql_bin_log.open_binlog(opt_bin_logname, 0,
4683                                   max_binlog_size, false,
4684                                   true/*need_lock_index=true*/,
4685                                   true/*need_sid_lock=true*/,
4686                                   NULL))
4687     {
4688       mysql_mutex_unlock(log_lock);
4689       unireg_abort(MYSQLD_ABORT_EXIT);
4690     }
4691     mysql_mutex_unlock(log_lock);
4692   }
4693 
4694 #ifdef WITH_WSREP
4695   }
4696 #endif /* WITH_WSREP */
4697   if (opt_myisam_log)
4698     (void) mi_log(1);
4699 
4700 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
4701   if (locked_in_memory && !getuid())
4702   {
4703     if (setreuid((uid_t)-1, 0) == -1)
4704     {                        // this should never happen
4705       sql_print_error("setreuid: %s", strerror(errno));
4706       unireg_abort(MYSQLD_ABORT_EXIT);
4707     }
4708     if (mlockall(MCL_CURRENT))
4709     {
4710       sql_print_warning("Failed to lock memory. Errno: %d\n",errno); /* purecov: inspected */
4711       locked_in_memory= 0;
4712     }
4713 #ifndef _WIN32
4714     if (user_info)
4715       set_user(mysqld_user, user_info);
4716 #endif
4717   }
4718   else
4719 #endif
4720     locked_in_memory=0;
4721 
4722   /* Initialize the optimizer cost module */
4723   init_optimizer_cost_module(true);
4724   ft_init_stopwords();
4725 
4726   init_max_user_conn();
4727   init_update_queries();
4728   DBUG_RETURN(0);
4729 }
4730 
4731 
4732 #ifndef EMBEDDED_LIBRARY
4733 #ifdef _WIN32
4734 
handle_shutdown(void * arg)4735 extern "C" void *handle_shutdown(void *arg)
4736 {
4737   MSG msg;
4738   my_thread_init();
4739   /* This call should create the message queue for this thread. */
4740   PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
4741   if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
4742   {
4743     sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN), my_progname);
4744     abort_loop= true;
4745     close_connections();
4746     my_thread_end();
4747     my_thread_exit(0);
4748   }
4749 #ifdef WITH_WSREP
4750   mysql_mutex_init(key_LOCK_wsrep_ready,
4751                    &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST);
4752   mysql_cond_init(key_COND_wsrep_ready, &COND_wsrep_ready);
4753   mysql_mutex_init(key_LOCK_wsrep_sst,
4754                    &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST);
4755   mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst);
4756   mysql_mutex_init(key_LOCK_wsrep_sst_init,
4757                    &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST);
4758   mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init);
4759   mysql_mutex_init(key_LOCK_wsrep_rollback,
4760                    &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST);
4761   mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback);
4762   mysql_mutex_init(key_LOCK_wsrep_replaying,
4763                    &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST);
4764   mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying);
4765   mysql_mutex_init(key_LOCK_wsrep_slave_threads,
4766                    &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST);
4767   mysql_mutex_init(key_LOCK_wsrep_desync,
4768                    &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST);
4769 #endif
4770   return 0;
4771 }
4772 
4773 
create_shutdown_thread()4774 static void create_shutdown_thread()
4775 {
4776   hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
4777   my_thread_attr_t thr_attr;
4778   DBUG_ENTER("create_shutdown_thread");
4779 
4780   my_thread_attr_init(&thr_attr);
4781 
4782   if (my_thread_create(&shutdown_thr_handle, &thr_attr, handle_shutdown, 0))
4783     sql_print_warning("Can't create thread to handle shutdown requests"
4784                       " (errno= %d)", errno);
4785   my_thread_attr_destroy(&thr_attr);
4786   // On "Stop Service" we have to do regular shutdown
4787   Service.SetShutdownEvent(hEventShutdown);
4788 }
4789 #endif /* _WIN32 */
4790 
4791 #ifndef NDEBUG
4792 /*
4793   Debugging helper function to keep the locale database
4794   (see sql_locale.cc) and max_month_name_length and
4795   max_day_name_length variable values in consistent state.
4796 */
test_lc_time_sz()4797 static void test_lc_time_sz()
4798 {
4799   DBUG_ENTER("test_lc_time_sz");
4800   for (MY_LOCALE **loc= my_locales; *loc; loc++)
4801   {
4802     size_t max_month_len= 0;
4803     size_t max_day_len = 0;
4804     for (const char **month= (*loc)->month_names->type_names; *month; month++)
4805     {
4806       set_if_bigger(max_month_len,
4807                     my_numchars_mb(&my_charset_utf8_general_ci,
4808                                    *month, *month + strlen(*month)));
4809     }
4810     for (const char **day= (*loc)->day_names->type_names; *day; day++)
4811     {
4812       set_if_bigger(max_day_len,
4813                     my_numchars_mb(&my_charset_utf8_general_ci,
4814                                    *day, *day + strlen(*day)));
4815     }
4816     if ((*loc)->max_month_name_length != max_month_len ||
4817         (*loc)->max_day_name_length != max_day_len)
4818     {
4819       DBUG_PRINT("Wrong max day name(or month name) length for locale:",
4820                  ("%s", (*loc)->name));
4821       assert(0);
4822     }
4823   }
4824   DBUG_VOID_RETURN;
4825 }
4826 #endif//NDEBUG
4827 
4828 /*
4829   @brief : Set opt_super_readonly to user supplied value before
4830            enabling communication channels to accept user connections
4831 */
4832 
set_super_read_only_post_init()4833 static void set_super_read_only_post_init()
4834 {
4835   opt_super_readonly= super_read_only;
4836 }
4837 
4838 #ifdef _WIN32
win_main(int argc,char ** argv)4839 int win_main(int argc, char **argv)
4840 #else
4841 int mysqld_main(int argc, char **argv)
4842 #endif
4843 {
4844   /*
4845     Perform basic thread library and malloc initialization,
4846     to be able to read defaults files and parse options.
4847   */
4848   my_progname= argv[0];
4849 
4850 #ifndef _WIN32
4851 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4852   pre_initialize_performance_schema();
4853 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
4854   // For windows, my_init() is called from the win specific mysqld_main
4855   if (my_init())                 // init my_sys library & pthreads
4856   {
4857     sql_print_error("my_init() failed.");
4858     flush_error_log_messages();
4859     return 1;
4860   }
4861 #endif /* _WIN32 */
4862 #ifdef WITH_WSREP
4863   wsrep_filter_new_cluster (&argc, argv);
4864 #endif /* WITH_WSREP */
4865 
4866   orig_argc= argc;
4867   orig_argv= argv;
4868   my_getopt_use_args_separator= TRUE;
4869   my_defaults_read_login_file= FALSE;
4870   if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
4871   {
4872     flush_error_log_messages();
4873     return 1;
4874   }
4875   my_getopt_use_args_separator= FALSE;
4876   defaults_argc= argc;
4877   defaults_argv= argv;
4878   remaining_argc= argc;
4879   remaining_argv= argv;
4880 
4881   /* Must be initialized early for comparison of options name */
4882   system_charset_info= &my_charset_utf8_general_ci;
4883 
4884   /* Write mysys error messages to the error log. */
4885   local_message_hook= error_log_print;
4886 
4887   int ho_error;
4888 
4889 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4890   /*
4891     Initialize the array of performance schema instrument configurations.
4892   */
4893   init_pfs_instrument_array();
4894 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
4895 
4896   ho_error= handle_early_options();
4897 
4898 #if !defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
4899 
4900   if (opt_bootstrap && opt_daemonize)
4901   {
4902     fprintf(stderr, "Bootstrap and daemon options are incompatible.\n");
4903     exit(MYSQLD_ABORT_EXIT);
4904   }
4905 
4906   if (opt_daemonize && log_error_dest == disabled_my_option &&
4907       (isatty(STDOUT_FILENO) || isatty(STDERR_FILENO)))
4908   {
4909     fprintf(stderr, "Please enable --log-error option or set appropriate "
4910                     "redirections for standard output and/or standard error "
4911                     "in daemon mode.\n");
4912     exit(MYSQLD_ABORT_EXIT);
4913   }
4914 
4915   if (opt_daemonize)
4916   {
4917     if (chdir("/") < 0)
4918     {
4919       fprintf(stderr, "Cannot change to root director: %s\n",
4920                       strerror(errno));
4921       exit(MYSQLD_ABORT_EXIT);
4922     }
4923 
4924     if ((pipe_write_fd= mysqld::runtime::mysqld_daemonize()) < 0)
4925     {
4926       fprintf(stderr, "mysqld_daemonize failed \n");
4927       exit(MYSQLD_ABORT_EXIT);
4928     }
4929   }
4930 #endif
4931 
4932   init_sql_statement_names();
4933   sys_var_init();
4934   ulong requested_open_files;
4935   adjust_related_options(&requested_open_files);
4936 
4937 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4938   if (ho_error == 0)
4939   {
4940     if (!opt_help && !opt_bootstrap)
4941     {
4942       /* Add sizing hints from the server sizing parameters. */
4943       pfs_param.m_hints.m_table_definition_cache= table_def_size;
4944       pfs_param.m_hints.m_table_open_cache= table_cache_size;
4945       pfs_param.m_hints.m_max_connections= max_connections;
4946       pfs_param.m_hints.m_open_files_limit= requested_open_files;
4947       pfs_param.m_hints.m_max_prepared_stmt_count= max_prepared_stmt_count;
4948 
4949       PSI_hook= initialize_performance_schema(&pfs_param);
4950       if (PSI_hook == NULL && pfs_param.m_enabled)
4951       {
4952         pfs_param.m_enabled= false;
4953         sql_print_warning("Performance schema disabled (reason: init failed).");
4954       }
4955     }
4956   }
4957 #else
4958   /*
4959     Other provider of the instrumentation interface should
4960     initialize PSI_hook here:
4961     - HAVE_PSI_INTERFACE is for the instrumentation interface
4962     - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
4963       of the interface,
4964     but there could be alternate implementations, which is why
4965     these two defines are kept separate.
4966   */
4967 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
4968 
4969 #ifdef HAVE_PSI_INTERFACE
4970   /*
4971     Obtain the current performance schema instrumentation interface,
4972     if available.
4973   */
4974   if (PSI_hook)
4975   {
4976     PSI *psi_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION);
4977     if (likely(psi_server != NULL))
4978     {
4979       set_psi_server(psi_server);
4980 
4981       /*
4982         Now that we have parsed the command line arguments, and have initialized
4983         the performance schema itself, the next step is to register all the
4984         server instruments.
4985       */
4986       init_server_psi_keys();
4987       /* Instrument the main thread */
4988       PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_main, NULL, 0);
4989       PSI_THREAD_CALL(set_thread_os_id)(psi);
4990       PSI_THREAD_CALL(set_thread)(psi);
4991 
4992       /*
4993         Now that some instrumentation is in place,
4994         recreate objects which were initialised early,
4995         so that they are instrumented as well.
4996       */
4997       my_thread_global_reinit();
4998     }
4999   }
5000 #endif /* HAVE_PSI_INTERFACE */
5001 
5002   init_error_log();
5003 
5004   /* Initialize audit interface globals. Audit plugins are inited later. */
5005   mysql_audit_initialize();
5006 
5007 #ifndef EMBEDDED_LIBRARY
5008   Srv_session::module_init();
5009 #endif
5010 
5011   /*
5012     Perform basic query log initialization. Should be called after
5013     MY_INIT, as it initializes mutexes.
5014   */
5015   query_logger.init();
5016 
5017   if (ho_error)
5018   {
5019     /*
5020       Parsing command line option failed,
5021       Since we don't have a workable remaining_argc/remaining_argv
5022       to continue the server initialization, this is as far as this
5023       code can go.
5024       This is the best effort to log meaningful messages:
5025       - messages will be printed to stderr, which is not redirected yet,
5026       - messages will be printed in the NT event log, for windows.
5027     */
5028     flush_error_log_messages();
5029     /*
5030       Not enough initializations for unireg_abort()
5031       Using exit() for windows.
5032     */
5033     exit (MYSQLD_ABORT_EXIT);
5034   }
5035 
5036   if (init_common_variables())
5037     unireg_abort(MYSQLD_ABORT_EXIT);        // Will do exit
5038 
5039   my_init_signals();
5040 
5041   size_t guardize= 0;
5042 #ifndef _WIN32
5043   int retval= pthread_attr_getguardsize(&connection_attrib, &guardize);
5044   assert(retval == 0);
5045   if (retval != 0)
5046     guardize= my_thread_stack_size;
5047 #endif
5048 
5049 #if defined(__ia64__) || defined(__ia64)
5050   /*
5051     Peculiar things with ia64 platforms - it seems we only have half the
5052     stack size in reality, so we have to double it here
5053   */
5054   guardize= my_thread_stack_size;
5055 #endif
5056 
5057   my_thread_attr_setstacksize(&connection_attrib,
5058                             my_thread_stack_size + guardize);
5059 
5060   {
5061     /* Retrieve used stack size;  Needed for checking stack overflows */
5062     size_t stack_size= 0;
5063     my_thread_attr_getstacksize(&connection_attrib, &stack_size);
5064 
5065     /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
5066     if (stack_size && stack_size < (my_thread_stack_size + guardize))
5067     {
5068       sql_print_warning("Asked for %lu thread stack, but got %ld",
5069                         my_thread_stack_size + guardize, (long) stack_size);
5070 #if defined(__ia64__) || defined(__ia64)
5071       my_thread_stack_size= stack_size / 2;
5072 #else
5073       my_thread_stack_size= static_cast<ulong>(stack_size - guardize);
5074 #endif
5075     }
5076   }
5077 
5078 #ifndef NDEBUG
5079   test_lc_time_sz();
5080   srand(static_cast<uint>(time(NULL)));
5081 #endif
5082 
5083 #ifndef _WIN32
5084   if ((user_info= check_user(mysqld_user)))
5085   {
5086 #if HAVE_CHOWN
5087     if (unlikely(opt_initialize))
5088     {
5089       /* need to change the owner of the freshly created data directory */
5090       MY_STAT stat;
5091       char errbuf[MYSYS_STRERROR_SIZE];
5092       bool must_chown= true;
5093 
5094       /* fetch the directory's owner */
5095       if (!my_stat(mysql_real_data_home, &stat, MYF(0)))
5096       {
5097         sql_print_information("Can't read data directory's stats (%d): %s."
5098                               "Assuming that it's not owned by the same user/group",
5099                               my_errno(),
5100                               my_strerror(errbuf, sizeof(errbuf), my_errno()));
5101       }
5102       /* Don't change it if it's already the same as SElinux stops this */
5103       else if(stat.st_uid == user_info->pw_uid &&
5104               stat.st_gid == user_info->pw_gid)
5105         must_chown= false;
5106 
5107       if (must_chown &&
5108           chown(mysql_real_data_home, user_info->pw_uid, user_info->pw_gid)
5109          )
5110       {
5111         sql_print_error("Can't change data directory owner to %s", mysqld_user);
5112         unireg_abort(1);
5113       }
5114     }
5115 #endif
5116 
5117 
5118 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
5119     if (locked_in_memory) // getuid() == 0 here
5120       set_effective_user(user_info);
5121     else
5122 #endif
5123       set_user(mysqld_user, user_info);
5124   }
5125 #endif // !_WIN32
5126 
5127   /*
5128    initiate key migration if any one of the migration specific
5129    options are provided.
5130   */
5131   if (opt_keyring_migration_source ||
5132       opt_keyring_migration_destination ||
5133       migrate_connect_options)
5134   {
5135     Migrate_keyring mk;
5136     if (mk.init(remaining_argc, remaining_argv,
5137                 opt_keyring_migration_source,
5138                 opt_keyring_migration_destination,
5139                 opt_keyring_migration_user,
5140                 opt_keyring_migration_host,
5141                 opt_keyring_migration_password,
5142                 opt_keyring_migration_socket,
5143                 opt_keyring_migration_port))
5144     {
5145       sql_print_error(ER_DEFAULT(ER_KEYRING_MIGRATION_STATUS),
5146                       "failed");
5147       log_error_dest= "stderr";
5148       flush_error_log_messages();
5149       unireg_abort(MYSQLD_ABORT_EXIT);
5150     }
5151 
5152     if (mk.execute())
5153     {
5154       sql_print_error(ER_DEFAULT(ER_KEYRING_MIGRATION_STATUS),
5155                       "failed");
5156       log_error_dest= "stderr";
5157       flush_error_log_messages();
5158       unireg_abort(MYSQLD_ABORT_EXIT);
5159     }
5160 
5161     sql_print_information(ER_DEFAULT(ER_KEYRING_MIGRATION_STATUS),
5162                           "successful");
5163     log_error_dest= "stderr";
5164     flush_error_log_messages();
5165     unireg_abort(MYSQLD_SUCCESS_EXIT);
5166   }
5167 
5168   /*
5169    We have enough space for fiddling with the argv, continue
5170   */
5171   if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help)
5172   {
5173     sql_print_error("failed to set datadir to %s", mysql_real_data_home);
5174     unireg_abort(MYSQLD_ABORT_EXIT);        /* purecov: inspected */
5175   }
5176 
5177   //If the binlog is enabled, one needs to provide a server-id
5178   if (opt_bin_log && !(server_id_supplied) )
5179   {
5180     sql_print_error("You have enabled the binary log, but you haven't provided "
5181                     "the mandatory server-id. Please refer to the proper "
5182                     "server start-up parameters documentation");
5183     unireg_abort(MYSQLD_ABORT_EXIT);
5184   }
5185 
5186   /*
5187    The subsequent calls may take a long time : e.g. innodb log read.
5188    Thus set the long running service control manager timeout
5189   */
5190 #if defined(_WIN32)
5191   Service.SetSlowStarting(slow_start_timeout);
5192 #endif
5193 
5194 #ifdef WITH_WSREP
5195   /*
5196     Make sure that SSL library gets initialized before WSREP provider
5197     is loaded. This is to ensure that possible server side initialization
5198     does not have any side effects while the provider is already running
5199     with open SSL sessions.
5200   */
5201   ssl_start();
5202 #endif /* */
5203   if (init_server_components())
5204     unireg_abort(MYSQLD_ABORT_EXIT);
5205 
5206 #ifdef WITH_WSREP /* WSREP AFTER SE */
5207   if (wsrep_recovery)
5208   {
5209     wsrep_recover();
5210     unireg_abort(0);
5211   }
5212 #endif /* WITH_WSREP */
5213   /*
5214     Each server should have one UUID. We will create it automatically, if it
5215     does not exist.
5216    */
5217   if (init_server_auto_options())
5218   {
5219     sql_print_error("Initialization of the server's UUID failed because it could"
5220                     " not be read from the auto.cnf file. If this is a new"
5221                     " server, the initialization failed because it was not"
5222                     " possible to generate a new UUID.");
5223     unireg_abort(MYSQLD_ABORT_EXIT);
5224   }
5225 
5226   /*
5227     Add server_uuid to the sid_map.  This must be done after
5228     server_uuid has been initialized in init_server_auto_options and
5229     after the binary log (and sid_map file) has been initialized in
5230     init_server_components().
5231 
5232     No error message is needed: init_sid_map() prints a message.
5233 
5234     Strictly speaking, this is not currently needed when
5235     opt_bin_log==0, since the variables that gtid_state->init
5236     initializes are not currently used in that case.  But we call it
5237     regardless to avoid possible future bugs if gtid_state ever
5238     needs to do anything else.
5239   */
5240   global_sid_lock->wrlock();
5241   int gtid_ret= gtid_state->init();
5242   global_sid_lock->unlock();
5243 
5244   if (gtid_ret)
5245     unireg_abort(MYSQLD_ABORT_EXIT);
5246 
5247   // Initialize executed_gtids from mysql.gtid_executed table.
5248   if (gtid_state->read_gtid_executed_from_table() == -1)
5249     unireg_abort(1);
5250 
5251   if (opt_bin_log)
5252   {
5253     /*
5254       Initialize GLOBAL.GTID_EXECUTED and GLOBAL.GTID_PURGED from
5255       gtid_executed table and binlog files during server startup.
5256     */
5257     Gtid_set *executed_gtids=
5258       const_cast<Gtid_set *>(gtid_state->get_executed_gtids());
5259     Gtid_set *lost_gtids=
5260       const_cast<Gtid_set *>(gtid_state->get_lost_gtids());
5261     Gtid_set *gtids_only_in_table=
5262       const_cast<Gtid_set *>(gtid_state->get_gtids_only_in_table());
5263     Gtid_set *previous_gtids_logged=
5264       const_cast<Gtid_set *>(gtid_state->get_previous_gtids_logged());
5265 
5266     Gtid_set purged_gtids_from_binlog(global_sid_map, global_sid_lock);
5267     Gtid_set gtids_in_binlog(global_sid_map, global_sid_lock);
5268     Gtid_set gtids_in_binlog_not_in_table(global_sid_map, global_sid_lock);
5269 
5270     if (mysql_bin_log.init_gtid_sets(&gtids_in_binlog,
5271                                      &purged_gtids_from_binlog,
5272                                      opt_master_verify_checksum,
5273                                      true/*true=need lock*/,
5274                                      NULL/*trx_parser*/,
5275                                      NULL/*gtid_partial_trx*/,
5276                                      true/*is_server_starting*/))
5277       unireg_abort(MYSQLD_ABORT_EXIT);
5278 
5279     global_sid_lock->wrlock();
5280 
5281     purged_gtids_from_binlog.dbug_print("purged_gtids_from_binlog");
5282     gtids_in_binlog.dbug_print("gtids_in_binlog");
5283 
5284     if (!gtids_in_binlog.is_empty() &&
5285         !gtids_in_binlog.is_subset(executed_gtids))
5286     {
5287       gtids_in_binlog_not_in_table.add_gtid_set(&gtids_in_binlog);
5288       if (!executed_gtids->is_empty())
5289         gtids_in_binlog_not_in_table.remove_gtid_set(executed_gtids);
5290       /*
5291         Save unsaved GTIDs into gtid_executed table, in the following
5292         four cases:
5293           1. the upgrade case.
5294           2. the case that a slave is provisioned from a backup of
5295              the master and the slave is cleaned by RESET MASTER
5296              and RESET SLAVE before this.
5297           3. the case that no binlog rotation happened from the
5298              last RESET MASTER on the server before it crashes.
5299           4. The set of GTIDs of the last binlog is not saved into the
5300              gtid_executed table if server crashes, so we save it into
5301              gtid_executed table and executed_gtids during recovery
5302              from the crash.
5303       */
5304       if (gtid_state->save(&gtids_in_binlog_not_in_table) == -1)
5305       {
5306         global_sid_lock->unlock();
5307         unireg_abort(MYSQLD_ABORT_EXIT);
5308       }
5309       executed_gtids->add_gtid_set(&gtids_in_binlog_not_in_table);
5310     }
5311 
5312     /* gtids_only_in_table= executed_gtids - gtids_in_binlog */
5313     if (gtids_only_in_table->add_gtid_set(executed_gtids) !=
5314         RETURN_STATUS_OK)
5315     {
5316       global_sid_lock->unlock();
5317       unireg_abort(MYSQLD_ABORT_EXIT);
5318     }
5319     gtids_only_in_table->remove_gtid_set(&gtids_in_binlog);
5320     /*
5321       lost_gtids = executed_gtids -
5322                    (gtids_in_binlog - purged_gtids_from_binlog)
5323                  = gtids_only_in_table + purged_gtids_from_binlog;
5324     */
5325     assert(lost_gtids->is_empty());
5326     if (lost_gtids->add_gtid_set(gtids_only_in_table) != RETURN_STATUS_OK ||
5327         lost_gtids->add_gtid_set(&purged_gtids_from_binlog) !=
5328         RETURN_STATUS_OK)
5329     {
5330       global_sid_lock->unlock();
5331       unireg_abort(MYSQLD_ABORT_EXIT);
5332     }
5333 
5334     /* Prepare previous_gtids_logged for next binlog */
5335     if (previous_gtids_logged->add_gtid_set(&gtids_in_binlog) !=
5336         RETURN_STATUS_OK)
5337     {
5338       global_sid_lock->unlock();
5339       unireg_abort(MYSQLD_ABORT_EXIT);
5340     }
5341 
5342     /*
5343       Write the previous set of gtids at this point because during
5344       the creation of the binary log this is not done as we cannot
5345       move the init_gtid_sets() to a place before openning the binary
5346       log. This requires some investigation.
5347 
5348       /Alfranio
5349     */
5350     Previous_gtids_log_event prev_gtids_ev(&gtids_in_binlog);
5351 
5352     global_sid_lock->unlock();
5353 
5354     (prev_gtids_ev.common_footer)->checksum_alg=
5355       static_cast<enum_binlog_checksum_alg>(binlog_checksum_options);
5356 
5357     if (prev_gtids_ev.write(mysql_bin_log.get_log_file()))
5358       unireg_abort(MYSQLD_ABORT_EXIT);
5359     mysql_bin_log.add_bytes_written(
5360       prev_gtids_ev.common_header->data_written);
5361 
5362     if (flush_io_cache(mysql_bin_log.get_log_file()) ||
5363         mysql_file_sync(mysql_bin_log.get_log_file()->file, MYF(MY_WME)))
5364       unireg_abort(MYSQLD_ABORT_EXIT);
5365     mysql_bin_log.update_binlog_end_pos();
5366 
5367 #ifdef HAVE_REPLICATION
5368     if (opt_bin_log && expire_logs_days)
5369     {
5370       time_t purge_time= server_start_time - expire_logs_days * 24 * 60 * 60;
5371       DBUG_EXECUTE_IF("expire_logs_always_at_start",
5372                       { purge_time= my_time(0); });
5373       if (purge_time >= 0)
5374         mysql_bin_log.purge_logs_before_date(purge_time, true);
5375     }
5376 #endif
5377 
5378     (void) RUN_HOOK(server_state, after_engine_recovery, (NULL));
5379   }
5380 
5381 
5382   if (init_ssl())
5383     unireg_abort(MYSQLD_ABORT_EXIT);
5384   if (network_init())
5385     unireg_abort(MYSQLD_ABORT_EXIT);
5386 
5387 #ifdef _WIN32
5388 #ifndef EMBEDDED_LIBRARY
5389   if (opt_require_secure_transport &&
5390       !opt_enable_shared_memory && !opt_use_ssl &&
5391       !opt_initialize && !opt_bootstrap)
5392   {
5393     sql_print_error("Server is started with --require-secure-transport=ON "
5394                     "but no secure transports (SSL or Shared Memory) are "
5395                     "configured.");
5396     unireg_abort(MYSQLD_ABORT_EXIT);
5397   }
5398 #endif
5399 
5400 #endif
5401 
5402   /*
5403    Initialize my_str_malloc(), my_str_realloc() and my_str_free()
5404   */
5405   my_str_malloc= &my_str_malloc_mysqld;
5406   my_str_free= &my_str_free_mysqld;
5407   my_str_realloc= &my_str_realloc_mysqld;
5408 
5409   error_handler_hook= my_message_sql;
5410 
5411   /* Save pid of this process in a file */
5412   if (!opt_bootstrap)
5413     create_pid_file();
5414 
5415 
5416   /* Read the optimizer cost model configuration tables */
5417   if (!opt_bootstrap)
5418     reload_optimizer_cost_constants();
5419 
5420   if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
5421       my_tz_init((THD *)0, default_tz_name, opt_bootstrap) ||
5422       grant_init(opt_noacl))
5423   {
5424     abort_loop= true;
5425     sql_print_error("Fatal error: Failed to initialize ACL/grant/time zones "
5426                     "structures or failed to remove temporary table files.");
5427 
5428     delete_pid_file(MYF(MY_WME));
5429 
5430     unireg_abort(MYSQLD_ABORT_EXIT);
5431   }
5432 
5433   if (!opt_bootstrap)
5434     servers_init(0);
5435 
5436   if (!opt_noacl)
5437   {
5438 #ifdef HAVE_DLOPEN
5439     udf_init();
5440 #endif
5441   }
5442 
5443   init_status_vars();
5444   /* If running with bootstrap, do not start replication. */
5445   if (opt_bootstrap)
5446     opt_skip_slave_start= 1;
5447 
5448   check_binlog_cache_size(NULL);
5449   check_binlog_stmt_cache_size(NULL);
5450 
5451   binlog_unsafe_map_init();
5452 
5453   /* If running with bootstrap, do not start replication. */
5454   if (!opt_bootstrap)
5455   {
5456     // Make @@slave_skip_errors show the nice human-readable value.
5457     set_slave_skip_errors(&opt_slave_skip_errors);
5458 
5459     /*
5460       init_slave() must be called after the thread keys are created.
5461     */
5462     if (server_id != 0)
5463       init_slave(); /* Ignoring errors while configuring replication. */
5464   }
5465 
5466 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5467   initialize_performance_schema_acl(opt_bootstrap);
5468   /*
5469     Do not check the structure of the performance schema tables
5470     during bootstrap:
5471     - the tables are not supposed to exist yet, bootstrap will create them
5472     - a check would print spurious error messages
5473   */
5474   if (! opt_bootstrap)
5475     check_performance_schema();
5476 #endif
5477 
5478   initialize_information_schema_acl();
5479 
5480   execute_ddl_log_recovery();
5481   (void) RUN_HOOK(server_state, after_recovery, (NULL));
5482 
5483   if (Events::init(opt_noacl || opt_bootstrap))
5484     unireg_abort(MYSQLD_ABORT_EXIT);
5485 
5486 #ifdef WITH_WSREP /* WSREP AFTER SE */
5487   if (opt_bootstrap)
5488   {
5489     /*! bootstrap wsrep init was taken care of above */
5490   }
5491   else
5492   {
5493     wsrep_SE_initialized(WSREP_SE_INIT_RESULT_SUCCESS);
5494 
5495     if (wsrep_before_SE())
5496     {
5497       /*! in case of SST wsrep waits for wsrep->sst_received */
5498       wsrep_sst_continue();
5499     }
5500     else
5501     {
5502       wsrep_init_startup (false);
5503     }
5504 
5505     wsrep_create_appliers(wsrep_slave_threads - 1);
5506   }
5507 #endif /* WITH_WSREP */
5508 #ifndef _WIN32
5509   //  Start signal handler thread.
5510   start_signal_handler();
5511 #endif
5512 
5513   if (opt_bootstrap)
5514   {
5515     start_processing_signals();
5516 
5517     int error= bootstrap(mysql_stdin);
5518     unireg_abort(error ? MYSQLD_ABORT_EXIT : MYSQLD_SUCCESS_EXIT);
5519   }
5520 
5521   if (opt_init_file && *opt_init_file)
5522   {
5523     if (read_init_file(opt_init_file))
5524       unireg_abort(MYSQLD_ABORT_EXIT);
5525   }
5526 
5527   /*
5528     Event must be invoked after error_handler_hook is assigned to
5529     my_message_sql, otherwise my_message will not cause the event to abort.
5530   */
5531   if (mysql_audit_notify(AUDIT_EVENT(MYSQL_AUDIT_SERVER_STARTUP_STARTUP),
5532                          (const char **) argv, argc))
5533     unireg_abort(MYSQLD_ABORT_EXIT);
5534 
5535 #ifdef _WIN32
5536   create_shutdown_thread();
5537 #endif
5538   start_handle_manager();
5539 
5540   create_compress_gtid_table_thread();
5541 
5542   sql_print_information(ER_DEFAULT(ER_STARTUP),
5543                         my_progname,
5544                         server_version,
5545 #ifdef HAVE_SYS_UN_H
5546                         (opt_bootstrap ? (char*) "" : mysqld_unix_port),
5547 #else
5548                         (char*) "",
5549 #endif
5550                          mysqld_port,
5551                          MYSQL_COMPILATION_COMMENT);
5552 #if defined(_WIN32)
5553   Service.SetRunning();
5554 #endif
5555 
5556   start_processing_signals();
5557 
5558 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
5559   /* engine specific hook, to be made generic */
5560   if (ndb_wait_setup_func && ndb_wait_setup_func(opt_ndb_wait_setup))
5561   {
5562     sql_print_warning("NDB : Tables not available after %lu seconds."
5563                       "  Consider increasing --ndb-wait-setup value",
5564                       opt_ndb_wait_setup);
5565   }
5566 #endif
5567 
5568   if (!opt_bootstrap)
5569   {
5570     /*
5571       Execute an I_S query to implicitly check for tables using the deprecated
5572       partition engine. No need to do this during bootstrap. We ignore the
5573       return value from the query execution. Note that this must be done after
5574       NDB is initialized to avoid polluting the server with invalid table shares.
5575     */
5576     if (!opt_disable_partition_check)
5577     {
5578       sql_print_information(
5579               "Executing 'SELECT * FROM INFORMATION_SCHEMA.TABLES;' "
5580               "to get a list of tables using the deprecated partition "
5581               "engine.");
5582 
5583       sql_print_information("Beginning of list of non-natively partitioned tables");
5584       (void) bootstrap_single_query(
5585               "SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES "
5586               "WHERE CREATE_OPTIONS LIKE '%partitioned%';");
5587       sql_print_information("End of list of non-natively partitioned tables");
5588     }
5589   }
5590 
5591   /*
5592     Set opt_super_readonly here because if opt_super_readonly is set
5593     in get_option, it will create problem while setting up event scheduler.
5594   */
5595   set_super_read_only_post_init();
5596 
5597   DBUG_PRINT("info", ("Block, listening for incoming connections"));
5598 
5599   (void)MYSQL_SET_STAGE(0 ,__FILE__, __LINE__);
5600 
5601   server_operational_state= SERVER_OPERATING;
5602 
5603   (void) RUN_HOOK(server_state, before_handle_connection, (NULL));
5604 
5605 #if defined(_WIN32)
5606   setup_conn_event_handler_threads();
5607 #else
5608   mysql_mutex_lock(&LOCK_socket_listener_active);
5609   // Make it possible for the signal handler to kill the listener.
5610   socket_listener_active= true;
5611   mysql_mutex_unlock(&LOCK_socket_listener_active);
5612 
5613   if (opt_daemonize)
5614     mysqld::runtime::signal_parent(pipe_write_fd,1);
5615 
5616   mysqld_socket_acceptor->connection_event_loop();
5617 #endif /* _WIN32 */
5618   server_operational_state= SERVER_SHUTTING_DOWN;
5619 
5620   DBUG_PRINT("info", ("No longer listening for incoming connections"));
5621 
5622   mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
5623                      MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
5624                      MYSQLD_SUCCESS_EXIT);
5625 
5626   terminate_compress_gtid_table_thread();
5627   /*
5628     Save set of GTIDs of the last binlog into gtid_executed table
5629     on server shutdown.
5630   */
5631   if (opt_bin_log)
5632     if (gtid_state->save_gtids_of_last_binlog_into_table(false))
5633       sql_print_warning("Failed to save the set of Global Transaction "
5634                         "Identifiers of the last binary log into the "
5635                         "mysql.gtid_executed table while the server was "
5636                         "shutting down. The next server restart will make "
5637                         "another attempt to save Global Transaction "
5638                         "Identifiers into the table.");
5639 
5640 #ifndef _WIN32
5641   mysql_mutex_lock(&LOCK_socket_listener_active);
5642   // Notify the signal handler that we have stopped listening for connections.
5643   socket_listener_active= false;
5644   mysql_cond_broadcast(&COND_socket_listener_active);
5645   mysql_mutex_unlock(&LOCK_socket_listener_active);
5646 #endif // !_WIN32
5647 
5648 #ifdef HAVE_PSI_THREAD_INTERFACE
5649   /*
5650     Disable the main thread instrumentation,
5651     to avoid recording events during the shutdown.
5652   */
5653   PSI_THREAD_CALL(delete_current_thread)();
5654 #endif
5655 
5656   DBUG_PRINT("info", ("Waiting for shutdown proceed"));
5657   int ret= 0;
5658 #ifdef _WIN32
5659   if (shutdown_thr_handle.handle)
5660     ret= my_thread_join(&shutdown_thr_handle, NULL);
5661   shutdown_thr_handle.handle= NULL;
5662   if (0 != ret)
5663     sql_print_warning("Could not join shutdown thread. error:%d", ret);
5664 #else
5665   if (signal_thread_id.thread != 0)
5666     ret= my_thread_join(&signal_thread_id, NULL);
5667   signal_thread_id.thread= 0;
5668   if (0 != ret)
5669     sql_print_warning("Could not join signal_thread. error:%d", ret);
5670 #endif
5671 
5672   clean_up(1);
5673   mysqld_exit(MYSQLD_SUCCESS_EXIT);
5674 }
5675 
5676 
5677 /****************************************************************************
5678   Main and thread entry function for Win32
5679   (all this is needed only to run mysqld as a service on WinNT)
5680 ****************************************************************************/
5681 
5682 #if defined(_WIN32)
mysql_service(void * p)5683 int mysql_service(void *p)
5684 {
5685   if (my_thread_init())
5686   {
5687     flush_error_log_messages();
5688     return 1;
5689   }
5690 
5691   if (use_opt_args)
5692     win_main(opt_argc, opt_argv);
5693   else
5694     win_main(Service.my_argc, Service.my_argv);
5695 
5696   my_thread_end();
5697   return 0;
5698 }
5699 
5700 
5701 /* Quote string if it contains space, else copy */
5702 
add_quoted_string(char * to,const char * from,char * to_end)5703 static char *add_quoted_string(char *to, const char *from, char *to_end)
5704 {
5705   uint length= (uint) (to_end-to);
5706 
5707   if (!strchr(from, ' '))
5708     return strmake(to, from, length-1);
5709   return strxnmov(to, length-1, "\"", from, "\"", NullS);
5710 }
5711 
5712 
5713 /**
5714   Handle basic handling of services, like installation and removal.
5715 
5716   @param argv             Pointer to argument list
5717   @param servicename    Internal name of service
5718   @param displayname    Display name of service (in taskbar ?)
5719   @param file_path    Path to this program
5720   @param startup_option Startup option to mysqld
5721 
5722   @retval
5723     0   option handled
5724   @retval
5725     1   Could not handle option
5726 */
5727 
5728 static bool
default_service_handling(char ** argv,const char * servicename,const char * displayname,const char * file_path,const char * extra_opt,const char * account_name)5729 default_service_handling(char **argv,
5730        const char *servicename,
5731        const char *displayname,
5732        const char *file_path,
5733        const char *extra_opt,
5734        const char *account_name)
5735 {
5736   char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
5737   const char *opt_delim;
5738   end= path_and_service + sizeof(path_and_service)-3;
5739 
5740   /* We have to quote filename if it contains spaces */
5741   pos= add_quoted_string(path_and_service, file_path, end);
5742   if (extra_opt && *extra_opt)
5743   {
5744     /*
5745      Add option after file_path. There will be zero or one extra option.  It's
5746      assumed to be --defaults-file=file but isn't checked.  The variable (not
5747      the option name) should be quoted if it contains a string.
5748     */
5749     *pos++= ' ';
5750     if (opt_delim= strchr(extra_opt, '='))
5751     {
5752       size_t length= ++opt_delim - extra_opt;
5753       pos= my_stpnmov(pos, extra_opt, length);
5754     }
5755     else
5756       opt_delim= extra_opt;
5757 
5758     pos= add_quoted_string(pos, opt_delim, end);
5759   }
5760   /* We must have servicename last */
5761   *pos++= ' ';
5762   (void) add_quoted_string(pos, servicename, end);
5763 
5764   if (Service.got_service_option(argv, "install"))
5765   {
5766     Service.Install(1, servicename, displayname, path_and_service,
5767                     account_name);
5768     return 0;
5769   }
5770   if (Service.got_service_option(argv, "install-manual"))
5771   {
5772     Service.Install(0, servicename, displayname, path_and_service,
5773                     account_name);
5774     return 0;
5775   }
5776   if (Service.got_service_option(argv, "remove"))
5777   {
5778     Service.Remove(servicename);
5779     return 0;
5780   }
5781   return 1;
5782 }
5783 
5784 
mysqld_main(int argc,char ** argv)5785 int mysqld_main(int argc, char **argv)
5786 {
5787   /*
5788     When several instances are running on the same machine, we
5789     need to have an  unique  named  hEventShudown  through the
5790     application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
5791   */
5792   int10_to_str((int) GetCurrentProcessId(),my_stpcpy(shutdown_event_name,
5793                                                   "MySQLShutdown"), 10);
5794 
5795   /* Must be initialized early for comparison of service name */
5796   system_charset_info= &my_charset_utf8_general_ci;
5797 
5798 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5799   pre_initialize_performance_schema();
5800 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
5801 
5802   if (my_init())
5803   {
5804     sql_print_error("my_init() failed.");
5805     flush_error_log_messages();
5806     return 1;
5807   }
5808 
5809   if (Service.GetOS())  /* true NT family */
5810   {
5811     char file_path[FN_REFLEN];
5812     my_path(file_path, argv[0], "");          /* Find name in path */
5813     fn_format(file_path,argv[0],file_path,"",
5814               MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
5815 
5816     if (argc == 2)
5817     {
5818       if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
5819                                     file_path, "", NULL))
5820         return 0;
5821       if (Service.IsService(argv[1]))        /* Start an optional service */
5822       {
5823         /*
5824           Only add the service name to the groups read from the config file
5825           if it's not "MySQL". (The default service name should be 'mysqld'
5826           but we started a bad tradition by calling it MySQL from the start
5827           and we are now stuck with it.
5828         */
5829         if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
5830           load_default_groups[load_default_groups_sz-2]= argv[1];
5831         windows_service= true;
5832         Service.Init(argv[1], mysql_service);
5833         return 0;
5834       }
5835     }
5836     else if (argc == 3) /* install or remove any optional service */
5837     {
5838       if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
5839                                     NULL))
5840         return 0;
5841       if (Service.IsService(argv[2]))
5842       {
5843         /*
5844           mysqld was started as
5845           mysqld --defaults-file=my_path\my.ini service-name
5846         */
5847         use_opt_args=1;
5848         opt_argc= 2;        // Skip service-name
5849         opt_argv=argv;
5850         windows_service= true;
5851         if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
5852           load_default_groups[load_default_groups_sz-2]= argv[2];
5853         Service.Init(argv[2], mysql_service);
5854         return 0;
5855       }
5856     }
5857     else if (argc == 4 || argc == 5)
5858     {
5859       /*
5860         This may seem strange, because we handle --local-service while
5861         preserving 4.1's behavior of allowing any one other argument that is
5862         passed to the service on startup. (The assumption is that this is
5863         --defaults-file=file, but that was not enforced in 4.1, so we don't
5864         enforce it here.)
5865       */
5866       const char *extra_opt= NullS;
5867       const char *account_name = NullS;
5868       int index;
5869       for (index = 3; index < argc; index++)
5870       {
5871         if (!strcmp(argv[index], "--local-service"))
5872           account_name= "NT AUTHORITY\\LocalService";
5873         else
5874           extra_opt= argv[index];
5875       }
5876 
5877       if (argc == 4 || account_name)
5878         if (!default_service_handling(argv, argv[2], argv[2], file_path,
5879                                       extra_opt, account_name))
5880           return 0;
5881     }
5882     else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
5883     {
5884       /* start the default service */
5885       windows_service= true;
5886       Service.Init(MYSQL_SERVICENAME, mysql_service);
5887       return 0;
5888     }
5889   }
5890   /* Start as standalone server */
5891   Service.my_argc=argc;
5892   Service.my_argv=argv;
5893   mysql_service(NULL);
5894   return 0;
5895 }
5896 #endif // _WIN32
5897 #endif // !EMBEDDED_LIBRARY
5898 
5899 
read_init_file(char * file_name)5900 static bool read_init_file(char *file_name)
5901 {
5902   MYSQL_FILE *file;
5903   DBUG_ENTER("read_init_file");
5904   DBUG_PRINT("enter",("name: %s",file_name));
5905 
5906   sql_print_information("Execution of init_file \'%s\' started.", file_name);
5907 
5908   if (!(file= mysql_file_fopen(key_file_init, file_name,
5909                                O_RDONLY, MYF(MY_WME))))
5910     DBUG_RETURN(TRUE);
5911   (void) bootstrap(file);
5912   mysql_file_fclose(file, MYF(MY_WME));
5913 
5914   sql_print_information("Execution of init_file \'%s\' ended.", file_name);
5915 
5916   DBUG_RETURN(FALSE);
5917 }
5918 
5919 
5920 /****************************************************************************
5921   Handle start options
5922 ******************************************************************************/
5923 
5924 /**
5925   Process command line options flagged as 'early'.
5926   Some components needs to be initialized as early as possible,
5927   because the rest of the server initialization depends on them.
5928   Options that needs to be parsed early includes:
5929   - the performance schema, when compiled in,
5930   - options related to the help,
5931   - options related to the bootstrap
5932   The performance schema needs to be initialized as early as possible,
5933   before to-be-instrumented objects of the server are initialized.
5934 */
handle_early_options()5935 int handle_early_options()
5936 {
5937   int ho_error;
5938   vector<my_option> all_early_options;
5939   all_early_options.reserve(100);
5940 
5941   my_getopt_register_get_addr(NULL);
5942   /* Skip unknown options so that they may be processed later */
5943   my_getopt_skip_unknown= TRUE;
5944 
5945   /* Add the system variables parsed early */
5946   sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
5947 
5948   /* Add the command line options parsed early */
5949   for (my_option *opt= my_long_early_options;
5950        opt->name != NULL;
5951        opt++)
5952     all_early_options.push_back(*opt);
5953 
5954   add_terminator(&all_early_options);
5955 
5956   my_getopt_error_reporter= option_error_reporter;
5957   my_charset_error_reporter= charset_error_reporter;
5958 
5959   ho_error= handle_options(&remaining_argc, &remaining_argv,
5960                            &all_early_options[0], mysqld_get_one_option);
5961   if (ho_error == 0)
5962   {
5963     /* Add back the program name handle_options removes */
5964     remaining_argc++;
5965     remaining_argv--;
5966 
5967     /* adjust the bootstrap options */
5968     if (opt_bootstrap)
5969     {
5970       sql_print_warning("--bootstrap is deprecated. "
5971                         "Please consider using --initialize instead");
5972     }
5973     if (opt_initialize_insecure)
5974       opt_initialize= TRUE;
5975     if (opt_initialize)
5976     {
5977       if (opt_bootstrap)
5978       {
5979         sql_print_error("Both --bootstrap and --initialize specified."
5980                         " Please pick one. Exiting.");
5981         ho_error= EXIT_AMBIGUOUS_OPTION;
5982       }
5983       opt_bootstrap= TRUE;
5984     }
5985   }
5986 
5987   // Swap with an empty vector, i.e. delete elements and free allocated space.
5988   vector<my_option>().swap(all_early_options);
5989 
5990   return ho_error;
5991 }
5992 
5993 /**
5994   Adjust @c open_files_limit.
5995   Computation is  based on:
5996   - @c max_connections,
5997   - @c table_cache_size,
5998   - the platform max open file limit.
5999 */
adjust_open_files_limit(ulong * requested_open_files)6000 void adjust_open_files_limit(ulong *requested_open_files)
6001 {
6002   ulong limit_1;
6003   ulong limit_2;
6004   ulong limit_3;
6005   ulong request_open_files;
6006   ulong effective_open_files;
6007 
6008   /* MyISAM requires two file handles per table. */
6009   limit_1= 10 + max_connections + table_cache_size * 2;
6010 
6011   /*
6012     We are trying to allocate no less than max_connections*5 file
6013     handles (i.e. we are trying to set the limit so that they will
6014     be available).
6015   */
6016   limit_2= max_connections * 5;
6017 
6018   /* Try to allocate no less than 5000 by default. */
6019   limit_3= open_files_limit ? open_files_limit : 5000;
6020 
6021   request_open_files= max<ulong>(max<ulong>(limit_1, limit_2), limit_3);
6022 
6023   /* Notice: my_set_max_open_files() may return more than requested. */
6024   effective_open_files= my_set_max_open_files(request_open_files);
6025 
6026   if (effective_open_files < request_open_files)
6027   {
6028     if (open_files_limit == 0)
6029     {
6030       sql_print_warning("Changed limits: max_open_files: %lu (requested %lu)",
6031                         effective_open_files, request_open_files);
6032     }
6033     else
6034     {
6035       sql_print_warning("Could not increase number of max_open_files to "
6036                         "more than %lu (request: %lu)",
6037                         effective_open_files, request_open_files);
6038     }
6039   }
6040 
6041   open_files_limit= effective_open_files;
6042   if (requested_open_files)
6043     *requested_open_files= min<ulong>(effective_open_files, request_open_files);
6044 }
6045 
adjust_max_connections(ulong requested_open_files)6046 void adjust_max_connections(ulong requested_open_files)
6047 {
6048   ulong limit;
6049 
6050   limit= requested_open_files - 10 - TABLE_OPEN_CACHE_MIN * 2;
6051 
6052   if (limit < max_connections)
6053   {
6054     sql_print_warning("Changed limits: max_connections: %lu (requested %lu)",
6055                       limit, max_connections);
6056 
6057     // This can be done unprotected since it is only called on startup.
6058     max_connections= limit;
6059   }
6060 }
6061 
adjust_table_cache_size(ulong requested_open_files)6062 void adjust_table_cache_size(ulong requested_open_files)
6063 {
6064   ulong limit;
6065 
6066   limit= max<ulong>((requested_open_files - 10 - max_connections) / 2,
6067                     TABLE_OPEN_CACHE_MIN);
6068 
6069   if (limit < table_cache_size)
6070   {
6071     sql_print_warning("Changed limits: table_open_cache: %lu (requested %lu)",
6072                       limit, table_cache_size);
6073 
6074     table_cache_size= limit;
6075   }
6076 
6077   table_cache_size_per_instance= table_cache_size / table_cache_instances;
6078 }
6079 
adjust_table_def_size()6080 void adjust_table_def_size()
6081 {
6082   ulong default_value;
6083   sys_var *var;
6084 
6085   default_value= min<ulong> (400 + table_cache_size / 2, 2000);
6086   var= intern_find_sys_var(STRING_WITH_LEN("table_definition_cache"));
6087   assert(var != NULL);
6088   var->update_default(default_value);
6089 
6090   if (! table_definition_cache_specified)
6091     table_def_size= default_value;
6092 }
6093 
adjust_related_options(ulong * requested_open_files)6094 void adjust_related_options(ulong *requested_open_files)
6095 {
6096   /* In bootstrap, disable grant tables (we are about to create them) */
6097   if (opt_bootstrap)
6098     opt_noacl= 1;
6099 
6100   /* The order is critical here, because of dependencies. */
6101   adjust_open_files_limit(requested_open_files);
6102   adjust_max_connections(*requested_open_files);
6103   adjust_table_cache_size(*requested_open_files);
6104   adjust_table_def_size();
6105 }
6106 
6107 vector<my_option> all_options;
6108 
6109 struct my_option my_long_early_options[]=
6110 {
6111   {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
6112    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6113 #if !defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
6114   {"daemonize", 0, "Run mysqld as sysv daemon", &opt_daemonize,
6115     &opt_daemonize, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,0},
6116 #endif
6117   {"skip-grant-tables", 0,
6118    "Start without grant tables. This gives all users FULL ACCESS to all tables.",
6119    &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6120    0},
6121   {"help", '?', "Display this help and exit.",
6122    &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
6123    0, 0},
6124   {"verbose", 'v', "Used with --help option for detailed help.",
6125    &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6126   {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
6127    NO_ARG, 0, 0, 0, 0, 0, 0},
6128   {"initialize", 0, "Create the default database and exit."
6129    " Create a super user with a random expired password and store it into the log.",
6130    &opt_initialize, &opt_initialize, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6131   {"initialize-insecure", 0, "Create the default database and exit."
6132    " Create a super user with empty password.",
6133    &opt_initialize_insecure, &opt_initialize_insecure, 0, GET_BOOL, NO_ARG,
6134    0, 0, 0, 0, 0, 0},
6135   {"disable-partition-engine-check", 0,
6136    "Skip the check for non-natively partitioned tables during bootstrap. "
6137    "This option is deprecated along with the partition engine.",
6138    &opt_disable_partition_check, &opt_disable_partition_check, 0, GET_BOOL,
6139    NO_ARG, TRUE, 0, 0, 0, 0, 0},
6140   {"keyring-migration-source", OPT_KEYRING_MIGRATION_SOURCE,
6141    "Keyring plugin from where the keys needs to "
6142    "be migrated to. This option must be specified along with "
6143    "--keyring-migration-destination.",
6144    &opt_keyring_migration_source, &opt_keyring_migration_source,
6145    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6146   {"keyring-migration-destination", OPT_KEYRING_MIGRATION_DESTINATION,
6147    "Keyring plugin to which the keys are "
6148    "migrated to. This option must be specified along with "
6149    "--keyring-migration-source.",
6150    &opt_keyring_migration_destination, &opt_keyring_migration_destination,
6151    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6152   {"keyring-migration-user", OPT_KEYRING_MIGRATION_USER,
6153    "User to login to server.",
6154    &opt_keyring_migration_user, &opt_keyring_migration_user,
6155    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6156   {"keyring-migration-host", OPT_KEYRING_MIGRATION_HOST, "Connect to host.",
6157    &opt_keyring_migration_host, &opt_keyring_migration_host,
6158    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6159   {"keyring-migration-password", OPT_KEYRING_MIGRATION_PASSWORD,
6160    "Password to use when connecting to server during keyring migration. "
6161    "If password value is not specified then it will be asked from the tty.",
6162    0, 0, 0, GET_PASSWORD, OPT_ARG, 0, 0, 0, 0, 0, 0},
6163   {"keyring-migration-socket", OPT_KEYRING_MIGRATION_SOCKET,
6164    "The socket file to use for connection.",
6165    &opt_keyring_migration_socket, &opt_keyring_migration_socket,
6166    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6167   {"keyring-migration-port", OPT_KEYRING_MIGRATION_PORT,
6168    "Port number to use for connection.",
6169    &opt_keyring_migration_port, &opt_keyring_migration_port,
6170    0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6171   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
6172 };
6173 
6174 /**
6175   System variables are automatically command-line options (few
6176   exceptions are documented in sys_var.h), so don't need
6177   to be listed here.
6178 */
6179 
6180 struct my_option my_long_options[]=
6181 {
6182 #ifdef HAVE_REPLICATION
6183   {"abort-slave-event-count", 0,
6184    "Option used by mysql-test for debugging and testing of replication.",
6185    &abort_slave_event_count,  &abort_slave_event_count,
6186    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6187 #endif /* HAVE_REPLICATION */
6188   {"allow-suspicious-udfs", 0,
6189    "Allows use of UDFs consisting of only one symbol xxx() "
6190    "without corresponding xxx_init() or xxx_deinit(). That also means "
6191    "that one can load any function from any library, for example exit() "
6192    "from libc.so",
6193    &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
6194    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6195   {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
6196    "will also set transaction isolation level 'serializable'.", 0, 0, 0,
6197    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6198   /*
6199     Because Sys_var_bit does not support command-line options, we need to
6200     explicitely add one for --autocommit
6201   */
6202   {"autocommit", 0, "Set default value for autocommit (0 or 1)",
6203    &opt_autocommit, &opt_autocommit, 0,
6204    GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL},
6205   {"binlog-do-db", OPT_BINLOG_DO_DB,
6206    "Tells the master it should log updates for the specified database, "
6207    "and exclude all others not explicitly mentioned.",
6208    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6209   {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
6210    "Tells the master that updates to the given database should not be logged to the binary log.",
6211    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6212   {"binlog-row-event-max-size", 0,
6213    "The maximum size of a row-based binary log event in bytes. Rows will be "
6214    "grouped into events smaller than this size if possible. "
6215    "The value has to be a multiple of 256.",
6216    &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
6217    0, GET_ULONG, REQUIRED_ARG,
6218    /* def_value */ 8192, /* min_value */  256, /* max_value */ ULONG_MAX,
6219    /* sub_size */     0, /* block_size */ 256,
6220    /* app_type */ 0
6221   },
6222   {"character-set-client-handshake", 0,
6223    "Don't ignore client side character set value sent during handshake.",
6224    &opt_character_set_client_handshake,
6225    &opt_character_set_client_handshake,
6226     0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
6227   {"character-set-filesystem", 0,
6228    "Set the filesystem character set.",
6229    &character_set_filesystem_name,
6230    &character_set_filesystem_name,
6231    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6232   {"character-set-server", 'C', "Set the default character set.",
6233    &default_character_set_name, &default_character_set_name,
6234    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6235   {"chroot", 'r', "Chroot mysqld daemon during startup.",
6236    &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
6237    0, 0, 0, 0, 0, 0},
6238   {"collation-server", 0, "Set the default collation.",
6239    &default_collation_name, &default_collation_name,
6240    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6241   {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
6242    &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
6243    0, 0, 0},
6244   {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
6245    NO_ARG, 0, 0, 0, 0, 0, 0},
6246   /* default-storage-engine should have "MyISAM" as def_value. Instead
6247      of initializing it here it is done in init_common_variables() due
6248      to a compiler bug in Sun Studio compiler. */
6249   {"default-storage-engine", 0, "The default storage engine for new tables",
6250    &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
6251    0, 0, 0, 0, 0, 0 },
6252   {"default-tmp-storage-engine", 0,
6253     "The default storage engine for new explict temporary tables",
6254    &default_tmp_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
6255    0, 0, 0, 0, 0, 0 },
6256   {"default-time-zone", 0, "Set the default time zone.",
6257    &default_tz_name, &default_tz_name,
6258    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6259 #ifdef HAVE_OPENSSL
6260   {"des-key-file", 0,
6261    "Load keys for des_encrypt() and des_encrypt from given file.",
6262    &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
6263    0, 0, 0, 0, 0, 0},
6264 #endif /* HAVE_OPENSSL */
6265 #ifdef HAVE_REPLICATION
6266   {"disconnect-slave-event-count", 0,
6267    "Option used by mysql-test for debugging and testing of replication.",
6268    &disconnect_slave_event_count, &disconnect_slave_event_count,
6269    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6270 #endif /* HAVE_REPLICATION */
6271   {"exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0,
6272    GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
6273 
6274   {"external-locking", 0, "Use system (external) locking (disabled by "
6275    "default).  With this option enabled you can run myisamchk to test "
6276    "(not repair) tables while the MySQL server is running. Disable with "
6277    "--skip-external-locking.", &opt_external_locking, &opt_external_locking,
6278    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6279   /* We must always support the next option to make scripts like mysqltest
6280      easier to do */
6281   {"gdb", 0,
6282    "Set up signals usable for debugging.",
6283    &opt_debugging, &opt_debugging,
6284    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6285 #if defined(HAVE_LINUX_LARGE_PAGES) || defined (HAVE_SOLARIS_LARGE_PAGES)
6286   {"super-large-pages", 0, "Enable support for super large pages.",
6287    &opt_super_large_pages, &opt_super_large_pages, 0,
6288    GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
6289 #endif
6290   {"ignore-db-dir", OPT_IGNORE_DB_DIRECTORY,
6291    "Specifies a directory to add to the ignore list when collecting "
6292    "database names from the datadir. Put a blank argument to reset "
6293    "the list accumulated so far.", 0, 0, 0, GET_STR, REQUIRED_ARG,
6294    0, 0, 0, 0, 0, 0},
6295   {"language", 'L',
6296    "Client error messages in given language. May be given as a full path. "
6297    "Deprecated. Use --lc-messages-dir instead.",
6298    &lc_messages_dir_ptr, &lc_messages_dir_ptr, 0,
6299    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6300   {"lc-messages", 0,
6301    "Set the language used for the error messages.",
6302    &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
6303    0, 0, 0, 0, 0, 0 },
6304   {"lc-time-names", 0,
6305    "Set the language used for the month names and the days of the week.",
6306    &lc_time_names_name, &lc_time_names_name,
6307    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6308   {"log-bin", OPT_BIN_LOG,
6309    "Log update queries in binary format. Optional (but strongly recommended "
6310    "to avoid replication problems if server's hostname changes) argument "
6311    "should be the chosen location for the binary log files.",
6312    &opt_bin_logname, &opt_bin_logname, 0, GET_STR_ALLOC,
6313    OPT_ARG, 0, 0, 0, 0, 0, 0},
6314   {"log-bin-index", 0,
6315    "File that holds the names for binary log files.",
6316    &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
6317    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6318   {"relay-log-index", 0,
6319    "File that holds the names for relay log files.",
6320    &opt_relaylog_index_name, &opt_relaylog_index_name, 0, GET_STR,
6321    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6322   {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
6323    &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
6324    OPT_ARG, 0, 0, 0, 0, 0, 0},
6325   {"log-raw", 0,
6326    "Log to general log before any rewriting of the query. For use in debugging, not production as "
6327    "sensitive information may be logged.",
6328    &opt_general_log_raw, &opt_general_log_raw,
6329    0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0 },
6330   {"log-short-format", 0,
6331    "Don't log extra information to update and slow-query logs.",
6332    &opt_short_log_format, &opt_short_log_format,
6333    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6334   {"log-tc", 0,
6335    "Path to transaction coordinator log (used for transactions that affect "
6336    "more than one storage engine, when binary log is disabled).",
6337    &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
6338    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6339   {"log-tc-size", 0, "Size of transaction coordinator log.",
6340    &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
6341    REQUIRED_ARG, TC_LOG_MIN_PAGES * my_getpagesize(),
6342    TC_LOG_MIN_PAGES * my_getpagesize(), ULONG_MAX, 0,
6343    my_getpagesize(), 0},
6344   {"master-info-file", 0,
6345    "The location and name of the file that remembers the master and where "
6346    "the I/O replication thread is in the master's binlogs.",
6347    &master_info_file, &master_info_file, 0, GET_STR,
6348    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6349   {"master-retry-count", OPT_MASTER_RETRY_COUNT,
6350    "The number of tries the slave will make to connect to the master before giving up. "
6351    "Deprecated option, use 'CHANGE MASTER TO master_retry_count = <num>' instead.",
6352    &master_retry_count, &master_retry_count, 0, GET_ULONG,
6353    REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
6354 #ifdef HAVE_REPLICATION
6355   {"max-binlog-dump-events", 0,
6356    "Option used by mysql-test for debugging and testing of replication.",
6357    &max_binlog_dump_events, &max_binlog_dump_events, 0,
6358    GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6359 #endif /* HAVE_REPLICATION */
6360   {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
6361    &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6362   {"old-style-user-limits", 0,
6363    "Enable old-style user limits (before 5.0.3, user resources were counted "
6364    "per each user+host vs. per account).",
6365    &opt_old_style_user_limits, &opt_old_style_user_limits,
6366    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6367   {"port-open-timeout", 0,
6368    "Maximum time in seconds to wait for the port to become free. "
6369    "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
6370    GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6371   {"replicate-do-db", OPT_REPLICATE_DO_DB,
6372    "Tells the slave thread to restrict replication to the specified database. "
6373    "To specify more than one database, use the directive multiple times, "
6374    "once for each database. Note that this will only work if you do not use "
6375    "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
6376    "while having selected a different or no database. If you need cross "
6377    "database updates to work, make sure you have 3.23.28 or later, and use "
6378    "replicate-wild-do-table=db_name.%.",
6379    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6380   {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
6381    "Tells the slave thread to restrict replication to the specified table. "
6382    "To specify more than one table, use the directive multiple times, once "
6383    "for each table. This will work for cross-database updates, in contrast "
6384    "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6385   {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
6386    "Tells the slave thread to not replicate to the specified database. To "
6387    "specify more than one database to ignore, use the directive multiple "
6388    "times, once for each database. This option will not work if you use "
6389    "cross database updates. If you need cross database updates to work, "
6390    "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
6391    "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6392   {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
6393    "Tells the slave thread to not replicate to the specified table. To specify "
6394    "more than one table to ignore, use the directive multiple times, once for "
6395    "each table. This will work for cross-database updates, in contrast to "
6396    "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6397   {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
6398    "Updates to a database with a different name than the original. Example: "
6399    "replicate-rewrite-db=master_db_name->slave_db_name.",
6400    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6401 #ifdef HAVE_REPLICATION
6402   {"replicate-same-server-id", 0,
6403    "In replication, if set to 1, do not skip events having our server id. "
6404    "Default value is 0 (to break infinite loops in circular replication). "
6405    "Can't be set to 1 if --log-slave-updates is used.",
6406    &replicate_same_server_id, &replicate_same_server_id,
6407    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6408 #endif
6409   {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
6410    "Tells the slave thread to restrict replication to the tables that match "
6411    "the specified wildcard pattern. To specify more than one table, use the "
6412    "directive multiple times, once for each table. This will work for cross-"
6413    "database updates. Example: replicate-wild-do-table=foo%.bar% will "
6414    "replicate only updates to tables in all databases that start with foo "
6415    "and whose table names start with bar.",
6416    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6417   {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
6418    "Tells the slave thread to not replicate to the tables that match the "
6419    "given wildcard pattern. To specify more than one table to ignore, use "
6420    "the directive multiple times, once for each table. This will work for "
6421    "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
6422    "will not do updates to tables in databases that start with foo and whose "
6423    "table names start with bar.",
6424    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6425   {"safe-user-create", 0,
6426    "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
6427    &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
6428    NO_ARG, 0, 0, 0, 0, 0, 0},
6429   {"show-slave-auth-info", 0,
6430    "Show user and password in SHOW SLAVE HOSTS on this master.",
6431    &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
6432    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6433   {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
6434    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6435   {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
6436    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6437   {"skip-slave-start", 0,
6438    "If set, slave is not autostarted.", &opt_skip_slave_start,
6439    &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6440   {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
6441    "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
6442    0, 0, 0, 0},
6443 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
6444   {"slow-start-timeout", 0,
6445    "Maximum number of milliseconds that the service control manager should wait "
6446    "before trying to kill the windows service during startup"
6447    "(Default: 15000).", &slow_start_timeout, &slow_start_timeout, 0,
6448    GET_ULONG, REQUIRED_ARG, 15000, 0, 0, 0, 0, 0},
6449 #endif
6450 #ifdef HAVE_REPLICATION
6451   {"sporadic-binlog-dump-fail", 0,
6452    "Option used by mysql-test for debugging and testing of replication.",
6453    &opt_sporadic_binlog_dump_fail,
6454    &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6455    0},
6456 #endif /* HAVE_REPLICATION */
6457 #ifdef HAVE_OPENSSL
6458   {"ssl", 0,
6459    "Enable SSL for connection (automatically enabled with other flags).",
6460    &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
6461    0, 0, 0},
6462 #endif
6463 #ifdef _WIN32
6464   {"standalone", 0,
6465   "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
6466    NO_ARG, 0, 0, 0, 0, 0, 0},
6467 #endif
6468   {"symbolic-links", 's', "Enable symbolic link support.",
6469    &my_enable_symlinks, &my_enable_symlinks, 0, GET_BOOL, NO_ARG,
6470    1, 0, 0, 0, 0, 0},
6471   {"sysdate-is-now", 0,
6472    "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. "
6473    "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
6474    "invocations, even within the same statement.",
6475    &global_system_variables.sysdate_is_now,
6476    0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
6477   {"tc-heuristic-recover", 0,
6478    "Decision to use in heuristic recover process. Possible values are OFF, "
6479    "COMMIT or ROLLBACK.", &tc_heuristic_recover, &tc_heuristic_recover,
6480    &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG,
6481    TC_HEURISTIC_NOT_USED, 0, 0, 0, 0, 0},
6482 #if defined(ENABLED_DEBUG_SYNC)
6483   {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
6484    "Enable the debug sync facility "
6485    "and optionally specify a default wait timeout in seconds. "
6486    "A zero value keeps the facility disabled.",
6487    &opt_debug_sync_timeout, 0,
6488    0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
6489 #endif /* defined(ENABLED_DEBUG_SYNC) */
6490   {"temp-pool", 0,
6491    "This option is deprecated and will be removed in a future version. "
6492 #if defined(__linux__)
6493    "Using this option will cause most temporary files created to use a small "
6494    "set of names, rather than a unique name for each new file.",
6495 #else
6496    "This option is ignored on this OS.",
6497 #endif
6498    &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
6499    0, 0, 0, 0, 0},
6500   {"transaction-isolation", OPT_TRANSACTION_ISOLATION,
6501    "Default transaction isolation level.",
6502    &global_system_variables.tx_isolation,
6503    &global_system_variables.tx_isolation, &tx_isolation_typelib,
6504    GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
6505   {"transaction-read-only", OPT_TRANSACTION_READ_ONLY,
6506    "Default transaction access mode. "
6507    "True if transactions are read-only.",
6508    &global_system_variables.tx_read_only,
6509    &global_system_variables.tx_read_only, 0,
6510    GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
6511   {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
6512    0, 0, 0, 0, 0, 0},
6513   {"early-plugin-load", OPT_EARLY_PLUGIN_LOAD,
6514    "Optional semicolon-separated list of plugins to load before storage engine "
6515    "initialization, where each plugin is identified as name=library, where "
6516    "name is the plugin name and library is the plugin library in plugin_dir.",
6517    0, 0, 0,
6518    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6519   {"plugin-load", OPT_PLUGIN_LOAD,
6520    "Optional semicolon-separated list of plugins to load, where each plugin is "
6521    "identified as name=library, where name is the plugin name and library "
6522    "is the plugin library in plugin_dir.",
6523    0, 0, 0,
6524    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6525   {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
6526    "Optional semicolon-separated list of plugins to load, where each plugin is "
6527    "identified as name=library, where name is the plugin name and library "
6528    "is the plugin library in plugin_dir. This option adds to the list "
6529    "specified by --plugin-load in an incremental way. "
6530    "Multiple --plugin-load-add are supported.",
6531    0, 0, 0,
6532    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6533 
6534   {"innodb", OPT_SKIP_INNODB,
6535    "Deprecated option. Provided for backward compatibility only. "
6536    "The option has no effect on the server behaviour. InnoDB is always enabled. "
6537    "The option will be removed in a future release.",
6538    0, 0, 0, GET_BOOL, OPT_ARG,
6539    0, 0, 0, 0, 0, 0},
6540 
6541   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
6542 };
6543 
6544 
show_queries(THD * thd,SHOW_VAR * var,char * buff)6545 static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
6546 {
6547   var->type= SHOW_LONGLONG;
6548   var->value= (char *)&thd->query_id;
6549   return 0;
6550 }
6551 
6552 
show_net_compression(THD * thd,SHOW_VAR * var,char * buff)6553 static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
6554 {
6555   var->type= SHOW_MY_BOOL;
6556   var->value= buff;
6557   *((bool *)buff)= thd->get_protocol()->get_compression();
6558   return 0;
6559 }
6560 
show_starttime(THD * thd,SHOW_VAR * var,char * buff)6561 static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
6562 {
6563   var->type= SHOW_LONGLONG;
6564   var->value= buff;
6565   *((longlong *)buff)= (longlong) (thd->query_start() - server_start_time);
6566   return 0;
6567 }
6568 
show_max_used_connections_time(THD * thd,SHOW_VAR * var,char * buff)6569 static int show_max_used_connections_time(THD *thd, SHOW_VAR *var, char *buff)
6570 {
6571   MYSQL_TIME max_used_connections_time;
6572   var->type= SHOW_CHAR;
6573   var->value= buff;
6574   thd->variables.time_zone->gmt_sec_to_TIME(&max_used_connections_time,
6575     Connection_handler_manager::max_used_connections_time);
6576   my_datetime_to_str(&max_used_connections_time, buff, 0);
6577   return 0;
6578 }
6579 
show_num_thread_running(THD * thd,SHOW_VAR * var,char * buff)6580 static int show_num_thread_running(THD *thd, SHOW_VAR *var, char *buff)
6581 {
6582   var->type= SHOW_LONGLONG;
6583   var->value= buff;
6584   long long *value= reinterpret_cast<long long*>(buff);
6585   *value= static_cast<long long>(Global_THD_manager::get_instance()->
6586                                  get_num_thread_running());
6587   return 0;
6588 }
6589 
6590 
show_num_thread_created(THD * thd,SHOW_VAR * var,char * buff)6591 static int show_num_thread_created(THD *thd, SHOW_VAR *var, char *buff)
6592 {
6593   var->type= SHOW_LONG;
6594   var->value= buff;
6595   long *value= reinterpret_cast<long*>(buff);
6596   *value= static_cast<long>(Global_THD_manager::get_instance()->
6597                             get_num_thread_created());
6598   return 0;
6599 }
6600 
show_thread_id_count(THD * thd,SHOW_VAR * var,char * buff)6601 static int show_thread_id_count(THD *thd, SHOW_VAR *var, char *buff)
6602 {
6603   var->type= SHOW_LONG;
6604   var->value= buff;
6605   long *value= reinterpret_cast<long*>(buff);
6606   *value= static_cast<long>(Global_THD_manager::get_instance()->
6607                             get_thread_id());
6608   return 0;
6609 }
6610 #ifdef WITH_WSREP
6611 /*
6612   like init_slave_thread(), rpl_slave.cc
6613 */
6614 
init_wsrep_thread(THD * thd)6615 static int init_wsrep_thread(THD* thd)
6616 {
6617   DBUG_ENTER("init_wsrep_thread");
6618 #if !defined(DBUG_OFF)
6619   int simulate_error= 0;
6620 #endif
6621   thd->system_thread = SYSTEM_THREAD_SLAVE_WORKER;
6622 
6623   thd->security_context()->skip_grants();
6624   thd->get_protocol_classic()->init_net(0);
6625   thd->slave_thread = 1;
6626   thd->enable_slow_log= opt_log_slow_slave_statements;
6627   set_slave_thread_options(thd);
6628   thd->get_protocol_classic()->set_client_capabilities(
6629       CLIENT_LOCAL_FILES);
6630 
6631   /*
6632     Replication threads are:
6633     - background threads in the server, not user sessions,
6634     - yet still assigned a PROCESSLIST_ID,
6635       for historical reasons (displayed in SHOW PROCESSLIST).
6636   */
6637   thd->set_new_thread_id();
6638 
6639 #ifdef HAVE_PSI_INTERFACE
6640   /*
6641     Populate the PROCESSLIST_ID in the instrumentation.
6642   */
6643   struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)();
6644   PSI_THREAD_CALL(set_thread_id)(psi, thd->thread_id());
6645 #endif /* HAVE_PSI_INTERFACE */
6646 
6647   DBUG_EXECUTE_IF("simulate_wsrep_slave_error_on_init",
6648                   simulate_error|= 1;);
6649 #if !defined(DBUG_OFF)
6650   if (thd->store_globals() || simulate_error)
6651 #else
6652   if (thd->store_globals())
6653 #endif
6654   {
6655     DBUG_RETURN(-1);
6656   }
6657 
6658   //THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log);
6659 
6660   thd->set_time();
6661   /* Do not use user-supplied timeout value for system threads. */
6662   thd->variables.lock_wait_timeout= LONG_TIMEOUT;
6663   DBUG_RETURN(0);
6664 }
6665 
6666 typedef void (*wsrep_thd_processor_fun)(THD *);
6667 
start_wsrep_THD(void * arg)6668 extern "C" void *start_wsrep_THD(void *arg)
6669 {
6670   THD *thd;
6671   bool thd_added= false;
6672 
6673   wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
6674 
6675   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6676   if (my_thread_init())
6677   {
6678     WSREP_ERROR("Could not initialize thread");
6679     return(NULL);
6680   }
6681 
6682 #ifdef OLD
6683   if (!(thd= new THD(true, true)))
6684   {
6685     return(NULL);
6686   }
6687 #else
6688   thd = new THD(false, true); // note that contructor of THD uses DBUG_ !
6689                               // (not enablin plugins, is applier)
6690   thd->thread_stack = (char*)&thd; // remember where our stack is
6691 #endif
6692 
6693   if (init_wsrep_thread(thd))
6694   {
6695     WSREP_WARN("Failed during wsrep thread initialization");
6696     goto err;
6697   }
6698 
6699   thd->real_id=pthread_self(); // Keep purify happy
6700 
6701   DBUG_PRINT("wsrep",(("creating thread %u"), thd->thread_id()));
6702 
6703   /* from bootstrap()... */
6704 //  thd->bootstrap=1;
6705   thd->get_protocol_classic()->set_max_packet_size(
6706     slave_max_allowed_packet + MAX_LOG_EVENT_HEADER);
6707 //  thd->security_context->master_access= ~(ulong)0;
6708 
6709 
6710   /* handle_one_connection() again... */
6711   //thd->version= refresh_version;
6712   thd->proc_info= 0;
6713   thd->set_command(COM_SLEEP);
6714   thd->init_for_queries();
6715 
6716   //thd->init_for_queries(rli);
6717   //thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
6718   //set_thd_in_use_temporary_tables(rli);   // (re)set sql_thd in use for saved temp tables
6719   /* Set applier thread InnoDB priority */
6720   //set_thd_tx_priority(thd, rli->get_thd_tx_priority());
6721 
6722   /* wsrep_running_threads counter is managed in thd_manager */
6723   thd_manager->add_thd(thd);
6724   thd_added= true;
6725 
6726 #ifdef SKIP_INNODB_HP
6727   /* set priority */
6728   thd->thd_tx_priority = 1;
6729 #endif
6730   THD_CHECK_SENTRY(thd);
6731 
6732   processor(thd);
6733 
6734  err:
6735   thd->clear_error();
6736   thd->set_catalog(NULL_CSTR);
6737   thd->reset_query();
6738   thd->reset_db(NULL_CSTR);
6739   close_connection(thd, 0);
6740 
6741   thd->temporary_tables = 0; // remove tempation from destructor to close them
6742 
6743   // Note: We can't call THD destructor without crashing
6744   // if plugins have not been initialized. However, in most of the
6745   // cases this means that pre SE initialization SST failed and
6746   // we are going to exit anyway.
6747   if (plugins_are_initialized)
6748   {
6749     thd->get_protocol_classic()->end_net();
6750     thd->release_resources();
6751 
6752     THD_CHECK_SENTRY(thd);
6753     if (thd_added)
6754       thd_manager->remove_thd(thd);
6755   }
6756   else
6757   {
6758     // TODO: lightweight cleanup to get rid of:
6759     // 'Error in my_thread_global_end(): 2 threads didn't exit'
6760     // at server shutdown
6761 
6762     if (thd_added)
6763     {
6764       thd->release_resources();
6765       thd_manager->remove_thd(thd);
6766     }
6767   }
6768 
6769   /*
6770     The thd can only be destructed after indirect references
6771     through mi->rli->info_thd are cleared: mi->rli->info_thd= NULL.
6772 
6773     For instance, user thread might be issuing show_slave_status
6774     and attempting to read mi->rli->info_thd->get_proc_info().
6775     Therefore thd must only be deleted after info_thd is set
6776     to NULL.
6777   */
6778   delete thd;
6779 
6780   my_thread_end();
6781 #if OPENSSL_VERSION_NUMBER < 0x10100000L
6782   ERR_remove_thread_state(0);
6783 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
6784   my_thread_exit(0);
6785 
6786   return(NULL);
6787 }
6788 
6789 /*
6790    returns the number of wsrep appliers running.
6791    However, the caller (thd parameter) is not taken in account
6792  */
6793 MY_ATTRIBUTE((noinline))
have_wsrep_appliers(THD * thd)6794 static int have_wsrep_appliers(THD *thd)
6795 {
6796   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6797   Count_wsrep_thd count_wsrep_applier_thd(APPLIER);
6798 
6799   thd_manager->do_for_all_thd(&count_wsrep_applier_thd);
6800   return count_wsrep_applier_thd.get_thd_count();
6801 }
6802 
wsrep_close_thread(THD * thd)6803 static void wsrep_close_thread(THD *thd)
6804 {
6805   thd->killed= THD::KILL_CONNECTION;
6806 
6807   mysql_mutex_lock(&thd->LOCK_thd_data);
6808   if (thd->current_cond)
6809   {
6810     mysql_mutex_lock(thd->current_mutex);
6811     mysql_cond_broadcast(thd->current_cond);
6812     mysql_mutex_unlock(thd->current_mutex);
6813   }
6814   mysql_mutex_unlock(&thd->LOCK_thd_data);
6815 }
6816 
6817 MY_ATTRIBUTE((noinline))
have_committing_connections()6818 static my_bool have_committing_connections()
6819 {
6820   Count_wsrep_thd count_thd_committing(COMMITTING);
6821   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6822 
6823   thd_manager->do_for_all_thd(&count_thd_committing);
6824   return (count_thd_committing.get_thd_count() != 0);
6825 }
6826 
wsrep_wait_committing_connections_close(int wait_time)6827 int wsrep_wait_committing_connections_close(int wait_time)
6828 {
6829   int sleep_time= 100;
6830 
6831   while (have_committing_connections() && wait_time > 0)
6832   {
6833     WSREP_DEBUG("wait for committing transaction to close: %d", wait_time);
6834     my_sleep(sleep_time);
6835     wait_time -= sleep_time;
6836   }
6837   if (have_committing_connections())
6838   {
6839     return 1;
6840   }
6841   return 0;
6842 }
6843 
wsrep_close_client_connections(my_bool wait_to_end)6844 void wsrep_close_client_connections(my_bool wait_to_end)
6845 {
6846 
6847   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6848   /*
6849     First signal all threads that it's time to die
6850     This will give the threads some time to gracefully abort their
6851     statements and inform their clients that the server is about to die.
6852   */
6853 
6854   sql_print_information("Giving %d client threads a chance to die gracefully",
6855                         static_cast<int>(thd_manager->get_thd_count()));
6856 
6857   Call_wsrep_close_client_conn call_wsrep_close_client_conn;
6858   thd_manager->do_for_all_thd(&call_wsrep_close_client_conn);
6859 
6860   if (thd_manager->get_thd_count() > 0)
6861     sleep(2);         // Give threads time to die
6862 
6863 }
6864 
wsrep_close_applier(THD * thd)6865 void wsrep_close_applier(THD *thd)
6866 {
6867   WSREP_DEBUG("closing applier %u", thd->thread_id());
6868   wsrep_close_thread(thd);
6869 }
6870 
wsrep_close_threads(THD * thd)6871 static void wsrep_close_threads(THD *thd)
6872 {
6873   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6874 
6875   Call_wsrep_close_wsrep_threads call_wsrep_close_wsrep_threads;
6876   thd_manager->do_for_all_thd(&call_wsrep_close_wsrep_threads);
6877 }
6878 
wsrep_close_applier_threads()6879 void wsrep_close_applier_threads()
6880 {
6881   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6882 
6883   Call_wsrep_close_wsrep_threads call_wsrep_close_wsrep_threads;
6884   thd_manager->do_for_all_thd(&call_wsrep_close_wsrep_threads);
6885 
6886 }
6887 
wsrep_wait_appliers_close(THD * thd)6888 void wsrep_wait_appliers_close(THD *thd)
6889 {
6890   /* Wait for wsrep appliers to gracefully exit */
6891   while (have_wsrep_appliers(thd) > 1)
6892   // 1 is for rollbacker thread which needs to be killed explicitly.
6893   // This gotta be fixed in a more elegant manner if we gonna have arbitrary
6894   // number of non-applier wsrep threads.
6895   {
6896     my_sleep(100000);
6897   }
6898 
6899   /* Notify rollbacker threads to exit */
6900   wsrep_close_applier_threads();
6901 
6902   /* Rollbacker thread can wait on condition so signal it */
6903   mysql_mutex_lock(&LOCK_wsrep_rollback);
6904   mysql_cond_signal(&COND_wsrep_rollback);
6905   mysql_mutex_unlock(&LOCK_wsrep_rollback);
6906 
6907   /* and wait for them to die */
6908   while (have_wsrep_appliers(thd) > 0)
6909   {
6910     my_sleep(100000);
6911   }
6912 
6913   /* All wsrep applier threads have now been aborted. However, if this thread
6914      is also applier, we are still running...
6915   */
6916 }
6917 
wsrep_kill_mysql(THD * thd)6918 void wsrep_kill_mysql(THD *thd)
6919 {
6920   if (mysqld_server_started)
6921   {
6922     WSREP_INFO("starting shutdown");
6923     kill_mysql();
6924   }
6925   else
6926   {
6927     unireg_abort(1);
6928   }
6929 }
6930 #endif /* WITH_WSREP */
6931 
6932 #ifndef EMBEDDED_LIBRARY
show_aborted_connects(THD * thd,SHOW_VAR * var,char * buff)6933 static int show_aborted_connects(THD *thd, SHOW_VAR *var, char *buff)
6934 {
6935   var->type= SHOW_LONG;
6936   var->value= buff;
6937   long *value= reinterpret_cast<long*>(buff);
6938   *value= static_cast<long>(Connection_handler_manager::get_instance()->
6939                             aborted_connects());
6940   return 0;
6941 }
6942 
show_connection_errors_max_connection(THD * thd,SHOW_VAR * var,char * buff)6943 static int show_connection_errors_max_connection(THD *thd, SHOW_VAR *var,
6944                                                  char *buff)
6945 {
6946   var->type= SHOW_LONG;
6947   var->value= buff;
6948   long *value= reinterpret_cast<long*>(buff);
6949   *value= static_cast<long>(Connection_handler_manager::get_instance()->
6950                             connection_errors_max_connection());
6951   return 0;
6952 }
6953 
show_connection_errors_select(THD * thd,SHOW_VAR * var,char * buff)6954 static int show_connection_errors_select(THD *thd, SHOW_VAR *var, char *buff)
6955 {
6956   var->type= SHOW_LONG;
6957   var->value= buff;
6958   long *value= reinterpret_cast<long*>(buff);
6959   *value=
6960     static_cast<long>(Mysqld_socket_listener::get_connection_errors_select());
6961   return 0;
6962 }
6963 
show_connection_errors_accept(THD * thd,SHOW_VAR * var,char * buff)6964 static int show_connection_errors_accept(THD *thd, SHOW_VAR *var, char *buff)
6965 {
6966   var->type= SHOW_LONG;
6967   var->value= buff;
6968   long *value= reinterpret_cast<long*>(buff);
6969   *value=
6970     static_cast<long>(Mysqld_socket_listener::get_connection_errors_accept());
6971   return 0;
6972 }
6973 
show_connection_errors_tcpwrap(THD * thd,SHOW_VAR * var,char * buff)6974 static int show_connection_errors_tcpwrap(THD *thd, SHOW_VAR *var, char *buff)
6975 {
6976   var->type= SHOW_LONG;
6977   var->value= buff;
6978   long *value= reinterpret_cast<long*>(buff);
6979   *value=
6980     static_cast<long>(Mysqld_socket_listener::get_connection_errors_tcpwrap());
6981   return 0;
6982 }
6983 #endif
6984 
6985 
6986 #ifdef ENABLED_PROFILING
show_flushstatustime(THD * thd,SHOW_VAR * var,char * buff)6987 static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
6988 {
6989   var->type= SHOW_LONGLONG;
6990   var->value= buff;
6991   *((longlong *)buff)= (longlong) (thd->query_start() - flush_status_time);
6992   return 0;
6993 }
6994 #endif
6995 
6996 #ifdef HAVE_REPLICATION
6997 /**
6998   After Multisource replication, this function only shows the value
6999   of default channel.
7000 
7001   To know the status of other channels, performance schema replication
7002   tables comes to the rescue.
7003 
7004   @TODO: any warning needed if multiple channels exist to request
7005          the users to start using replication performance schema
7006          tables.
7007 */
show_slave_running(THD * thd,SHOW_VAR * var,char * buff)7008 static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
7009 {
7010   channel_map.rdlock();
7011   Master_info *mi= channel_map.get_default_channel_mi();
7012 
7013   if (mi)
7014   {
7015     var->type= SHOW_MY_BOOL;
7016     var->value= buff;
7017     *((my_bool *)buff)= (my_bool) (mi &&
7018                                    mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
7019                                    mi->rli->slave_running);
7020   }
7021   else
7022     var->type= SHOW_UNDEF;
7023 
7024   channel_map.unlock();
7025   return 0;
7026 }
7027 
7028 
7029 /**
7030   This status variable is also exclusively (look comments on
7031   show_slave_running()) for default channel.
7032 */
show_slave_retried_trans(THD * thd,SHOW_VAR * var,char * buff)7033 static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
7034 {
7035   channel_map.rdlock();
7036   Master_info *mi= channel_map.get_default_channel_mi();
7037 
7038   if (mi)
7039   {
7040     var->type= SHOW_LONG;
7041     var->value= buff;
7042     *((long *)buff)= (long)mi->rli->retried_trans;
7043   }
7044   else
7045     var->type= SHOW_UNDEF;
7046 
7047   channel_map.unlock();
7048   return 0;
7049 }
7050 
7051 /**
7052   Only for default channel. Refer to comments on show_slave_running()
7053 */
show_slave_received_heartbeats(THD * thd,SHOW_VAR * var,char * buff)7054 static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
7055 {
7056   channel_map.rdlock();
7057   Master_info *mi= channel_map.get_default_channel_mi();
7058 
7059   if (mi)
7060   {
7061     var->type= SHOW_LONGLONG;
7062     var->value= buff;
7063     *((longlong *)buff)= mi->received_heartbeats;
7064   }
7065   else
7066     var->type= SHOW_UNDEF;
7067 
7068   channel_map.unlock();
7069   return 0;
7070 }
7071 
7072 /**
7073   Only for default channel. Refer to comments on show_slave_running()
7074 */
show_slave_last_heartbeat(THD * thd,SHOW_VAR * var,char * buff)7075 static int show_slave_last_heartbeat(THD *thd, SHOW_VAR *var, char *buff)
7076 {
7077   MYSQL_TIME received_heartbeat_time;
7078 
7079   channel_map.rdlock();
7080   Master_info *mi= channel_map.get_default_channel_mi();
7081 
7082   if (mi)
7083   {
7084     var->type= SHOW_CHAR;
7085     var->value= buff;
7086     if (mi->last_heartbeat == 0)
7087       buff[0]='\0';
7088     else
7089     {
7090       thd->variables.time_zone->gmt_sec_to_TIME(&received_heartbeat_time,
7091         static_cast<my_time_t>(mi->last_heartbeat));
7092       my_datetime_to_str(&received_heartbeat_time, buff, 0);
7093     }
7094   }
7095   else
7096     var->type= SHOW_UNDEF;
7097 
7098   channel_map.unlock();
7099   return 0;
7100 }
7101 
7102 /**
7103   Only for default channel. For details, refer to show_slave_running()
7104 */
show_heartbeat_period(THD * thd,SHOW_VAR * var,char * buff)7105 static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
7106 {
7107   DEBUG_SYNC(thd, "dsync_show_heartbeat_period");
7108 
7109   channel_map.rdlock();
7110   Master_info *mi= channel_map.get_default_channel_mi();
7111 
7112   if (mi)
7113   {
7114     var->type= SHOW_CHAR;
7115     var->value= buff;
7116     sprintf(buff, "%.3f", mi->heartbeat_period);
7117   }
7118   else
7119     var->type= SHOW_UNDEF;
7120 
7121   channel_map.unlock();
7122   return 0;
7123 }
7124 
7125 #ifndef NDEBUG
show_slave_rows_last_search_algorithm_used(THD * thd,SHOW_VAR * var,char * buff)7126 static int show_slave_rows_last_search_algorithm_used(THD *thd, SHOW_VAR *var, char *buff)
7127 {
7128   uint res= slave_rows_last_search_algorithm_used;
7129   const char* s= ((res == Rows_log_event::ROW_LOOKUP_TABLE_SCAN) ? "TABLE_SCAN" :
7130                   ((res == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN" :
7131                    "INDEX_SCAN"));
7132 
7133   var->type= SHOW_CHAR;
7134   var->value= buff;
7135   sprintf(buff, "%s", s);
7136 
7137   return 0;
7138 }
7139 
show_ongoing_automatic_gtid_violating_transaction_count(THD * thd,SHOW_VAR * var,char * buf)7140 static int show_ongoing_automatic_gtid_violating_transaction_count(
7141   THD *thd, SHOW_VAR *var, char *buf)
7142 {
7143   var->type= SHOW_CHAR;
7144   var->value= buf;
7145   sprintf(buf, "%d",
7146           gtid_state->get_automatic_gtid_violating_transaction_count());
7147   return 0;
7148 }
7149 
show_ongoing_anonymous_gtid_violating_transaction_count(THD * thd,SHOW_VAR * var,char * buf)7150 static int show_ongoing_anonymous_gtid_violating_transaction_count(
7151   THD *thd, SHOW_VAR *var, char *buf)
7152 {
7153   var->type= SHOW_CHAR;
7154   var->value= buf;
7155   sprintf(buf, "%d",
7156           gtid_state->get_anonymous_gtid_violating_transaction_count());
7157   return 0;
7158 }
7159 
7160 #endif
7161 
show_ongoing_anonymous_transaction_count(THD * thd,SHOW_VAR * var,char * buf)7162 static int show_ongoing_anonymous_transaction_count(
7163   THD *thd, SHOW_VAR *var, char *buf)
7164 {
7165   var->type= SHOW_CHAR;
7166   var->value= buf;
7167   sprintf(buf, "%d", gtid_state->get_anonymous_ownership_count());
7168   return 0;
7169 }
7170 
7171 #endif /* HAVE_REPLICATION */
7172 
show_open_tables(THD * thd,SHOW_VAR * var,char * buff)7173 static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
7174 {
7175   var->type= SHOW_LONG;
7176   var->value= buff;
7177   *((long *)buff)= (long)table_cache_manager.cached_tables();
7178   return 0;
7179 }
7180 
show_prepared_stmt_count(THD * thd,SHOW_VAR * var,char * buff)7181 static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff)
7182 {
7183   var->type= SHOW_LONG;
7184   var->value= buff;
7185   mysql_mutex_lock(&LOCK_prepared_stmt_count);
7186   *((long *)buff)= (long)prepared_stmt_count;
7187   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
7188   return 0;
7189 }
7190 
show_table_definitions(THD * thd,SHOW_VAR * var,char * buff)7191 static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
7192 {
7193   var->type= SHOW_LONG;
7194   var->value= buff;
7195   *((long *)buff)= (long)cached_table_definitions();
7196   return 0;
7197 }
7198 
7199 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
7200 /* Functions relying on CTX */
show_ssl_ctx_sess_accept(THD * thd,SHOW_VAR * var,char * buff)7201 static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
7202 {
7203   var->type= SHOW_LONG;
7204   var->value= buff;
7205   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7206                      SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
7207   return 0;
7208 }
7209 
show_ssl_ctx_sess_accept_good(THD * thd,SHOW_VAR * var,char * buff)7210 static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
7211 {
7212   var->type= SHOW_LONG;
7213   var->value= buff;
7214   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7215                      SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
7216   return 0;
7217 }
7218 
show_ssl_ctx_sess_connect_good(THD * thd,SHOW_VAR * var,char * buff)7219 static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
7220 {
7221   var->type= SHOW_LONG;
7222   var->value= buff;
7223   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7224                      SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
7225   return 0;
7226 }
7227 
show_ssl_ctx_sess_accept_renegotiate(THD * thd,SHOW_VAR * var,char * buff)7228 static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7229 {
7230   var->type= SHOW_LONG;
7231   var->value= buff;
7232   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7233                      SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
7234   return 0;
7235 }
7236 
show_ssl_ctx_sess_connect_renegotiate(THD * thd,SHOW_VAR * var,char * buff)7237 static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7238 {
7239   var->type= SHOW_LONG;
7240   var->value= buff;
7241   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7242                      SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
7243   return 0;
7244 }
7245 
show_ssl_ctx_sess_cb_hits(THD * thd,SHOW_VAR * var,char * buff)7246 static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
7247 {
7248   var->type= SHOW_LONG;
7249   var->value= buff;
7250   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7251                      SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
7252   return 0;
7253 }
7254 
show_ssl_ctx_sess_hits(THD * thd,SHOW_VAR * var,char * buff)7255 static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
7256 {
7257   var->type= SHOW_LONG;
7258   var->value= buff;
7259   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7260                      SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
7261   return 0;
7262 }
7263 
show_ssl_ctx_sess_cache_full(THD * thd,SHOW_VAR * var,char * buff)7264 static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
7265 {
7266   var->type= SHOW_LONG;
7267   var->value= buff;
7268   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7269                      SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
7270   return 0;
7271 }
7272 
show_ssl_ctx_sess_misses(THD * thd,SHOW_VAR * var,char * buff)7273 static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
7274 {
7275   var->type= SHOW_LONG;
7276   var->value= buff;
7277   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7278                      SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
7279   return 0;
7280 }
7281 
show_ssl_ctx_sess_timeouts(THD * thd,SHOW_VAR * var,char * buff)7282 static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
7283 {
7284   var->type= SHOW_LONG;
7285   var->value= buff;
7286   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7287                      SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
7288   return 0;
7289 }
7290 
show_ssl_ctx_sess_number(THD * thd,SHOW_VAR * var,char * buff)7291 static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
7292 {
7293   var->type= SHOW_LONG;
7294   var->value= buff;
7295   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7296                      SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
7297   return 0;
7298 }
7299 
show_ssl_ctx_sess_connect(THD * thd,SHOW_VAR * var,char * buff)7300 static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
7301 {
7302   var->type= SHOW_LONG;
7303   var->value= buff;
7304   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7305                      SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
7306   return 0;
7307 }
7308 
show_ssl_ctx_sess_get_cache_size(THD * thd,SHOW_VAR * var,char * buff)7309 static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
7310 {
7311   var->type= SHOW_LONG;
7312   var->value= buff;
7313   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7314                      SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
7315   return 0;
7316 }
7317 
show_ssl_ctx_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)7318 static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7319 {
7320   var->type= SHOW_LONG;
7321   var->value= buff;
7322   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7323                      SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
7324   return 0;
7325 }
7326 
show_ssl_ctx_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)7327 static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7328 {
7329   var->type= SHOW_LONG;
7330   var->value= buff;
7331   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
7332                      SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
7333   return 0;
7334 }
7335 
show_ssl_ctx_get_session_cache_mode(THD * thd,SHOW_VAR * var,char * buff)7336 static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
7337 {
7338   var->type= SHOW_CHAR;
7339   if (!ssl_acceptor_fd)
7340     var->value= const_cast<char*>("NONE");
7341   else
7342     switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
7343     {
7344     case SSL_SESS_CACHE_OFF:
7345       var->value= const_cast<char*>("OFF"); break;
7346     case SSL_SESS_CACHE_CLIENT:
7347       var->value= const_cast<char*>("CLIENT"); break;
7348     case SSL_SESS_CACHE_SERVER:
7349       var->value= const_cast<char*>("SERVER"); break;
7350     case SSL_SESS_CACHE_BOTH:
7351       var->value= const_cast<char*>("BOTH"); break;
7352     case SSL_SESS_CACHE_NO_AUTO_CLEAR:
7353       var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
7354     case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
7355       var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
7356     default:
7357       var->value= const_cast<char*>("Unknown"); break;
7358     }
7359   return 0;
7360 }
7361 
7362 /*
7363    Functions relying on SSL
7364    Note: In the show_ssl_* functions, we need to check if we have a
7365          valid vio-object since this isn't always true, specifically
7366          when session_status or global_status is requested from
7367          inside an Event.
7368  */
show_ssl_get_version(THD * thd,SHOW_VAR * var,char * buff)7369 static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
7370 {
7371   SSL_handle ssl = thd->get_ssl();
7372   var->type= SHOW_CHAR;
7373   if (ssl)
7374     var->value=
7375       const_cast<char*>(SSL_get_version(ssl));
7376   else
7377     var->value= (char *)"";
7378   return 0;
7379 }
7380 
show_ssl_session_reused(THD * thd,SHOW_VAR * var,char * buff)7381 static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
7382 {
7383   SSL_handle ssl = thd->get_ssl();
7384   var->type= SHOW_LONG;
7385   var->value= buff;
7386   if (ssl)
7387     *((long *)buff)=
7388         (long)SSL_session_reused(ssl);
7389   else
7390     *((long *)buff)= 0;
7391   return 0;
7392 }
7393 
show_ssl_get_default_timeout(THD * thd,SHOW_VAR * var,char * buff)7394 static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
7395 {
7396   SSL_handle ssl = thd->get_ssl();
7397   var->type= SHOW_LONG;
7398   var->value= buff;
7399   if (ssl)
7400     *((long *)buff)=
7401       (long)SSL_get_default_timeout(ssl);
7402   else
7403     *((long *)buff)= 0;
7404   return 0;
7405 }
7406 
show_ssl_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)7407 static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7408 {
7409   SSL_handle ssl = thd->get_ssl();
7410   var->type= SHOW_LONG;
7411   var->value= buff;
7412   if (ssl)
7413     *((long *)buff)=
7414       (long)SSL_get_verify_mode(ssl);
7415   else
7416     *((long *)buff)= 0;
7417   return 0;
7418 }
7419 
show_ssl_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)7420 static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7421 {
7422   SSL_handle ssl = thd->get_ssl();
7423   var->type= SHOW_LONG;
7424   var->value= buff;
7425   if (ssl)
7426     *((long *)buff)=
7427         (long)SSL_get_verify_depth(ssl);
7428   else
7429     *((long *)buff)= 0;
7430   return 0;
7431 }
7432 
show_ssl_get_cipher(THD * thd,SHOW_VAR * var,char * buff)7433 static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
7434 {
7435   SSL_handle ssl = thd->get_ssl();
7436   var->type= SHOW_CHAR;
7437   if (ssl)
7438     var->value=
7439       const_cast<char*>(SSL_get_cipher(ssl));
7440   else
7441     var->value= (char *)"";
7442   return 0;
7443 }
7444 
show_ssl_get_cipher_list(THD * thd,SHOW_VAR * var,char * buff)7445 static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
7446 {
7447   SSL_handle ssl = thd->get_ssl();
7448   var->type= SHOW_CHAR;
7449   var->value= buff;
7450   if (ssl)
7451   {
7452     int i;
7453     const char *p;
7454     char *end= buff + SHOW_VAR_FUNC_BUFF_SIZE;
7455     for (i=0; (p= SSL_get_cipher_list(ssl,i)) &&
7456                buff < end; i++)
7457     {
7458       buff= my_stpnmov(buff, p, end-buff-1);
7459       *buff++= ':';
7460     }
7461     if (i)
7462       buff--;
7463   }
7464   *buff=0;
7465   return 0;
7466 }
7467 
7468 
7469 static char *
my_asn1_time_to_string(ASN1_TIME * time,char * buf,size_t len)7470 my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len)
7471 {
7472   int n_read;
7473   char *res= NULL;
7474   BIO *bio= BIO_new(BIO_s_mem());
7475 
7476   if (bio == NULL)
7477     return NULL;
7478 
7479   if (!ASN1_TIME_print(bio, time))
7480     goto end;
7481 
7482   n_read= BIO_read(bio, buf, (int) (len - 1));
7483 
7484   if (n_read > 0)
7485   {
7486     buf[n_read]= 0;
7487     res= buf;
7488   }
7489 
7490 end:
7491   BIO_free(bio);
7492   return res;
7493 }
7494 
7495 
7496 /**
7497   Handler function for the 'ssl_get_server_not_before' variable
7498 
7499   @param      thd  the mysql thread structure
7500   @param      var  the data for the variable
7501   @param[out] buf  the string to put the value of the variable into
7502 
7503   @return          status
7504   @retval     0    success
7505 */
7506 
7507 static int
show_ssl_get_server_not_before(THD * thd,SHOW_VAR * var,char * buff)7508 show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff)
7509 {
7510   var->type= SHOW_CHAR;
7511   if (ssl_acceptor_fd)
7512   {
7513     X509 *cert= SSL_get_certificate(ssl_acceptor);
7514     ASN1_TIME *not_before= X509_get_notBefore(cert);
7515 
7516     if (not_before == NULL)
7517     {
7518       var->value= empty_c_string;
7519       return 0;
7520     }
7521 
7522     var->value= my_asn1_time_to_string(not_before, buff,
7523                                        SHOW_VAR_FUNC_BUFF_SIZE);
7524     if (var->value == NULL)
7525     {
7526       var->value= empty_c_string;
7527       return 1;
7528     }
7529   }
7530   else
7531     var->value= empty_c_string;
7532   return 0;
7533 }
7534 
7535 
7536 /**
7537   Handler function for the 'ssl_get_server_not_after' variable
7538 
7539   @param      thd  the mysql thread structure
7540   @param      var  the data for the variable
7541   @param[out] buf  the string to put the value of the variable into
7542 
7543   @return          status
7544   @retval     0    success
7545 */
7546 
7547 static int
show_ssl_get_server_not_after(THD * thd,SHOW_VAR * var,char * buff)7548 show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff)
7549 {
7550   var->type= SHOW_CHAR;
7551   if (ssl_acceptor_fd)
7552   {
7553     X509 *cert= SSL_get_certificate(ssl_acceptor);
7554     ASN1_TIME *not_after= X509_get_notAfter(cert);
7555 
7556     if (not_after == NULL)
7557     {
7558       var->value= empty_c_string;
7559       return 0;
7560     }
7561 
7562     var->value= my_asn1_time_to_string(not_after, buff,
7563                                        SHOW_VAR_FUNC_BUFF_SIZE);
7564     if (var->value == NULL)
7565     {
7566       var->value= empty_c_string;
7567       return 1;
7568     }
7569   }
7570   else
7571     var->value= empty_c_string;
7572   return 0;
7573 }
7574 
7575 #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
7576 
show_slave_open_temp_tables(THD * thd,SHOW_VAR * var,char * buf)7577 static int show_slave_open_temp_tables(THD *thd, SHOW_VAR *var, char *buf)
7578 {
7579   var->type= SHOW_INT;
7580   var->value= buf;
7581   *((int *) buf)= slave_open_temp_tables.atomic_get();
7582   return 0;
7583 }
7584 
7585 /*
7586   Variables shown by SHOW STATUS in alphabetical order
7587 */
7588 
7589 SHOW_VAR status_vars[]= {
7590   {"Aborted_clients",          (char*) &aborted_threads,                              SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7591 #ifndef EMBEDDED_LIBRARY
7592   {"Aborted_connects",         (char*) &show_aborted_connects,                        SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7593 #endif
7594 #ifdef HAVE_REPLICATION
7595 #ifndef NDEBUG
7596   {"Ongoing_anonymous_gtid_violating_transaction_count",(char*) &show_ongoing_anonymous_gtid_violating_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
7597 #endif//!NDEBUG
7598   {"Ongoing_anonymous_transaction_count",(char*) &show_ongoing_anonymous_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
7599 #ifndef NDEBUG
7600   {"Ongoing_automatic_gtid_violating_transaction_count",(char*) &show_ongoing_automatic_gtid_violating_transaction_count, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
7601 #endif//!NDEBUG
7602 #endif//HAVE_REPLICATION
7603   {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,                        SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7604   {"Binlog_cache_use",         (char*) &binlog_cache_use,                             SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7605   {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,                  SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7606   {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,                        SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7607   {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received),          SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7608   {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent),              SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7609   {"Com",                      (char*) com_status_vars,                               SHOW_ARRAY,              SHOW_SCOPE_ALL},
7610   {"Com_stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare),      SHOW_LONG_STATUS,        SHOW_SCOPE_ALL},
7611   {"Compression",              (char*) &show_net_compression,                         SHOW_FUNC,               SHOW_SCOPE_SESSION},
7612   {"Connections",              (char*) &show_thread_id_count,                         SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7613 #ifndef EMBEDDED_LIBRARY
7614   {"Connection_errors_accept",   (char*) &show_connection_errors_accept,              SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7615   {"Connection_errors_internal", (char*) &connection_errors_internal,                 SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7616   {"Connection_errors_max_connections",   (char*) &show_connection_errors_max_connection, SHOW_FUNC,           SHOW_SCOPE_GLOBAL},
7617   {"Connection_errors_peer_address", (char*) &connection_errors_peer_addr,            SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7618   {"Connection_errors_select",   (char*) &show_connection_errors_select,              SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7619   {"Connection_errors_tcpwrap",  (char*) &show_connection_errors_tcpwrap,             SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7620 #endif
7621   {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7622   {"Created_tmp_files",        (char*) &my_tmp_file_created,                          SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7623   {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables),      SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7624   {"Delayed_errors",           (char*) &delayed_insert_errors,                        SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7625   {"Delayed_insert_threads",   (char*) &delayed_insert_threads,                       SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7626   {"Delayed_writes",           (char*) &delayed_insert_writes,                        SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7627   {"Flush_commands",           (char*) &refresh_version,                              SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7628   {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count),         SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7629   {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count),         SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7630   {"Handler_discover",         (char*) offsetof(STATUS_VAR, ha_discover_count),       SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7631   {"Handler_external_lock",    (char*) offsetof(STATUS_VAR, ha_external_lock_count),  SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7632   {"Handler_mrr_init",         (char*) offsetof(STATUS_VAR, ha_multi_range_read_init_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7633   {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),        SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7634   {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count),     SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7635   {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count),       SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7636   {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count),      SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7637   {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count),      SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7638   {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count),      SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7639   {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count),       SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7640   {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count),  SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7641   {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count),       SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7642   {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count),      SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7643   {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7644   {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count),         SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7645   {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count),          SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7646   {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed),    SHOW_KEY_CACHE_LONG,     SHOW_SCOPE_GLOBAL},
7647   {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused),            SHOW_KEY_CACHE_LONG,     SHOW_SCOPE_GLOBAL},
7648   {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used),              SHOW_KEY_CACHE_LONG,     SHOW_SCOPE_GLOBAL},
7649   {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests),  SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
7650   {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read),        SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
7651   {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests),  SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
7652   {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write),       SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
7653   {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost),         SHOW_DOUBLE_STATUS,      SHOW_SCOPE_SESSION},
7654   {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans),SHOW_LONGLONG_STATUS,    SHOW_SCOPE_SESSION},
7655 #ifndef EMBEDDED_LIBRARY
7656   {"Locked_connects",          (char*) &locked_account_connection_count,              SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7657 #endif
7658   {"Max_execution_time_exceeded",   (char*) offsetof(STATUS_VAR, max_execution_time_exceeded),   SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7659   {"Max_execution_time_set",        (char*) offsetof(STATUS_VAR, max_execution_time_set),        SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7660   {"Max_execution_time_set_failed", (char*) offsetof(STATUS_VAR, max_execution_time_set_failed), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7661   {"Max_used_connections",     (char*) &Connection_handler_manager::max_used_connections,        SHOW_LONG,        SHOW_SCOPE_GLOBAL},
7662   {"Max_used_connections_time",(char*) &show_max_used_connections_time,               SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7663   {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,                          SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7664   {"Open_files",               (char*) &my_file_opened,                               SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7665   {"Open_streams",             (char*) &my_stream_opened,                             SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7666   {"Open_table_definitions",   (char*) &show_table_definitions,                       SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7667   {"Open_tables",              (char*) &show_open_tables,                             SHOW_FUNC,               SHOW_SCOPE_ALL},
7668   {"Opened_files",             (char*) &my_file_total_opened,                         SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7669   {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables),           SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7670   {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares),           SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7671   {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count,                     SHOW_FUNC,               SHOW_SCOPE_GLOBAL},
7672   {"Qcache_free_blocks",       (char*) &query_cache.free_memory_blocks,               SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7673   {"Qcache_free_memory",       (char*) &query_cache.free_memory,                      SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7674   {"Qcache_hits",              (char*) &query_cache.hits,                             SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7675   {"Qcache_inserts",           (char*) &query_cache.inserts,                          SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7676   {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes,                    SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7677   {"Qcache_not_cached",        (char*) &query_cache.refused,                          SHOW_LONG,               SHOW_SCOPE_GLOBAL},
7678   {"Qcache_queries_in_cache",  (char*) &query_cache.queries_in_cache,                 SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7679   {"Qcache_total_blocks",      (char*) &query_cache.total_blocks,                     SHOW_LONG_NOFLUSH,       SHOW_SCOPE_GLOBAL},
7680   {"Queries",                  (char*) &show_queries,                                 SHOW_FUNC,               SHOW_SCOPE_ALL},
7681   {"Questions",                (char*) offsetof(STATUS_VAR, questions),               SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7682   {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count),  SHOW_LONGLONG_STATUS,    SHOW_SCOPE_ALL},
7683   {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
7684   {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count),       SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7685   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7686   {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count),              SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7687   {"Slave_open_temp_tables",   (char*) &show_slave_open_temp_tables,                   SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7688 #ifdef HAVE_REPLICATION
7689   {"Slave_retried_transactions",(char*) &show_slave_retried_trans,                     SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7690   {"Slave_heartbeat_period",   (char*) &show_heartbeat_period,                         SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7691   {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats,                SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7692   {"Slave_last_heartbeat",     (char*) &show_slave_last_heartbeat,                     SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7693 #ifndef NDEBUG
7694   {"Slave_rows_last_search_algorithm_used",(char*) &show_slave_rows_last_search_algorithm_used, SHOW_FUNC,     SHOW_SCOPE_GLOBAL},
7695 #endif
7696   {"Slave_running",            (char*) &show_slave_running,                            SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7697 #endif
7698 #ifndef EMBEDDED_LIBRARY
7699   {"Slow_launch_threads",      (char*) &Per_thread_connection_handler::slow_launch_threads, SHOW_LONG,         SHOW_SCOPE_ALL},
7700 #endif
7701   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count),         SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7702   {"Sort_merge_passes",        (char*) offsetof(STATUS_VAR, filesort_merge_passes),    SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7703   {"Sort_range",               (char*) offsetof(STATUS_VAR, filesort_range_count),     SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7704   {"Sort_rows",                (char*) offsetof(STATUS_VAR, filesort_rows),            SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7705   {"Sort_scan",                (char*) offsetof(STATUS_VAR, filesort_scan_count),      SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7706 #ifdef HAVE_OPENSSL
7707 #ifndef EMBEDDED_LIBRARY
7708   {"Ssl_accept_renegotiates",  (char*) &show_ssl_ctx_sess_accept_renegotiate,          SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7709   {"Ssl_accepts",              (char*) &show_ssl_ctx_sess_accept,                      SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7710   {"Ssl_callback_cache_hits",  (char*) &show_ssl_ctx_sess_cb_hits,                     SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7711   {"Ssl_cipher",               (char*) &show_ssl_get_cipher,                           SHOW_FUNC,              SHOW_SCOPE_ALL},
7712   {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list,                      SHOW_FUNC,              SHOW_SCOPE_ALL},
7713   {"Ssl_client_connects",      (char*) &show_ssl_ctx_sess_connect,                     SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7714   {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate,         SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7715   {"Ssl_ctx_verify_depth",     (char*) &show_ssl_ctx_get_verify_depth,                 SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7716   {"Ssl_ctx_verify_mode",      (char*) &show_ssl_ctx_get_verify_mode,                  SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7717   {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout,                  SHOW_FUNC,              SHOW_SCOPE_ALL},
7718   {"Ssl_finished_accepts",     (char*) &show_ssl_ctx_sess_accept_good,                 SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7719   {"Ssl_finished_connects",    (char*) &show_ssl_ctx_sess_connect_good,                SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7720   {"Ssl_session_cache_hits",   (char*) &show_ssl_ctx_sess_hits,                        SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7721   {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses,                      SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7722   {"Ssl_session_cache_mode",   (char*) &show_ssl_ctx_get_session_cache_mode,           SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7723   {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full,               SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7724   {"Ssl_session_cache_size",   (char*) &show_ssl_ctx_sess_get_cache_size,              SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7725   {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts,                  SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7726   {"Ssl_sessions_reused",      (char*) &show_ssl_session_reused,                       SHOW_FUNC,              SHOW_SCOPE_ALL},
7727   {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number,                 SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7728   {"Ssl_verify_depth",         (char*) &show_ssl_get_verify_depth,                     SHOW_FUNC,              SHOW_SCOPE_ALL},
7729   {"Ssl_verify_mode",          (char*) &show_ssl_get_verify_mode,                      SHOW_FUNC,              SHOW_SCOPE_ALL},
7730   {"Ssl_version",              (char*) &show_ssl_get_version,                          SHOW_FUNC,              SHOW_SCOPE_ALL},
7731   {"Ssl_server_not_before",    (char*) &show_ssl_get_server_not_before,                SHOW_FUNC,              SHOW_SCOPE_ALL},
7732   {"Ssl_server_not_after",     (char*) &show_ssl_get_server_not_after,                 SHOW_FUNC,              SHOW_SCOPE_ALL},
7733   {"Rsa_public_key",           (char*) &show_rsa_public_key,                           SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7734 #endif
7735 #endif /* HAVE_OPENSSL */
7736   {"Table_locks_immediate",    (char*) &locks_immediate,                               SHOW_LONG,              SHOW_SCOPE_GLOBAL},
7737   {"Table_locks_waited",       (char*) &locks_waited,                                  SHOW_LONG,              SHOW_SCOPE_GLOBAL},
7738   {"Table_open_cache_hits",    (char*) offsetof(STATUS_VAR, table_open_cache_hits),    SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7739   {"Table_open_cache_misses",  (char*) offsetof(STATUS_VAR, table_open_cache_misses),  SHOW_LONGLONG_STATUS,   SHOW_SCOPE_ALL},
7740   {"Table_open_cache_overflows",(char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS,SHOW_SCOPE_ALL},
7741   {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,                         SHOW_LONG,              SHOW_SCOPE_GLOBAL},
7742   {"Tc_log_page_size",         (char*) &tc_log_page_size,                              SHOW_LONG_NOFLUSH,      SHOW_SCOPE_GLOBAL},
7743   {"Tc_log_page_waits",        (char*) &tc_log_page_waits,                             SHOW_LONG,              SHOW_SCOPE_GLOBAL},
7744 #ifndef EMBEDDED_LIBRARY
7745   {"Threads_cached",           (char*) &Per_thread_connection_handler::blocked_pthread_count, SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
7746 #endif
7747   {"Threads_connected",        (char*) &Connection_handler_manager::connection_count,  SHOW_INT,               SHOW_SCOPE_GLOBAL},
7748   {"Threads_created",          (char*) &show_num_thread_created,                       SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7749   {"Threads_running",          (char*) &show_num_thread_running,                       SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7750   {"Uptime",                   (char*) &show_starttime,                                SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7751 #ifdef ENABLED_PROFILING
7752   {"Uptime_since_flush_status",(char*) &show_flushstatustime,                          SHOW_FUNC,              SHOW_SCOPE_GLOBAL},
7753 #endif
7754 #ifdef WITH_WSREP
7755   {"wsrep_connected",          (char*) &wsrep_connected,         SHOW_BOOL, SHOW_SCOPE_GLOBAL},
7756   {"wsrep_ready",              (char*) &wsrep_show_ready,        SHOW_FUNC, SHOW_SCOPE_GLOBAL},
7757   {"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR, SHOW_SCOPE_GLOBAL},
7758   {"wsrep_cluster_conf_id",    (char*) &wsrep_cluster_conf_id,   SHOW_LONGLONG, SHOW_SCOPE_GLOBAL},
7759   {"wsrep_cluster_status",     (char*) &wsrep_cluster_status,    SHOW_CHAR_PTR, SHOW_SCOPE_GLOBAL},
7760   {"wsrep_cluster_size",       (char*) &wsrep_cluster_size,      SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
7761   {"wsrep_local_index",        (char*) &wsrep_local_index,       SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
7762   {"wsrep_local_bf_aborts",    (char*) &wsrep_show_bf_aborts,    SHOW_FUNC, SHOW_SCOPE_GLOBAL},
7763   {"wsrep_provider_name",      (char*) &wsrep_provider_name,     SHOW_CHAR_PTR, SHOW_SCOPE_GLOBAL},
7764   {"wsrep_provider_version",   (char*) &wsrep_provider_version,  SHOW_CHAR_PTR, SHOW_SCOPE_GLOBAL},
7765   {"wsrep_provider_vendor",    (char*) &wsrep_provider_vendor,   SHOW_CHAR_PTR, SHOW_SCOPE_GLOBAL},
7766   {"wsrep",                    (char*) &wsrep_show_status,       SHOW_FUNC, SHOW_SCOPE_ALL},
7767 #endif
7768   {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}
7769 };
7770 
add_terminator(vector<my_option> * options)7771 void add_terminator(vector<my_option> *options)
7772 {
7773   my_option empty_element=
7774     {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0};
7775   options->push_back(empty_element);
7776 }
7777 
7778 #ifndef EMBEDDED_LIBRARY
print_version(void)7779 static void print_version(void)
7780 {
7781   set_server_version();
7782 
7783   printf("%s  Ver %s for %s on %s (%s)\n",my_progname,
7784    server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
7785 }
7786 
7787 /** Compares two options' names, treats - and _ the same */
operator <(const my_option & a,const my_option & b)7788 static bool operator<(const my_option &a, const my_option &b)
7789 {
7790   const char *sa= a.name;
7791   const char *sb= b.name;
7792   for (; *sa || *sb; sa++, sb++)
7793   {
7794     if (*sa < *sb)
7795     {
7796       if (*sa == '-' && *sb == '_')
7797         continue;
7798       else
7799         return true;
7800     }
7801     if (*sa > *sb)
7802     {
7803       if (*sa == '_' && *sb == '-')
7804         continue;
7805       else
7806         return false;
7807     }
7808   }
7809   assert(a.name == b.name);
7810   return false;
7811 }
7812 
print_help()7813 static void print_help()
7814 {
7815   MEM_ROOT mem_root;
7816   init_alloc_root(key_memory_help, &mem_root, 4096, 4096);
7817 
7818   all_options.pop_back();
7819   sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
7820   for (my_option *opt= my_long_early_options;
7821        opt->name != NULL;
7822        opt++)
7823   {
7824     all_options.push_back(*opt);
7825   }
7826   add_plugin_options(&all_options, &mem_root);
7827   std::sort(all_options.begin(), all_options.end(), std::less<my_option>());
7828   add_terminator(&all_options);
7829 
7830   my_print_help(&all_options[0]);
7831   my_print_variables(&all_options[0]);
7832 
7833   free_root(&mem_root, MYF(0));
7834   vector<my_option>().swap(all_options);  // Deletes the vector contents.
7835 }
7836 
usage(void)7837 static void usage(void)
7838 {
7839   DBUG_ENTER("usage");
7840   if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
7841                      MY_CS_PRIMARY,
7842                MYF(MY_WME))))
7843     exit(MYSQLD_ABORT_EXIT);
7844   if (!default_collation_name)
7845     default_collation_name= (char*) default_charset_info->name;
7846   print_version();
7847   puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
7848   puts("Starts the MySQL database server.\n");
7849   printf("Usage: %s [OPTIONS]\n", my_progname);
7850   if (!opt_verbose)
7851     puts("\nFor more help options (several pages), use mysqld --verbose --help.");
7852   else
7853   {
7854 #ifdef _WIN32
7855   puts("NT and Win32 specific options:\n\
7856   --install                     Install the default service (NT).\n\
7857   --install-manual              Install the default service started manually (NT).\n\
7858   --install service_name        Install an optional service (NT).\n\
7859   --install-manual service_name Install an optional service started manually (NT).\n\
7860   --remove                      Remove the default service from the service list (NT).\n\
7861   --remove service_name         Remove the service_name from the service list (NT).\n\
7862   --enable-named-pipe           Only to be used for the default server (NT).\n\
7863   --standalone                  Dummy option to start as a standalone server (NT).\
7864 ");
7865   puts("");
7866 #endif
7867   print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
7868   puts("");
7869   set_ports();
7870 
7871   /* Print out all the options including plugin supplied options */
7872   print_help();
7873 
7874   if (! plugins_are_initialized)
7875   {
7876     puts("\n\
7877 Plugins have parameters that are not reflected in this list\n\
7878 because execution stopped before plugins were initialized.");
7879   }
7880 
7881   puts("\n\
7882 To see what values a running MySQL server is using, type\n\
7883 'mysqladmin variables' instead of 'mysqld --verbose --help'.");
7884   }
7885   DBUG_VOID_RETURN;
7886 }
7887 #endif /*!EMBEDDED_LIBRARY*/
7888 
7889 /**
7890   Initialize MySQL global variables to default values.
7891 
7892   @note
7893     The reason to set a lot of global variables to zero is to allow one to
7894     restart the embedded server with a clean environment
7895     It's also needed on some exotic platforms where global variables are
7896     not set to 0 when a program starts.
7897 
7898     We don't need to set variables refered to in my_long_options
7899     as these are initialized by my_getopt.
7900 */
7901 
mysql_init_variables(void)7902 static int mysql_init_variables(void)
7903 {
7904   /* Things reset to zero */
7905   opt_skip_slave_start= opt_reckless_slave = 0;
7906   mysql_home[0]= pidfile_name[0]= 0;
7907   myisam_test_invalid_symlink= test_if_data_home_dir;
7908   opt_general_log= opt_slow_log= false;
7909   opt_bin_log= 0;
7910   opt_disable_networking= opt_skip_show_db=0;
7911   opt_skip_name_resolve= 0;
7912   opt_ignore_builtin_innodb= 0;
7913   opt_general_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= NULL;
7914   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
7915   opt_secure_auth= 0;
7916   opt_myisam_log= 0;
7917   mqh_used= 0;
7918   kill_in_progress= 0;
7919   cleanup_done= 0;
7920   server_id_supplied= false;
7921   test_flags= select_errors= dropping_tables= ha_open_options=0;
7922   slave_open_temp_tables.atomic_set(0);
7923   opt_endinfo= using_udf_functions= 0;
7924   opt_using_transactions= 0;
7925   abort_loop= false;
7926   server_operational_state= SERVER_BOOTING;
7927   aborted_threads= 0;
7928   delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
7929   delayed_insert_errors= 0;
7930   specialflag= 0;
7931   binlog_cache_use=  binlog_cache_disk_use= 0;
7932   mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
7933   prepared_stmt_count= 0;
7934   mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
7935   memset(&mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list));
7936   memset(&global_status_var, 0, sizeof(global_status_var));
7937   opt_large_pages= 0;
7938   opt_super_large_pages= 0;
7939 #if defined(ENABLED_DEBUG_SYNC)
7940   opt_debug_sync_timeout= 0;
7941 #endif /* defined(ENABLED_DEBUG_SYNC) */
7942   key_map_full.set_all();
7943   server_uuid[0]= 0;
7944 
7945   /* Character sets */
7946   system_charset_info= &my_charset_utf8_general_ci;
7947   files_charset_info= &my_charset_utf8_general_ci;
7948   national_charset_info= &my_charset_utf8_general_ci;
7949   table_alias_charset= &my_charset_bin;
7950   character_set_filesystem= &my_charset_bin;
7951 
7952   opt_specialflag= 0;
7953   mysql_home_ptr= mysql_home;
7954   pidfile_name_ptr= pidfile_name;
7955   lc_messages_dir_ptr= lc_messages_dir;
7956   protocol_version= PROTOCOL_VERSION;
7957   what_to_log= ~ (1L << (uint) COM_TIME);
7958   refresh_version= 1L;  /* Increments on each reload */
7959   global_query_id= 1L;
7960   my_stpcpy(server_version, MYSQL_SERVER_VERSION);
7961   key_caches.empty();
7962   if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
7963                                                 default_key_cache_base.length)))
7964   {
7965     sql_print_error("Cannot allocate the keycache");
7966     return 1;
7967   }
7968   /* set key_cache_hash.default_value = dflt_key_cache */
7969   multi_keycache_init();
7970 
7971   /* Set directory paths */
7972   mysql_real_data_home_len=
7973     strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
7974             sizeof(mysql_real_data_home)-1) - mysql_real_data_home;
7975   /* Replication parameters */
7976   master_info_file= (char*) "master.info",
7977     relay_log_info_file= (char*) "relay-log.info";
7978   report_user= report_password = report_host= 0;  /* TO BE DELETED */
7979   opt_relay_logname= opt_relaylog_index_name= 0;
7980   log_bin_basename= NULL;
7981   log_bin_index= NULL;
7982 
7983   /* Handler variables */
7984   total_ha= 0;
7985   total_ha_2pc= 0;
7986   /* Variables in libraries */
7987   charsets_dir= 0;
7988   default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
7989   default_collation_name= compiled_default_collation_name;
7990   character_set_filesystem_name= (char*) "binary";
7991   lc_messages= (char*) "en_US";
7992   lc_time_names_name= (char*) "en_US";
7993   opt_replication_optimize_for_static_plugin_config= 0;
7994   opt_replication_sender_observe_commit_only= 0;
7995 
7996   /* Variables that depends on compile options */
7997 #ifndef NDEBUG
7998   default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
7999            "d:t:i:o,/tmp/mysqld.trace");
8000 #endif
8001 #ifdef ENABLED_PROFILING
8002     have_profiling = SHOW_OPTION_YES;
8003 #else
8004     have_profiling = SHOW_OPTION_NO;
8005 #endif
8006 
8007 #ifdef HAVE_OPENSSL
8008   have_ssl=SHOW_OPTION_YES;
8009 #else
8010   have_ssl=SHOW_OPTION_NO;
8011 #endif
8012 
8013   have_symlink= SHOW_OPTION_YES;
8014 
8015 #ifdef HAVE_DLOPEN
8016   have_dlopen=SHOW_OPTION_YES;
8017 #else
8018   have_dlopen=SHOW_OPTION_NO;
8019 #endif
8020 
8021   have_query_cache=SHOW_OPTION_YES;
8022 
8023   have_geometry=SHOW_OPTION_YES;
8024 
8025   have_rtree_keys=SHOW_OPTION_YES;
8026 
8027 #ifdef HAVE_CRYPT
8028   have_crypt=SHOW_OPTION_YES;
8029 #else
8030   have_crypt=SHOW_OPTION_NO;
8031 #endif
8032 #ifdef HAVE_COMPRESS
8033   have_compress= SHOW_OPTION_YES;
8034 #else
8035   have_compress= SHOW_OPTION_NO;
8036 #endif
8037 #ifdef HAVE_OPENSSL
8038   des_key_file = 0;
8039 #ifndef EMBEDDED_LIBRARY
8040   ssl_acceptor_fd= 0;
8041 #endif /* ! EMBEDDED_LIBRARY */
8042 #endif /* HAVE_OPENSSL */
8043 #if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
8044   shared_memory_base_name= default_shared_memory_base_name;
8045 #endif
8046 
8047 #if defined(_WIN32)
8048   /* Allow Win32 users to move MySQL anywhere */
8049   {
8050     char prg_dev[LIBLEN];
8051     char executing_path_name[LIBLEN];
8052     if (!test_if_hard_path(my_progname))
8053     {
8054       // we don't want to use GetModuleFileName inside of my_path since
8055       // my_path is a generic path dereferencing function and here we care
8056       // only about the executing binary.
8057       GetModuleFileName(NULL, executing_path_name, sizeof(executing_path_name));
8058       my_path(prg_dev, executing_path_name, NULL);
8059     }
8060     else
8061       my_path(prg_dev, my_progname, "mysql/bin");
8062     strcat(prg_dev,"/../");     // Remove 'bin' to get base dir
8063     cleanup_dirname(mysql_home,prg_dev);
8064   }
8065 #else
8066   const char *tmpenv;
8067   if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
8068     tmpenv = DEFAULT_MYSQL_HOME;
8069   (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
8070 #endif
8071 #ifdef WITH_WSREP
8072   if (wsrep_init_vars())
8073     return 1;
8074 #endif
8075   return 0;
8076 }
8077 
8078 my_bool
mysqld_get_one_option(int optid,const struct my_option * opt MY_ATTRIBUTE ((unused)),char * argument)8079 mysqld_get_one_option(int optid,
8080                       const struct my_option *opt MY_ATTRIBUTE((unused)),
8081                       char *argument)
8082 {
8083   switch(optid) {
8084   case '#':
8085 #ifndef NDEBUG
8086     DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
8087 #endif
8088     opt_endinfo=1;        /* unireg: memory allocation */
8089     break;
8090   case 'a':
8091     global_system_variables.sql_mode= MODE_ANSI;
8092     global_system_variables.tx_isolation=
8093            global_system_variables.transaction_isolation= ISO_SERIALIZABLE;
8094     break;
8095   case 'b':
8096     strmake(mysql_home,argument,sizeof(mysql_home)-1);
8097     mysql_home_ptr= mysql_home;
8098     break;
8099   case 'C':
8100     if (default_collation_name == compiled_default_collation_name)
8101       default_collation_name= 0;
8102     break;
8103   case 'h':
8104     strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
8105     /* Correct pointer set by my_getopt (for embedded library) */
8106     mysql_real_data_home_ptr= mysql_real_data_home;
8107     break;
8108   case 'u':
8109     if (!mysqld_user || !strcmp(mysqld_user, argument))
8110       mysqld_user= argument;
8111     else
8112       sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
8113     break;
8114   case 'L':
8115     push_deprecated_warn(NULL, "--language/-l", "'--lc-messages-dir'");
8116     /* Note:  fall-through */
8117   case OPT_LC_MESSAGES_DIRECTORY:
8118     strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1);
8119     lc_messages_dir_ptr= lc_messages_dir;
8120     break;
8121   case OPT_BINLOG_FORMAT:
8122     binlog_format_used= true;
8123     break;
8124   case OPT_BINLOG_MAX_FLUSH_QUEUE_TIME:
8125     push_deprecated_warn_no_replacement(NULL, "--binlog_max_flush_queue_time");
8126     break;
8127 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8128   case OPT_SSL_KEY:
8129   case OPT_SSL_CERT:
8130   case OPT_SSL_CA:
8131   case OPT_SSL_CAPATH:
8132   case OPT_SSL_CIPHER:
8133   case OPT_SSL_CRL:
8134   case OPT_SSL_CRLPATH:
8135   case OPT_TLS_VERSION:
8136     /*
8137       Enable use of SSL if we are using any ssl option.
8138       One can disable SSL later by using --skip-ssl or --ssl=0.
8139     */
8140     opt_use_ssl= true;
8141     break;
8142 #endif /* HAVE_OPENSSL */
8143 #ifndef EMBEDDED_LIBRARY
8144   case 'V':
8145     print_version();
8146     exit(MYSQLD_SUCCESS_EXIT);
8147 #endif /*EMBEDDED_LIBRARY*/
8148   case 'W':
8149     push_deprecated_warn(NULL, "--log_warnings/-W", "'--log_error_verbosity'");
8150     if (!argument)
8151       log_error_verbosity++;
8152     else if (argument == disabled_my_option)
8153      log_error_verbosity= 1L;
8154     else
8155       log_error_verbosity= 1 + atoi(argument);
8156     log_error_verbosity= min(3UL, log_error_verbosity);
8157     break;
8158   case 'T':
8159     test_flags= argument ? (uint) atoi(argument) : 0;
8160     opt_endinfo=1;
8161     break;
8162   case (int) OPT_ISAM_LOG:
8163     opt_myisam_log=1;
8164     break;
8165   case (int) OPT_BIN_LOG:
8166     opt_bin_log= MY_TEST(argument != disabled_my_option);
8167     break;
8168 #ifdef HAVE_REPLICATION
8169   case (int)OPT_REPLICATE_IGNORE_DB:
8170   {
8171     rpl_filter->add_ignore_db(argument);
8172     break;
8173   }
8174   case (int)OPT_REPLICATE_DO_DB:
8175   {
8176     rpl_filter->add_do_db(argument);
8177     break;
8178   }
8179   case (int)OPT_REPLICATE_REWRITE_DB:
8180   {
8181     char* key = argument,*p, *val;
8182 
8183     if (!(p= strstr(argument, "->")))
8184     {
8185       sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
8186       return 1;
8187     }
8188     val= p + 2;
8189     while(p > argument && my_isspace(mysqld_charset, p[-1]))
8190       p--;
8191     *p= 0;
8192     if (!*key)
8193     {
8194       sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
8195       return 1;
8196     }
8197     while (*val && my_isspace(mysqld_charset, *val))
8198       val++;
8199     if (!*val)
8200     {
8201       sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
8202       return 1;
8203     }
8204 
8205     rpl_filter->add_db_rewrite(key, val);
8206     break;
8207   }
8208 
8209   case (int)OPT_BINLOG_IGNORE_DB:
8210   {
8211     binlog_filter->add_ignore_db(argument);
8212     break;
8213   }
8214   case (int)OPT_BINLOG_DO_DB:
8215   {
8216     binlog_filter->add_do_db(argument);
8217     break;
8218   }
8219   case (int)OPT_REPLICATE_DO_TABLE:
8220   {
8221     if (rpl_filter->add_do_table_array(argument))
8222     {
8223       sql_print_error("Could not add do table rule '%s'!\n", argument);
8224       return 1;
8225     }
8226     break;
8227   }
8228   case (int)OPT_REPLICATE_WILD_DO_TABLE:
8229   {
8230     if (rpl_filter->add_wild_do_table(argument))
8231     {
8232       sql_print_error("Could not add do table rule '%s'!\n", argument);
8233       return 1;
8234     }
8235     break;
8236   }
8237   case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
8238   {
8239     if (rpl_filter->add_wild_ignore_table(argument))
8240     {
8241       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
8242       return 1;
8243     }
8244     break;
8245   }
8246   case (int)OPT_REPLICATE_IGNORE_TABLE:
8247   {
8248     if (rpl_filter->add_ignore_table_array(argument))
8249     {
8250       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
8251       return 1;
8252     }
8253     break;
8254   }
8255 #endif /* HAVE_REPLICATION */
8256   case (int) OPT_MASTER_RETRY_COUNT:
8257     push_deprecated_warn(NULL, "--master-retry-count", "'CHANGE MASTER TO master_retry_count = <num>'");
8258     break;
8259   case (int) OPT_SKIP_NEW:
8260     opt_specialflag|= SPECIAL_NO_NEW_FUNC;
8261     delay_key_write_options= DELAY_KEY_WRITE_NONE;
8262     myisam_concurrent_insert=0;
8263     myisam_recover_options= HA_RECOVER_OFF;
8264     sp_automatic_privileges=0;
8265     my_enable_symlinks= 0;
8266     ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
8267     query_cache_size=0;
8268     break;
8269   case (int) OPT_SKIP_HOST_CACHE:
8270     opt_specialflag|= SPECIAL_NO_HOST_CACHE;
8271     break;
8272   case (int) OPT_SKIP_RESOLVE:
8273     opt_skip_name_resolve= 1;
8274     opt_specialflag|=SPECIAL_NO_RESOLVE;
8275     break;
8276   case (int) OPT_WANT_CORE:
8277     test_flags |= TEST_CORE_ON_SIGNAL;
8278     break;
8279   case (int) OPT_SKIP_STACK_TRACE:
8280     test_flags|=TEST_NO_STACKTRACE;
8281     break;
8282   case OPT_BOOTSTRAP:
8283     opt_bootstrap= 1;
8284     break;
8285   case OPT_SERVER_ID:
8286     /*
8287      Consider that one received a Server Id when 2 conditions are present:
8288      1) The argument is on the list
8289      2) There is a value present
8290     */
8291     server_id_supplied= (*argument != 0);
8292 
8293     break;
8294   case OPT_LOWER_CASE_TABLE_NAMES:
8295     lower_case_table_names_used= 1;
8296     break;
8297 #ifdef WITH_WSREP
8298   case OPT_WSREP_START_POSITION:
8299     wsrep_start_position_init (argument);
8300     break;
8301   case OPT_WSREP_SST_AUTH:
8302     wsrep_sst_auth_init (argument);
8303     break;
8304 #endif
8305 #if defined(ENABLED_DEBUG_SYNC)
8306   case OPT_DEBUG_SYNC_TIMEOUT:
8307     /*
8308       Debug Sync Facility. See debug_sync.cc.
8309       Default timeout for WAIT_FOR action.
8310       Default value is zero (facility disabled).
8311       If option is given without an argument, supply a non-zero value.
8312     */
8313     if (!argument)
8314     {
8315       /* purecov: begin tested */
8316       opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
8317       /* purecov: end */
8318     }
8319     break;
8320 #endif /* defined(ENABLED_DEBUG_SYNC) */
8321   case OPT_LOG_ERROR:
8322     /*
8323       "No --log-error" == "write errors to stderr",
8324       "--log-error without argument" == "write errors to a file".
8325     */
8326     if (argument == NULL) /* no argument */
8327       log_error_dest= "";
8328     break;
8329 
8330   case OPT_IGNORE_DB_DIRECTORY:
8331     if (*argument == 0)
8332       ignore_db_dirs_reset();
8333     else
8334     {
8335       if (push_ignored_db_dir(argument))
8336       {
8337         sql_print_error("Can't start server: "
8338                         "cannot process --ignore-db-dir=%.*s",
8339                         FN_REFLEN, argument);
8340         return 1;
8341       }
8342     }
8343     break;
8344 
8345   case OPT_EARLY_PLUGIN_LOAD:
8346     free_list(opt_early_plugin_load_list_ptr);
8347     opt_early_plugin_load_list_ptr->push_back(new i_string(argument));
8348     break;
8349   case OPT_PLUGIN_LOAD:
8350     free_list(opt_plugin_load_list_ptr);
8351     /* fall through */
8352   case OPT_PLUGIN_LOAD_ADD:
8353     opt_plugin_load_list_ptr->push_back(new i_string(argument));
8354     break;
8355   case OPT_SECURE_AUTH:
8356     push_deprecated_warn_no_replacement(NULL, "--secure-auth");
8357     if (!opt_secure_auth)
8358     {
8359       sql_print_error("Unsupported value 0 for secure-auth");
8360       return 1;
8361     }
8362     break;
8363   case OPT_PFS_INSTRUMENT:
8364     {
8365 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
8366 #ifndef EMBEDDED_LIBRARY
8367 
8368       /*
8369         Parse instrument name and value from argument string. Handle leading
8370         and trailing spaces. Also handle single quotes.
8371 
8372         Acceptable:
8373           performance_schema_instrument = ' foo/%/bar/  =  ON  '
8374           performance_schema_instrument = '%=OFF'
8375         Not acceptable:
8376           performance_schema_instrument = '' foo/%/bar = ON ''
8377           performance_schema_instrument = '%='OFF''
8378       */
8379       char *name= argument,*p= NULL, *val= NULL;
8380       my_bool quote= false; /* true if quote detected */
8381       my_bool error= true;  /* false if no errors detected */
8382       const int PFS_BUFFER_SIZE= 128;
8383       char orig_argument[PFS_BUFFER_SIZE+1];
8384       orig_argument[0]= 0;
8385 
8386       if (!argument)
8387         goto pfs_error;
8388 
8389       /* Save original argument string for error reporting */
8390       strncpy(orig_argument, argument, PFS_BUFFER_SIZE);
8391 
8392       /* Split instrument name and value at the equal sign */
8393       if (!(p= strchr(argument, '=')))
8394         goto pfs_error;
8395 
8396       /* Get option value */
8397       val= p + 1;
8398       if (!*val)
8399         goto pfs_error;
8400 
8401       /* Trim leading spaces and quote from the instrument name */
8402       while (*name && (my_isspace(mysqld_charset, *name) || (*name == '\'')))
8403       {
8404         /* One quote allowed */
8405         if (*name == '\'')
8406         {
8407           if (!quote)
8408             quote= true;
8409           else
8410             goto pfs_error;
8411         }
8412         name++;
8413       }
8414 
8415       /* Trim trailing spaces from instrument name */
8416       while ((p > name) && my_isspace(mysqld_charset, p[-1]))
8417         p--;
8418       *p= 0;
8419 
8420       /* Remove trailing slash from instrument name */
8421       if (p > name && (p[-1] == '/'))
8422         p[-1]= 0;
8423 
8424       if (!*name)
8425         goto pfs_error;
8426 
8427       /* Trim leading spaces from option value */
8428       while (*val && my_isspace(mysqld_charset, *val))
8429         val++;
8430 
8431       /* Trim trailing spaces and matching quote from value */
8432       p= val + strlen(val);
8433       while (p > val && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '\''))
8434       {
8435         /* One matching quote allowed */
8436         if (p[-1] == '\'')
8437         {
8438           if (quote)
8439             quote= false;
8440           else
8441             goto pfs_error;
8442         }
8443         p--;
8444       }
8445 
8446       *p= 0;
8447 
8448       if (!*val)
8449         goto pfs_error;
8450 
8451       /* Add instrument name and value to array of configuration options */
8452       if (add_pfs_instr_to_array(name, val))
8453         goto pfs_error;
8454 
8455       error= false;
8456 
8457 pfs_error:
8458       if (error)
8459       {
8460         sql_print_warning("Invalid instrument name or value for "
8461                           "performance_schema_instrument '%s'",
8462                           orig_argument);
8463         return 0;
8464       }
8465 #endif /* EMBEDDED_LIBRARY */
8466 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
8467       break;
8468     }
8469   case OPT_THREAD_CACHE_SIZE:
8470     thread_cache_size_specified= true;
8471     break;
8472   case OPT_HOST_CACHE_SIZE:
8473     host_cache_size_specified= true;
8474     break;
8475   case OPT_TABLE_DEFINITION_CACHE:
8476     table_definition_cache_specified= true;
8477     break;
8478   case OPT_MDL_CACHE_SIZE:
8479     push_deprecated_warn_no_replacement(NULL, "--metadata_locks_cache_size");
8480     break;
8481   case OPT_MDL_HASH_INSTANCES:
8482     push_deprecated_warn_no_replacement(NULL,
8483                                         "--metadata_locks_hash_instances");
8484     break;
8485   case OPT_SKIP_INNODB:
8486     sql_print_warning("The use of InnoDB is mandatory since MySQL 5.7. "
8487                       "The former options like '--innodb=0/1/OFF/ON' or "
8488                       "'--skip-innodb' are ignored.");
8489     break;
8490   case OPT_AVOID_TEMPORAL_UPGRADE:
8491     push_deprecated_warn_no_replacement(NULL, "avoid_temporal_upgrade");
8492     break;
8493   case OPT_SHOW_OLD_TEMPORALS:
8494     push_deprecated_warn_no_replacement(NULL, "show_old_temporals");
8495     break;
8496   case OPT_KEYRING_MIGRATION_PASSWORD:
8497     if (argument)
8498     {
8499       char *start= argument;
8500       opt_keyring_migration_password= my_strdup(PSI_NOT_INSTRUMENTED,
8501         argument, MYF(MY_FAE));
8502       while (*argument) *argument++= 'x';
8503       if (*start)
8504        start[1]= 0;
8505     }
8506     else
8507       opt_keyring_migration_password= get_tty_password(NullS);
8508     migrate_connect_options= 1;
8509     break;
8510   case OPT_KEYRING_MIGRATION_USER:
8511   case OPT_KEYRING_MIGRATION_HOST:
8512   case OPT_KEYRING_MIGRATION_SOCKET:
8513   case OPT_KEYRING_MIGRATION_PORT:
8514     migrate_connect_options= 1;
8515     break;
8516   case OPT_ENFORCE_GTID_CONSISTENCY:
8517   {
8518     const char *wrong_value=
8519       fixup_enforce_gtid_consistency_command_line(argument);
8520     if (wrong_value != NULL)
8521       sql_print_warning("option 'enforce-gtid-consistency': value '%s' "
8522                         "was not recognized. Setting enforce-gtid-consistency "
8523                         "to OFF.", wrong_value);
8524     break;
8525   }
8526   case OPT_TRANSACTION_READ_ONLY:
8527     global_system_variables.transaction_read_only=
8528                             global_system_variables.tx_read_only;
8529     break;
8530   case OPT_TRANSACTION_ISOLATION:
8531     global_system_variables.transaction_isolation=
8532                             global_system_variables.tx_isolation;
8533     break;
8534   case OPT_NAMED_PIPE_FULL_ACCESS_GROUP:
8535 #if defined(_WIN32)  && !defined(EMBEDDED_LIBRARY)
8536     if (!is_valid_named_pipe_full_access_group(argument))
8537     {
8538       sql_print_error("Invalid value for named_pipe_full_access_group.");
8539       return 1;
8540     }
8541 #endif /* _WIN32 && !EMBEDDED_LIBRARY */
8542     break;
8543   }
8544   return 0;
8545 }
8546 
8547 
8548 /** Handle arguments for multiple key caches. */
8549 
8550 C_MODE_START
8551 
8552 static void*
mysql_getopt_value(const char * keyname,size_t key_length,const struct my_option * option,int * error)8553 mysql_getopt_value(const char *keyname, size_t key_length,
8554        const struct my_option *option, int *error)
8555 {
8556   if (error)
8557     *error= 0;
8558   switch (option->id) {
8559   case OPT_KEY_BUFFER_SIZE:
8560   case OPT_KEY_CACHE_BLOCK_SIZE:
8561   case OPT_KEY_CACHE_DIVISION_LIMIT:
8562   case OPT_KEY_CACHE_AGE_THRESHOLD:
8563   {
8564     KEY_CACHE *key_cache;
8565     if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
8566     {
8567       if (error)
8568         *error= EXIT_OUT_OF_MEMORY;
8569       return 0;
8570     }
8571     switch (option->id) {
8572     case OPT_KEY_BUFFER_SIZE:
8573       return &key_cache->param_buff_size;
8574     case OPT_KEY_CACHE_BLOCK_SIZE:
8575       return &key_cache->param_block_size;
8576     case OPT_KEY_CACHE_DIVISION_LIMIT:
8577       return &key_cache->param_division_limit;
8578     case OPT_KEY_CACHE_AGE_THRESHOLD:
8579       return &key_cache->param_age_threshold;
8580     }
8581   }
8582   }
8583   return option->value;
8584 }
8585 
8586 C_MODE_END
8587 
8588 /**
8589   Ensure all the deprecared options with 1 possible value are
8590   within acceptable range.
8591 
8592   @retval true error in the values set
8593   @retval false all checked
8594 */
check_ghost_options()8595 bool check_ghost_options()
8596 {
8597   if (global_system_variables.old_passwords == 1)
8598   {
8599     sql_print_error("Invalid old_passwords mode: 1. Valid values are 2 and 0\n");
8600     return true;
8601   }
8602   if (!opt_secure_auth)
8603   {
8604     sql_print_error("Invalid secure_auth mode: 0. Valid value is 1\n");
8605     return true;
8606   }
8607 
8608   return false;
8609 }
8610 
8611 
8612 /**
8613   Get server options from the command line,
8614   and perform related server initializations.
8615   @param [in, out] argc_ptr       command line options (count)
8616   @param [in, out] argv_ptr       command line options (values)
8617   @return 0 on success
8618 
8619   @todo
8620   - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
8621 */
get_options(int * argc_ptr,char *** argv_ptr)8622 static int get_options(int *argc_ptr, char ***argv_ptr)
8623 {
8624   int ho_error;
8625 
8626   my_getopt_register_get_addr(mysql_getopt_value);
8627 
8628   /* prepare all_options array */
8629   all_options.reserve(array_elements(my_long_options));
8630   for (my_option *opt= my_long_options;
8631        opt < my_long_options + array_elements(my_long_options) - 1;
8632        opt++)
8633   {
8634     all_options.push_back(*opt);
8635   }
8636   sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
8637   add_terminator(&all_options);
8638 
8639   if (opt_help || opt_bootstrap)
8640   {
8641     /*
8642       Show errors during --help, but gag everything else so the info the
8643       user actually wants isn't lost in the spam.  (For --help --verbose,
8644       we need to set up far enough to be able to print variables provided
8645       by plugins, so a good number of warnings/notes might get printed.)
8646       Likewise for --bootstrap.
8647     */
8648     struct my_option *opt= &all_options[0];
8649     for (; opt->name; opt++)
8650       if (!strcmp("log_error_verbosity", opt->name))
8651         opt->def_value= opt_initialize ? 2 : 1;
8652   }
8653 
8654   /* Skip unknown options so that they may be processed later by plugins */
8655   my_getopt_skip_unknown= TRUE;
8656 
8657   if ((ho_error= handle_options(argc_ptr, argv_ptr, &all_options[0],
8658                                 mysqld_get_one_option)))
8659     return ho_error;
8660 
8661   if (!opt_help)
8662     vector<my_option>().swap(all_options);  // Deletes the vector contents.
8663 
8664   /* Add back the program name handle_options removes */
8665   (*argc_ptr)++;
8666   (*argv_ptr)--;
8667 
8668   /*
8669     Options have been parsed. Now some of them need additional special
8670     handling, like custom value checking, checking of incompatibilites
8671     between options, setting of multiple variables, etc.
8672     Do them here.
8673   */
8674 
8675   if (!opt_help && opt_verbose)
8676     sql_print_error("--verbose is for use with --help; "
8677                     "did you mean --log-error-verbosity?");
8678 
8679   if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
8680        opt_log_slow_slave_statements) &&
8681       !opt_slow_log)
8682     sql_print_warning("options --log-slow-admin-statements, "
8683                       "--log-queries-not-using-indexes and "
8684                       "--log-slow-slave-statements have no effect if "
8685                       "--slow-query-log is not set");
8686   if (global_system_variables.net_buffer_length >
8687       global_system_variables.max_allowed_packet)
8688   {
8689     sql_print_warning("net_buffer_length (%lu) is set to be larger "
8690                       "than max_allowed_packet (%lu). Please rectify.",
8691                       global_system_variables.net_buffer_length,
8692                       global_system_variables.max_allowed_packet);
8693   }
8694 
8695   /*
8696     TIMESTAMP columns get implicit DEFAULT values when
8697     --explicit_defaults_for_timestamp is not set.
8698     This behavior is deprecated now.
8699   */
8700   if (!opt_help && !global_system_variables.explicit_defaults_for_timestamp)
8701     sql_print_warning("TIMESTAMP with implicit DEFAULT value is deprecated. "
8702                       "Please use --explicit_defaults_for_timestamp server "
8703                       "option (see documentation for more details).");
8704 
8705   opt_init_connect.length=strlen(opt_init_connect.str);
8706   opt_init_slave.length=strlen(opt_init_slave.str);
8707 
8708   if (global_system_variables.low_priority_updates)
8709     thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
8710 
8711   if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax))
8712   {
8713     sql_print_error("Invalid ft-boolean-syntax string: %s\n",
8714                     ft_boolean_syntax);
8715     return 1;
8716   }
8717 
8718   if (opt_disable_networking)
8719     mysqld_port= 0;
8720 
8721   if (opt_skip_show_db)
8722     opt_specialflag|= SPECIAL_SKIP_SHOW_DB;
8723 
8724   if (check_ghost_options())
8725     return 1;
8726 
8727   if (myisam_flush)
8728     flush_time= 0;
8729 
8730 #ifdef HAVE_REPLICATION
8731   if (opt_slave_skip_errors)
8732     add_slave_skip_errors(opt_slave_skip_errors);
8733 #endif
8734 
8735   if (global_system_variables.max_join_size == HA_POS_ERROR)
8736     global_system_variables.option_bits|= OPTION_BIG_SELECTS;
8737   else
8738     global_system_variables.option_bits&= ~OPTION_BIG_SELECTS;
8739 
8740 #ifdef WITH_WSREP
8741   if (global_system_variables.wsrep_causal_reads) {
8742       WSREP_WARN("option --wsrep-causal-reads is deprecated");
8743       if (!(global_system_variables.wsrep_sync_wait &
8744             WSREP_SYNC_WAIT_BEFORE_READ)) {
8745           WSREP_WARN("--wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=%u. "
8746                      "WSREP_SYNC_WAIT_BEFORE_READ is on",
8747                      global_system_variables.wsrep_sync_wait);
8748           global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
8749       } else {
8750           // they are turned on both.
8751       }
8752   } else {
8753       if (global_system_variables.wsrep_sync_wait &
8754           WSREP_SYNC_WAIT_BEFORE_READ) {
8755           WSREP_WARN("--wsrep-sync-wait=%u takes precedence over --wsrep-causal-reads=OFF. "
8756                      "WSREP_SYNC_WAIT_BEFORE_READ is on",
8757                      global_system_variables.wsrep_sync_wait);
8758           global_system_variables.wsrep_causal_reads = 1;
8759       } else {
8760           // they are turned off both.
8761       }
8762   }
8763 #endif // WITH_WSREP
8764 
8765   // Synchronize @@global.autocommit on --autocommit
8766   const ulonglong turn_bit_on= opt_autocommit ?
8767     OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
8768   global_system_variables.option_bits=
8769     (global_system_variables.option_bits &
8770      ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) | turn_bit_on;
8771 
8772   global_system_variables.sql_mode=
8773     expand_sql_mode(global_system_variables.sql_mode, NULL);
8774 
8775   if (!(global_system_variables.sql_mode & MODE_NO_AUTO_CREATE_USER))
8776   {
8777     sql_print_warning("'NO_AUTO_CREATE_USER' sql mode was not set.");
8778   }
8779 
8780   if (!my_enable_symlinks)
8781     have_symlink= SHOW_OPTION_DISABLED;
8782 
8783   if (opt_debugging)
8784   {
8785     /* Allow break with SIGINT, no core or stack trace */
8786     test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
8787     test_flags&= ~TEST_CORE_ON_SIGNAL;
8788   }
8789   /* Set global MyISAM variables from delay_key_write_options */
8790   fix_delay_key_write(0, 0, OPT_GLOBAL);
8791 
8792 #ifndef EMBEDDED_LIBRARY
8793 #ifndef _WIN32
8794   if (mysqld_chroot)
8795     set_root(mysqld_chroot);
8796 #endif
8797 #else
8798   max_allowed_packet= global_system_variables.max_allowed_packet;
8799   net_buffer_length= global_system_variables.net_buffer_length;
8800 #endif
8801   if (fix_paths())
8802     return 1;
8803 
8804   /*
8805     Set some global variables from the global_system_variables
8806     In most cases the global variables will not be used
8807   */
8808   my_disable_locking= myisam_single_user= MY_TEST(opt_external_locking == 0);
8809   my_default_record_cache_size=global_system_variables.read_buff_size;
8810 
8811   global_system_variables.long_query_time= (ulonglong)
8812     (global_system_variables.long_query_time_double * 1e6);
8813 
8814   if (opt_short_log_format)
8815     opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
8816 
8817   if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
8818                                   &global_date_format) ||
8819       init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
8820                                   &global_time_format) ||
8821       init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
8822                                   &global_datetime_format))
8823     return 1;
8824 
8825 #ifndef EMBEDDED_LIBRARY
8826   if (Connection_handler_manager::init())
8827   {
8828     sql_print_error("Could not allocate memory for connection handling");
8829     return 1;
8830   }
8831 #endif
8832   if (Global_THD_manager::create_instance())
8833   {
8834     sql_print_error("Could not allocate memory for thread handling");
8835     return 1;
8836   }
8837 
8838   /* If --super-read-only was specified, set read_only to 1 */
8839   read_only= super_read_only ? super_read_only : read_only;
8840   opt_readonly= read_only;
8841 
8842   return 0;
8843 }
8844 
8845 
8846 /*
8847   Create version name for running mysqld version
8848   We automaticly add suffixes -debug, -embedded, -log, -valgrind and -asan
8849   to the version name to make the version more descriptive.
8850   (MYSQL_SERVER_SUFFIX is set by the compilation environment)
8851 */
8852 
set_server_version(void)8853 static void set_server_version(void)
8854 {
8855   char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
8856                      MYSQL_SERVER_SUFFIX_STR, NullS);
8857 #ifdef EMBEDDED_LIBRARY
8858   end= my_stpcpy(end, "-embedded");
8859 #endif
8860 #ifndef NDEBUG
8861   if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
8862     end= my_stpcpy(end, "-debug");
8863 #endif
8864   if (opt_general_log || opt_slow_log || opt_bin_log)
8865     end= my_stpcpy(end, "-log");          // This may slow down system
8866 #ifdef HAVE_VALGRIND
8867   if (SERVER_VERSION_LENGTH - (end - server_version) >
8868       static_cast<int>(sizeof("-valgrind")))
8869     end= my_stpcpy(end, "-valgrind");
8870 #endif
8871 #ifdef HAVE_ASAN
8872   if (SERVER_VERSION_LENGTH - (end - server_version) >
8873       static_cast<int>(sizeof("-asan")))
8874     end= my_stpcpy(end, "-asan");
8875 #endif
8876 }
8877 
8878 
get_relative_path(const char * path)8879 static char *get_relative_path(const char *path)
8880 {
8881   if (test_if_hard_path(path) &&
8882       is_prefix(path,DEFAULT_MYSQL_HOME) &&
8883       strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
8884   {
8885     path+= strlen(DEFAULT_MYSQL_HOME);
8886     while (is_directory_separator(*path))
8887       path++;
8888   }
8889   return (char*) path;
8890 }
8891 
8892 
8893 /**
8894   Fix filename and replace extension where 'dir' is relative to
8895   mysql_real_data_home.
8896   @return
8897     1 if len(path) > FN_REFLEN
8898 */
8899 
8900 bool
fn_format_relative_to_data_home(char * to,const char * name,const char * dir,const char * extension)8901 fn_format_relative_to_data_home(char * to, const char *name,
8902         const char *dir, const char *extension)
8903 {
8904   char tmp_path[FN_REFLEN];
8905   if (!test_if_hard_path(dir))
8906   {
8907     strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
8908        dir, NullS);
8909     dir=tmp_path;
8910   }
8911   return !fn_format(to, name, dir, extension,
8912         MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
8913 }
8914 
8915 
8916 /**
8917   Test a file path to determine if the path is compatible with the secure file
8918   path restriction.
8919 
8920   @param path null terminated character string
8921 
8922   @return
8923     @retval TRUE The path is secure
8924     @retval FALSE The path isn't secure
8925 */
8926 
is_secure_file_path(char * path)8927 bool is_secure_file_path(char *path)
8928 {
8929   char buff1[FN_REFLEN], buff2[FN_REFLEN];
8930   size_t opt_secure_file_priv_len;
8931   /*
8932     All paths are secure if opt_secure_file_priv is 0
8933   */
8934   if (!opt_secure_file_priv[0])
8935     return TRUE;
8936 
8937   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
8938 
8939   if (strlen(path) >= FN_REFLEN)
8940     return FALSE;
8941 
8942   if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
8943     return FALSE;
8944 
8945   if (my_realpath(buff1, path, 0))
8946   {
8947     /*
8948       The supplied file path might have been a file and not a directory.
8949     */
8950     int length= (int)dirname_length(path);
8951     if (length >= FN_REFLEN)
8952       return FALSE;
8953     memcpy(buff2, path, length);
8954     buff2[length]= '\0';
8955     if (length == 0 || my_realpath(buff1, buff2, 0))
8956       return FALSE;
8957   }
8958   convert_dirname(buff2, buff1, NullS);
8959   if (!lower_case_file_system)
8960   {
8961     if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
8962       return FALSE;
8963   }
8964   else
8965   {
8966     if (files_charset_info->coll->strnncoll(files_charset_info,
8967                                             (uchar *) buff2, strlen(buff2),
8968                                             (uchar *) opt_secure_file_priv,
8969                                             opt_secure_file_priv_len,
8970                                             TRUE))
8971       return FALSE;
8972   }
8973   return TRUE;
8974 }
8975 
8976 
8977 /**
8978   check_secure_file_priv_path : Checks path specified through
8979   --secure-file-priv and raises warning in following cases:
8980   1. If path is empty string or NULL and mysqld is not running
8981      with --bootstrap mode.
8982   2. If path can access data directory
8983   3. If path points to a directory which is accessible by
8984      all OS users (non-Windows build only)
8985 
8986   It throws error in following cases:
8987 
8988   1. If path normalization fails
8989   2. If it can not get stats of the directory
8990 
8991   @params NONE
8992 
8993   Assumptions :
8994   1. Data directory path has been normalized
8995   2. opt_secure_file_priv has been normalized unless it is set
8996      to "NULL".
8997 
8998   @returns Status of validation
8999     @retval true : Validation is successful with/without warnings
9000     @retval false : Validation failed. Error is raised.
9001 */
9002 
check_secure_file_priv_path()9003 bool check_secure_file_priv_path()
9004 {
9005   char datadir_buffer[FN_REFLEN+1]={0};
9006   char plugindir_buffer[FN_REFLEN+1]={0};
9007   char whichdir[20]= {0};
9008   size_t opt_plugindir_len= 0;
9009   size_t opt_datadir_len= 0;
9010   size_t opt_secure_file_priv_len= 0;
9011   bool warn= false;
9012   bool case_insensitive_fs;
9013 #ifndef _WIN32
9014   MY_STAT dir_stat;
9015 #endif
9016 
9017   if (!opt_secure_file_priv[0])
9018   {
9019     if (opt_bootstrap)
9020     {
9021       /*
9022         Do not impose --secure-file-priv restriction
9023         in --bootstrap mode
9024       */
9025       sql_print_information("Ignoring --secure-file-priv value as server is "
9026                             "running with --initialize(-insecure) or "
9027                             "--bootstrap.");
9028     }
9029     else
9030     {
9031       sql_print_warning("Insecure configuration for --secure-file-priv: "
9032                         "Current value does not restrict location of generated "
9033                         "files. Consider setting it to a valid, "
9034                         "non-empty path.");
9035     }
9036     return true;
9037   }
9038 
9039   /*
9040     Setting --secure-file-priv to NULL would disable
9041     reading/writing from/to file
9042   */
9043   if(!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
9044   {
9045     sql_print_information("--secure-file-priv is set to NULL. "
9046                           "Operations related to importing and exporting "
9047                           "data are disabled");
9048     return true;
9049   }
9050 
9051   /*
9052     Check if --secure-file-priv can access data directory
9053   */
9054   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
9055 
9056   /*
9057     Adds dir seperator at the end.
9058     This is required in subsequent comparison
9059   */
9060   convert_dirname(datadir_buffer, mysql_unpacked_real_data_home, NullS);
9061   opt_datadir_len= strlen(datadir_buffer);
9062 
9063   case_insensitive_fs=
9064     (test_if_case_insensitive(datadir_buffer) == 1);
9065 
9066   if (!case_insensitive_fs)
9067   {
9068     if (!strncmp(datadir_buffer, opt_secure_file_priv,
9069           opt_datadir_len < opt_secure_file_priv_len ?
9070           opt_datadir_len : opt_secure_file_priv_len))
9071     {
9072       warn= true;
9073       strcpy(whichdir, "Data directory");
9074     }
9075   }
9076   else
9077   {
9078     if (!files_charset_info->coll->strnncoll(files_charset_info,
9079           (uchar *) datadir_buffer,
9080           opt_datadir_len,
9081           (uchar *) opt_secure_file_priv,
9082           opt_secure_file_priv_len,
9083           TRUE))
9084     {
9085       warn= true;
9086       strcpy(whichdir, "Data directory");
9087     }
9088   }
9089 
9090   /*
9091     Don't bother comparing --secure-file-priv with --plugin-dir
9092     if we already have a match against --datdir or
9093     --plugin-dir is not pointing to a valid directory.
9094   */
9095   if (!warn && !my_realpath(plugindir_buffer, opt_plugin_dir, 0))
9096   {
9097     convert_dirname(plugindir_buffer, plugindir_buffer, NullS);
9098     opt_plugindir_len= strlen(plugindir_buffer);
9099 
9100     if (!case_insensitive_fs)
9101     {
9102       if (!strncmp(plugindir_buffer, opt_secure_file_priv,
9103           opt_plugindir_len < opt_secure_file_priv_len ?
9104           opt_plugindir_len : opt_secure_file_priv_len))
9105       {
9106         warn= true;
9107         strcpy(whichdir, "Plugin directory");
9108       }
9109     }
9110     else
9111     {
9112       if (!files_charset_info->coll->strnncoll(files_charset_info,
9113           (uchar *) plugindir_buffer,
9114           opt_plugindir_len,
9115           (uchar *) opt_secure_file_priv,
9116           opt_secure_file_priv_len,
9117           TRUE))
9118       {
9119         warn= true;
9120         strcpy(whichdir, "Plugin directory");
9121       }
9122     }
9123   }
9124 
9125 
9126   if (warn)
9127     sql_print_warning("Insecure configuration for --secure-file-priv: "
9128                       "%s is accessible through "
9129                       "--secure-file-priv. Consider choosing a different "
9130                       "directory.", whichdir);
9131 
9132 #ifndef _WIN32
9133   /*
9134      Check for --secure-file-priv directory's permission
9135   */
9136   if (!(my_stat(opt_secure_file_priv, &dir_stat, MYF(0))))
9137   {
9138     sql_print_error("Failed to get stat for directory pointed out "
9139                     "by --secure-file-priv");
9140     return false;
9141   }
9142 
9143   if (dir_stat.st_mode & S_IRWXO)
9144     sql_print_warning("Insecure configuration for --secure-file-priv: "
9145                       "Location is accessible to all OS users. "
9146                       "Consider choosing a different directory.");
9147 #endif
9148   return true;
9149 }
9150 
fix_paths(void)9151 static int fix_paths(void)
9152 {
9153   char buff[FN_REFLEN],*pos;
9154   bool secure_file_priv_nonempty= false;
9155   convert_dirname(mysql_home,mysql_home,NullS);
9156   /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
9157   my_realpath(mysql_home,mysql_home,MYF(0));
9158   /* Ensure that mysql_home ends in FN_LIBCHAR */
9159   pos=strend(mysql_home);
9160   if (pos[-1] != FN_LIBCHAR)
9161   {
9162     pos[0]= FN_LIBCHAR;
9163     pos[1]= 0;
9164   }
9165   convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
9166   convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
9167   (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
9168   (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
9169   (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
9170 
9171   convert_dirname(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
9172                                   get_relative_path(PLUGINDIR), NullS);
9173   (void) my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
9174   opt_plugin_dir_ptr= opt_plugin_dir;
9175 
9176   my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
9177   mysql_unpacked_real_data_home_len=
9178     strlen(mysql_unpacked_real_data_home);
9179   if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
9180     --mysql_unpacked_real_data_home_len;
9181 
9182   char *sharedir=get_relative_path(SHAREDIR);
9183   if (test_if_hard_path(sharedir))
9184     strmake(buff,sharedir,sizeof(buff)-1);    /* purecov: tested */
9185   else
9186     strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
9187   convert_dirname(buff,buff,NullS);
9188   (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
9189 
9190   /* If --character-sets-dir isn't given, use shared library dir */
9191   if (charsets_dir)
9192     strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir)-1);
9193   else
9194     strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
9195        CHARSET_DIR, NullS);
9196   (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
9197   convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
9198   charsets_dir=mysql_charsets_dir;
9199 
9200   if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
9201     return 1;
9202   if (!opt_mysql_tmpdir)
9203     opt_mysql_tmpdir= mysql_tmpdir;
9204 #ifdef HAVE_REPLICATION
9205   if (!slave_load_tmpdir)
9206     slave_load_tmpdir= mysql_tmpdir;
9207 #endif /* HAVE_REPLICATION */
9208   /*
9209     Convert the secure-file-priv option to system format, allowing
9210     a quick strcmp to check if read or write is in an allowed dir
9211   */
9212   if (opt_bootstrap)
9213     opt_secure_file_priv= EMPTY_STR.str;
9214   secure_file_priv_nonempty= opt_secure_file_priv[0] ? true : false;
9215 
9216   if (secure_file_priv_nonempty && strlen(opt_secure_file_priv) > FN_REFLEN)
9217   {
9218     sql_print_warning("Value for --secure-file-priv is longer than maximum "
9219                       "limit of %d", FN_REFLEN-1);
9220     return 1;
9221   }
9222 
9223   memset(buff, 0, sizeof(buff));
9224   if (secure_file_priv_nonempty &&
9225       my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
9226   {
9227     int retval= my_realpath(buff, opt_secure_file_priv, MYF(MY_WME));
9228     if (!retval)
9229     {
9230       convert_dirname(secure_file_real_path, buff, NullS);
9231 #ifdef WIN32
9232       MY_DIR *dir= my_dir(secure_file_real_path, MYF(MY_DONT_SORT+MY_WME));
9233       if (!dir)
9234       {
9235         retval= 1;
9236       }
9237       else
9238       {
9239         my_dirend(dir);
9240       }
9241 #endif
9242     }
9243 
9244     if (retval)
9245     {
9246       char err_buffer[FN_REFLEN];
9247       my_snprintf(err_buffer, FN_REFLEN-1,
9248                   "Failed to access directory for --secure-file-priv."
9249                   " Please make sure that directory exists and is "
9250                   "accessible by MySQL Server. Supplied value : %s",
9251                   opt_secure_file_priv);
9252       err_buffer[FN_REFLEN-1]='\0';
9253       sql_print_error("%s", err_buffer);
9254       return 1;
9255     }
9256     opt_secure_file_priv= secure_file_real_path;
9257   }
9258 
9259   if (!check_secure_file_priv_path())
9260     return 1;
9261 
9262   return 0;
9263 }
9264 
9265 /**
9266   Check if file system used for databases is case insensitive.
9267 
9268   @param dir_name     Directory to test
9269 
9270   @retval
9271     -1  Don't know (Test failed)
9272   @retval
9273     0   File system is case sensitive
9274   @retval
9275     1   File system is case insensitive
9276 */
9277 
test_if_case_insensitive(const char * dir_name)9278 static int test_if_case_insensitive(const char *dir_name)
9279 {
9280   int result= 0;
9281   File file;
9282   char buff[FN_REFLEN], buff2[FN_REFLEN];
9283   MY_STAT stat_info;
9284   DBUG_ENTER("test_if_case_insensitive");
9285 
9286   fn_format(buff, glob_hostname, dir_name, ".lower-test",
9287       MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
9288   fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
9289       MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
9290   mysql_file_delete(key_file_casetest, buff2, MYF(0));
9291   if ((file= mysql_file_create(key_file_casetest,
9292                                buff, 0666, O_RDWR, MYF(0))) < 0)
9293   {
9294     sql_print_warning("Can't create test file %s", buff);
9295     DBUG_RETURN(-1);
9296   }
9297   mysql_file_close(file, MYF(0));
9298   if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
9299     result= 1;          // Can access file
9300   mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
9301   DBUG_PRINT("exit", ("result: %d", result));
9302   DBUG_RETURN(result);
9303 }
9304 
9305 
9306 #ifndef EMBEDDED_LIBRARY
9307 
9308 /**
9309   Create file to store pid number.
9310 */
create_pid_file()9311 static void create_pid_file()
9312 {
9313   File file;
9314   bool check_parent_path= 1, is_path_accessible= 1;
9315   char pid_filepath[FN_REFLEN], *pos= NULL;
9316   /* Copy pid file name to get pid file path */
9317   strcpy(pid_filepath, pidfile_name);
9318 
9319   /* Iterate through the entire path to check if even one of the sub-dirs
9320      is world-writable */
9321   while (check_parent_path && (pos= strrchr(pid_filepath, FN_LIBCHAR))
9322          && (pos != pid_filepath)) /* shouldn't check root */
9323   {
9324     *pos= '\0';  /* Trim the inner-most dir */
9325     switch (is_file_or_dir_world_writable(pid_filepath))
9326     {
9327       case -2:
9328         is_path_accessible= 0;
9329         break;
9330       case -1:
9331         sql_print_error("Can't start server: can't check PID filepath: %s",
9332                         strerror(errno));
9333         exit(MYSQLD_ABORT_EXIT);
9334       case 1:
9335         sql_print_warning("Insecure configuration for --pid-file: Location "
9336                           "'%s' in the path is accessible to all OS users. "
9337                           "Consider choosing a different directory.",
9338                           pid_filepath);
9339         check_parent_path= 0;
9340         break;
9341       case 0:
9342         continue; /* Keep checking the parent dir */
9343     }
9344   }
9345   if (!is_path_accessible)
9346   {
9347     sql_print_warning("Few location(s) are inaccessible while checking PID filepath.");
9348   }
9349   if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
9350                                O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
9351   {
9352     char buff[MAX_BIGINT_WIDTH + 1], *end;
9353     end= int10_to_str((long) getpid(), buff, 10);
9354     *end++= '\n';
9355     if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
9356                           MYF(MY_WME | MY_NABP)))
9357     {
9358       mysql_file_close(file, MYF(0));
9359       pid_file_created= true;
9360       return;
9361     }
9362     mysql_file_close(file, MYF(0));
9363   }
9364   sql_print_error("Can't start server: can't create PID file: %s",
9365                   strerror(errno));
9366   exit(MYSQLD_ABORT_EXIT);
9367 }
9368 
9369 
9370 /**
9371   Remove the process' pid file.
9372 
9373   @param  flags  file operation flags
9374 */
9375 
delete_pid_file(myf flags)9376 static void delete_pid_file(myf flags)
9377 {
9378   File file;
9379   if (opt_bootstrap ||
9380       !pid_file_created ||
9381       !(file= mysql_file_open(key_file_pid, pidfile_name,
9382                               O_RDONLY, flags)))
9383     return;
9384 
9385   if (file == -1)
9386   {
9387     sql_print_information("Unable to delete pid file: %s", strerror(errno));
9388     return;
9389   }
9390 
9391   uchar buff[MAX_BIGINT_WIDTH + 1];
9392   /* Make sure that the pid file was created by the same process. */
9393   size_t error= mysql_file_read(file, buff, sizeof(buff), flags);
9394   mysql_file_close(file, flags);
9395   buff[sizeof(buff) - 1]= '\0';
9396   if (error != MY_FILE_ERROR &&
9397       atol((char *) buff) == (long) getpid())
9398   {
9399     mysql_file_delete(key_file_pid, pidfile_name, flags);
9400     pid_file_created= false;
9401   }
9402   return;
9403 }
9404 #endif /* EMBEDDED_LIBRARY */
9405 
9406 
9407 /**
9408   Returns the current state of the server : booting, operational or shutting
9409   down.
9410 
9411   @return
9412     SERVER_BOOTING        Server is not operational. It is starting.
9413     SERVER_OPERATING      Server is fully initialized and operating.
9414     SERVER_SHUTTING_DOWN  Server is shutting down.
9415 */
get_server_state()9416 enum_server_operational_state get_server_state()
9417 {
9418   return server_operational_state;
9419 }
9420 
9421 /**
9422   Reset status for all threads.
9423 */
9424 class Reset_thd_status : public Do_THD_Impl
9425 {
9426 public:
Reset_thd_status()9427   Reset_thd_status() { }
operator ()(THD * thd)9428   virtual void operator()(THD *thd)
9429   {
9430     /*
9431       Add thread's status variabes to global status
9432       and reset thread's status variables.
9433     */
9434     add_to_status(&global_status_var, &thd->status_var, true);
9435   }
9436 };
9437 
9438 /**
9439   Reset global and session status variables.
9440 */
refresh_status(THD * thd)9441 void refresh_status(THD *thd)
9442 {
9443   mysql_mutex_lock(&LOCK_status);
9444 
9445   if (show_compatibility_56)
9446   {
9447     /*
9448       Add thread's status variabes to global status
9449       and reset current thread's status variables.
9450     */
9451     add_to_status(&global_status_var, &thd->status_var, true);
9452   }
9453   else
9454   {
9455     /* For all threads, add status to global status and then reset. */
9456     Reset_thd_status reset_thd_status;
9457     Global_THD_manager::get_instance()->do_for_all_thd_copy(&reset_thd_status);
9458 #ifndef EMBEDDED_LIBRARY
9459 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
9460     /* Reset aggregated status counters. */
9461     reset_pfs_status_stats();
9462 #endif
9463 #endif
9464   }
9465 
9466   /* Reset some global variables. */
9467   reset_status_vars();
9468 #ifdef WITH_WSREP
9469   wsrep->stats_reset(wsrep);
9470 #endif /* WITH_WSREP */
9471 
9472   /* Reset the counters of all key caches (default and named). */
9473   process_key_caches(reset_key_cache_counters);
9474   flush_status_time= time((time_t*) 0);
9475   mysql_mutex_unlock(&LOCK_status);
9476 
9477 #ifndef EMBEDDED_LIBRARY
9478   /*
9479     Set max_used_connections to the number of currently open
9480     connections.  Do this out of LOCK_status to avoid deadlocks.
9481     Status reset becomes not atomic, but status data is not exact anyway.
9482   */
9483   Connection_handler_manager::reset_max_used_connections();
9484 #endif
9485 }
9486 
9487 
9488 /*****************************************************************************
9489   Instantiate variables for missing storage engines
9490   This section should go away soon
9491 *****************************************************************************/
9492 
9493 #ifdef HAVE_PSI_INTERFACE
9494 PSI_mutex_key key_LOCK_tc;
9495 
9496 #ifdef HAVE_OPENSSL
9497 PSI_mutex_key key_LOCK_des_key_file;
9498 #endif /* HAVE_OPENSSL */
9499 
9500 PSI_mutex_key key_BINLOG_LOCK_commit;
9501 PSI_mutex_key key_BINLOG_LOCK_commit_queue;
9502 PSI_mutex_key key_BINLOG_LOCK_done;
9503 PSI_mutex_key key_BINLOG_LOCK_flush_queue;
9504 PSI_mutex_key key_BINLOG_LOCK_index;
9505 PSI_mutex_key key_BINLOG_LOCK_log;
9506 PSI_mutex_key key_BINLOG_LOCK_binlog_end_pos;
9507 PSI_mutex_key key_BINLOG_LOCK_sync;
9508 PSI_mutex_key key_BINLOG_LOCK_sync_queue;
9509 PSI_mutex_key key_BINLOG_LOCK_xids;
9510 PSI_mutex_key
9511   key_hash_filo_lock,
9512   Gtid_set::key_gtid_executed_free_intervals_mutex,
9513   key_LOCK_crypt, key_LOCK_error_log,
9514   key_LOCK_gdl, key_LOCK_global_system_variables,
9515   key_LOCK_manager,
9516   key_LOCK_prepared_stmt_count,
9517   key_LOCK_server_started, key_LOCK_status,
9518   key_LOCK_sql_slave_skip_counter,
9519   key_LOCK_slave_net_timeout,
9520   key_LOCK_slave_trans_dep_tracker,
9521   key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
9522   key_LOCK_thd_sysvar,
9523   key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
9524   key_master_info_data_lock, key_master_info_run_lock,
9525   key_master_info_sleep_lock, key_master_info_thd_lock,
9526   key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
9527   key_relay_log_info_sleep_lock, key_relay_log_info_thd_lock,
9528   key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
9529   key_mutex_slave_parallel_pend_jobs, key_mutex_mts_temp_tables_lock,
9530   key_mutex_slave_parallel_worker_count,
9531   key_mutex_slave_parallel_worker,
9532   key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
9533   key_LOCK_error_messages,
9534   key_LOCK_log_throttle_qni, key_LOCK_query_plan, key_LOCK_thd_query,
9535   key_LOCK_cost_const, key_LOCK_current_cond,
9536   key_LOCK_keyring_operations;
9537 
9538 #ifdef WITH_WSREP
9539 PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd,
9540   key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst,
9541   key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init,
9542   key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync;
9543 #endif
9544 
9545 PSI_mutex_key key_RELAYLOG_LOCK_commit;
9546 PSI_mutex_key key_RELAYLOG_LOCK_commit_queue;
9547 PSI_mutex_key key_RELAYLOG_LOCK_done;
9548 PSI_mutex_key key_RELAYLOG_LOCK_flush_queue;
9549 PSI_mutex_key key_RELAYLOG_LOCK_index;
9550 PSI_mutex_key key_RELAYLOG_LOCK_log;
9551 PSI_mutex_key key_RELAYLOG_LOCK_sync;
9552 PSI_mutex_key key_RELAYLOG_LOCK_sync_queue;
9553 PSI_mutex_key key_RELAYLOG_LOCK_xids;
9554 PSI_mutex_key key_LOCK_sql_rand;
9555 PSI_mutex_key key_gtid_ensure_index_mutex;
9556 PSI_mutex_key key_mts_temp_table_LOCK;
9557 PSI_mutex_key key_LOCK_reset_gtid_table;
9558 PSI_mutex_key key_LOCK_compress_gtid_table;
9559 PSI_mutex_key key_mts_gaq_LOCK;
9560 PSI_mutex_key key_thd_timer_mutex;
9561 PSI_mutex_key key_LOCK_offline_mode;
9562 PSI_mutex_key key_LOCK_default_password_lifetime;
9563 
9564 #ifdef HAVE_REPLICATION
9565 PSI_mutex_key key_commit_order_manager_mutex;
9566 PSI_mutex_key key_mutex_slave_worker_hash;
9567 #endif
9568 
9569 static PSI_mutex_info all_server_mutexes[]=
9570 {
9571   { &key_LOCK_tc, "TC_LOG_MMAP::LOCK_tc", 0},
9572 
9573 #ifdef HAVE_OPENSSL
9574   { &key_LOCK_des_key_file, "LOCK_des_key_file", PSI_FLAG_GLOBAL},
9575 #endif /* HAVE_OPENSSL */
9576 
9577   { &key_BINLOG_LOCK_commit, "MYSQL_BIN_LOG::LOCK_commit", 0 },
9578   { &key_BINLOG_LOCK_commit_queue, "MYSQL_BIN_LOG::LOCK_commit_queue", 0 },
9579   { &key_BINLOG_LOCK_done, "MYSQL_BIN_LOG::LOCK_done", 0 },
9580   { &key_BINLOG_LOCK_flush_queue, "MYSQL_BIN_LOG::LOCK_flush_queue", 0 },
9581   { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0},
9582   { &key_BINLOG_LOCK_log, "MYSQL_BIN_LOG::LOCK_log", 0},
9583   { &key_BINLOG_LOCK_binlog_end_pos, "MYSQL_BIN_LOG::LOCK_binlog_end_pos", 0},
9584   { &key_BINLOG_LOCK_sync, "MYSQL_BIN_LOG::LOCK_sync", 0},
9585   { &key_BINLOG_LOCK_sync_queue, "MYSQL_BIN_LOG::LOCK_sync_queue", 0 },
9586   { &key_BINLOG_LOCK_xids, "MYSQL_BIN_LOG::LOCK_xids", 0 },
9587   { &key_RELAYLOG_LOCK_commit, "MYSQL_RELAY_LOG::LOCK_commit", 0},
9588   { &key_RELAYLOG_LOCK_commit_queue, "MYSQL_RELAY_LOG::LOCK_commit_queue", 0 },
9589   { &key_RELAYLOG_LOCK_done, "MYSQL_RELAY_LOG::LOCK_done", 0 },
9590   { &key_RELAYLOG_LOCK_flush_queue, "MYSQL_RELAY_LOG::LOCK_flush_queue", 0 },
9591   { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
9592   { &key_RELAYLOG_LOCK_log, "MYSQL_RELAY_LOG::LOCK_log", 0},
9593   { &key_RELAYLOG_LOCK_sync, "MYSQL_RELAY_LOG::LOCK_sync", 0},
9594   { &key_RELAYLOG_LOCK_sync_queue, "MYSQL_RELAY_LOG::LOCK_sync_queue", 0 },
9595   { &key_RELAYLOG_LOCK_xids, "MYSQL_RELAY_LOG::LOCK_xids", 0},
9596   { &key_hash_filo_lock, "hash_filo::lock", 0},
9597   { &Gtid_set::key_gtid_executed_free_intervals_mutex, "Gtid_set::gtid_executed::free_intervals_mutex", 0 },
9598   { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
9599   { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL},
9600   { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
9601   { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
9602 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
9603   { &key_LOCK_handler_count, "LOCK_handler_count", PSI_FLAG_GLOBAL},
9604 #endif
9605   { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
9606   { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
9607   { &key_LOCK_sql_slave_skip_counter, "LOCK_sql_slave_skip_counter", PSI_FLAG_GLOBAL},
9608   { &key_LOCK_slave_net_timeout, "LOCK_slave_net_timeout", PSI_FLAG_GLOBAL},
9609   { &key_LOCK_slave_trans_dep_tracker, "LOCK_slave_trans_dep_tracker", PSI_FLAG_GLOBAL},
9610   { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL},
9611   { &key_LOCK_keyring_operations, "LOCK_keyring_operations", PSI_FLAG_GLOBAL},
9612 #if !defined(EMBEDDED_LIBRARY) && !defined(_WIN32)
9613   { &key_LOCK_socket_listener_active, "LOCK_socket_listener_active", PSI_FLAG_GLOBAL},
9614   { &key_LOCK_start_signal_handler, "LOCK_start_signal_handler", PSI_FLAG_GLOBAL},
9615 #endif
9616   { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL},
9617   { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
9618   { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL},
9619   { &key_LOCK_thd_data, "THD::LOCK_thd_data", PSI_FLAG_VOLATILITY_SESSION},
9620   { &key_LOCK_thd_query, "THD::LOCK_thd_query", PSI_FLAG_VOLATILITY_SESSION},
9621   { &key_LOCK_thd_sysvar, "THD::LOCK_thd_sysvar", PSI_FLAG_VOLATILITY_SESSION},
9622   { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
9623   { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
9624   { &key_LOCK_sql_rand, "LOCK_sql_rand", PSI_FLAG_GLOBAL},
9625   { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
9626   { &key_master_info_data_lock, "Master_info::data_lock", 0},
9627   { &key_master_info_run_lock, "Master_info::run_lock", 0},
9628   { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
9629   { &key_master_info_thd_lock, "Master_info::info_thd_lock", 0},
9630   { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
9631   { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0},
9632   { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0},
9633   { &key_relay_log_info_thd_lock, "Relay_log_info::info_thd_lock", 0},
9634   { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0},
9635   { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0},
9636   { &key_mutex_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_lock", 0},
9637   { &key_mutex_slave_parallel_worker_count, "Relay_log_info::exit_count_lock", 0},
9638   { &key_mutex_mts_temp_tables_lock, "Relay_log_info::temp_tables_lock", 0},
9639   { &key_mutex_slave_parallel_worker, "Worker_info::jobs_lock", 0},
9640   { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
9641   { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
9642   { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
9643   { &key_LOCK_log_throttle_qni, "LOCK_log_throttle_qni", PSI_FLAG_GLOBAL},
9644   { &key_gtid_ensure_index_mutex, "Gtid_state", PSI_FLAG_GLOBAL},
9645   { &key_LOCK_query_plan, "THD::LOCK_query_plan", PSI_FLAG_VOLATILITY_SESSION},
9646   { &key_LOCK_cost_const, "Cost_constant_cache::LOCK_cost_const",
9647     PSI_FLAG_GLOBAL},
9648   { &key_LOCK_current_cond, "THD::LOCK_current_cond", PSI_FLAG_VOLATILITY_SESSION},
9649   { &key_mts_temp_table_LOCK, "key_mts_temp_table_LOCK", 0},
9650   { &key_LOCK_reset_gtid_table, "LOCK_reset_gtid_table", PSI_FLAG_GLOBAL},
9651   { &key_LOCK_compress_gtid_table, "LOCK_compress_gtid_table", PSI_FLAG_GLOBAL},
9652   { &key_mts_gaq_LOCK, "key_mts_gaq_LOCK", 0},
9653 #ifdef WITH_WSREP
9654   { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL},
9655   { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
9656   { &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0},
9657   { &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL},
9658   { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
9659   { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL},
9660   { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0},
9661   { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL},
9662   { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL},
9663   { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL},
9664 #endif
9665   { &key_thd_timer_mutex, "thd_timer_mutex", 0},
9666 #ifdef HAVE_REPLICATION
9667   { &key_commit_order_manager_mutex, "Commit_order_manager::m_mutex", 0},
9668   { &key_mutex_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0},
9669 #endif
9670   { &key_LOCK_offline_mode, "LOCK_offline_mode", PSI_FLAG_GLOBAL},
9671   { &key_LOCK_default_password_lifetime, "LOCK_default_password_lifetime", PSI_FLAG_GLOBAL}
9672 };
9673 
9674 PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
9675   key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
9676   key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
9677   key_rwlock_global_sid_lock, key_rwlock_gtid_mode_lock,
9678   key_rwlock_channel_map_lock, key_rwlock_channel_lock;
9679 
9680 PSI_rwlock_key key_rwlock_Trans_delegate_lock;
9681 PSI_rwlock_key key_rwlock_Server_state_delegate_lock;
9682 PSI_rwlock_key key_rwlock_Binlog_storage_delegate_lock;
9683 #ifdef HAVE_REPLICATION
9684 PSI_rwlock_key key_rwlock_Binlog_transmit_delegate_lock;
9685 PSI_rwlock_key key_rwlock_Binlog_relay_IO_delegate_lock;
9686 #endif
9687 
9688 static PSI_rwlock_info all_server_rwlocks[]=
9689 {
9690 #ifdef HAVE_REPLICATION
9691   { &key_rwlock_Binlog_transmit_delegate_lock, "Binlog_transmit_delegate::lock", PSI_FLAG_GLOBAL},
9692   { &key_rwlock_Binlog_relay_IO_delegate_lock, "Binlog_relay_IO_delegate::lock", PSI_FLAG_GLOBAL},
9693 #endif
9694   { &key_rwlock_LOCK_grant, "LOCK_grant", 0},
9695   { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
9696   { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
9697   { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
9698   { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
9699   { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0},
9700   { &key_rwlock_global_sid_lock, "gtid_commit_rollback", PSI_FLAG_GLOBAL},
9701   { &key_rwlock_gtid_mode_lock, "gtid_mode_lock", PSI_FLAG_GLOBAL},
9702   { &key_rwlock_channel_map_lock, "channel_map_lock", 0},
9703   { &key_rwlock_channel_lock, "channel_lock", 0},
9704   { &key_rwlock_Trans_delegate_lock, "Trans_delegate::lock", PSI_FLAG_GLOBAL},
9705   { &key_rwlock_Server_state_delegate_lock, "Server_state_delegate::lock", PSI_FLAG_GLOBAL},
9706   { &key_rwlock_Binlog_storage_delegate_lock, "Binlog_storage_delegate::lock", PSI_FLAG_GLOBAL},
9707 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
9708   { &key_rwlock_LOCK_named_pipe_full_access_group, "LOCK_named_pipe_full_access_group", PSI_FLAG_GLOBAL},
9709 #endif /* _WIN32 && !EMBEDDED_LIBRARY */
9710 };
9711 
9712 PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
9713 PSI_cond_key key_BINLOG_update_cond,
9714   key_COND_cache_status_changed, key_COND_manager,
9715   key_COND_server_started,
9716   key_item_func_sleep_cond, key_master_info_data_cond,
9717   key_master_info_start_cond, key_master_info_stop_cond,
9718   key_master_info_sleep_cond,
9719   key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
9720   key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
9721   key_relay_log_info_sleep_cond, key_cond_slave_parallel_pend_jobs,
9722   key_cond_slave_parallel_worker, key_cond_mts_gaq,
9723   key_cond_mts_submode_logical_clock,
9724   key_TABLE_SHARE_cond, key_user_level_lock_cond;
9725 #ifdef WITH_WSREP
9726 PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd,
9727   key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst,
9728   key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread,  key_COND_wsrep_thd_pool;
9729 
9730 #endif /* WITH_WSREP */
9731 PSI_cond_key key_RELAYLOG_update_cond;
9732 PSI_cond_key key_BINLOG_COND_done;
9733 PSI_cond_key key_RELAYLOG_COND_done;
9734 PSI_cond_key key_BINLOG_prep_xids_cond;
9735 PSI_cond_key key_RELAYLOG_prep_xids_cond;
9736 PSI_cond_key key_gtid_ensure_index_cond;
9737 PSI_cond_key key_COND_compress_gtid_table;
9738 PSI_cond_key key_COND_thr_lock;
9739 #ifdef HAVE_REPLICATION
9740 PSI_cond_key key_commit_order_manager_cond;
9741 PSI_cond_key key_cond_slave_worker_hash;
9742 #endif
9743 
9744 static PSI_cond_info all_server_conds[]=
9745 {
9746   { &key_PAGE_cond, "PAGE::cond", 0},
9747   { &key_COND_active, "TC_LOG_MMAP::COND_active", 0},
9748   { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0},
9749   { &key_BINLOG_COND_done, "MYSQL_BIN_LOG::COND_done", 0},
9750   { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
9751   { &key_BINLOG_prep_xids_cond, "MYSQL_BIN_LOG::prep_xids_cond", 0},
9752   { &key_RELAYLOG_COND_done, "MYSQL_RELAY_LOG::COND_done", 0},
9753   { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
9754   { &key_RELAYLOG_prep_xids_cond, "MYSQL_RELAY_LOG::prep_xids_cond", 0},
9755   { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
9756 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
9757   { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL},
9758 #endif
9759   { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
9760   { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
9761 #if !defined(EMBEDDED_LIBRARY) && !defined(_WIN32)
9762   { &key_COND_socket_listener_active, "COND_socket_listener_active", PSI_FLAG_GLOBAL},
9763   { &key_COND_start_signal_handler, "COND_start_signal_handler", PSI_FLAG_GLOBAL},
9764 #endif
9765 #ifdef WITH_WSREP
9766   { &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL},
9767   { &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL},
9768   { &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL},
9769   { &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0},
9770   { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL},
9771   { &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0},
9772   { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL},
9773   { &key_COND_wsrep_thd_pool, "COND_wsrep_thd_pool", PSI_FLAG_GLOBAL},
9774 #endif
9775   { &key_COND_thr_lock, "COND_thr_lock", 0 },
9776   { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0},
9777   { &key_master_info_data_cond, "Master_info::data_cond", 0},
9778   { &key_master_info_start_cond, "Master_info::start_cond", 0},
9779   { &key_master_info_stop_cond, "Master_info::stop_cond", 0},
9780   { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
9781   { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0},
9782   { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0},
9783   { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0},
9784   { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0},
9785   { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0},
9786   { &key_cond_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_cond", 0},
9787   { &key_cond_slave_parallel_worker, "Worker_info::jobs_cond", 0},
9788   { &key_cond_mts_gaq, "Relay_log_info::mts_gaq_cond", 0},
9789   { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
9790   { &key_user_level_lock_cond, "User_level_lock::cond", 0},
9791   { &key_gtid_ensure_index_cond, "Gtid_state", PSI_FLAG_GLOBAL},
9792   { &key_COND_compress_gtid_table, "COND_compress_gtid_table", PSI_FLAG_GLOBAL}
9793 #ifdef HAVE_REPLICATION
9794   ,
9795   { &key_commit_order_manager_cond, "Commit_order_manager::m_workers.cond", 0},
9796   { &key_cond_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0}
9797 #endif
9798 };
9799 
9800 PSI_thread_key key_thread_bootstrap, key_thread_handle_manager, key_thread_main,
9801   key_thread_one_connection, key_thread_signal_hand,
9802   key_thread_compress_gtid_table, key_thread_parser_service;
9803 PSI_thread_key key_thread_timer_notifier;
9804 
9805 static PSI_thread_info all_server_threads[]=
9806 {
9807 #if defined (_WIN32) && !defined (EMBEDDED_LIBRARY)
9808   { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL},
9809   { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL},
9810   { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL},
9811   { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL},
9812 #endif /* _WIN32 && !EMBEDDED_LIBRARY */
9813   { &key_thread_timer_notifier, "thread_timer_notifier", PSI_FLAG_GLOBAL},
9814   { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL},
9815   { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL},
9816   { &key_thread_main, "main", PSI_FLAG_GLOBAL},
9817   { &key_thread_one_connection, "one_connection", 0},
9818   { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL},
9819   { &key_thread_compress_gtid_table, "compress_gtid_table", PSI_FLAG_GLOBAL},
9820   { &key_thread_parser_service, "parser_service", PSI_FLAG_GLOBAL},
9821 };
9822 
9823 PSI_file_key key_file_map;
9824 PSI_file_key key_file_binlog, key_file_binlog_cache,
9825   key_file_binlog_index, key_file_binlog_index_cache, key_file_casetest,
9826   key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
9827   key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
9828   key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
9829   key_file_master_info, key_file_misc, key_file_partition_ddl_log,
9830   key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
9831   key_file_trg, key_file_trn, key_file_init;
9832 PSI_file_key key_file_general_log, key_file_slow_log;
9833 PSI_file_key key_file_relaylog, key_file_relaylog_cache, key_file_relaylog_index, key_file_relaylog_index_cache;
9834 
9835 static PSI_file_info all_server_files[]=
9836 {
9837   { &key_file_map, "map", 0},
9838   { &key_file_binlog, "binlog", 0},
9839   { &key_file_binlog_cache, "binlog_cache", 0},
9840   { &key_file_binlog_index, "binlog_index", 0},
9841   { &key_file_binlog_index_cache, "binlog_index_cache", 0},
9842   { &key_file_relaylog, "relaylog", 0},
9843   { &key_file_relaylog_cache, "relaylog_cache", 0},
9844   { &key_file_relaylog_index, "relaylog_index", 0},
9845   { &key_file_relaylog_index_cache, "relaylog_index_cache", 0},
9846   { &key_file_io_cache, "io_cache", 0},
9847   { &key_file_casetest, "casetest", 0},
9848   { &key_file_dbopt, "dbopt", 0},
9849   { &key_file_des_key_file, "des_key_file", 0},
9850   { &key_file_ERRMSG, "ERRMSG", 0},
9851   { &key_select_to_file, "select_to_file", 0},
9852   { &key_file_fileparser, "file_parser", 0},
9853   { &key_file_frm, "FRM", 0},
9854   { &key_file_global_ddl_log, "global_ddl_log", 0},
9855   { &key_file_load, "load", 0},
9856   { &key_file_loadfile, "LOAD_FILE", 0},
9857   { &key_file_log_event_data, "log_event_data", 0},
9858   { &key_file_log_event_info, "log_event_info", 0},
9859   { &key_file_master_info, "master_info", 0},
9860   { &key_file_misc, "misc", 0},
9861   { &key_file_partition_ddl_log, "partition_ddl_log", 0},
9862   { &key_file_pid, "pid", 0},
9863   { &key_file_general_log, "query_log", 0},
9864   { &key_file_relay_log_info, "relay_log_info", 0},
9865   { &key_file_send_file, "send_file", 0},
9866   { &key_file_slow_log, "slow_log", 0},
9867   { &key_file_tclog, "tclog", 0},
9868   { &key_file_trg, "trigger_name", 0},
9869   { &key_file_trn, "trigger", 0},
9870   { &key_file_init, "init", 0}
9871 };
9872 #endif /* HAVE_PSI_INTERFACE */
9873 
9874 PSI_stage_info stage_after_create= { 0, "After create", 0};
9875 PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
9876 PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
9877 PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
9878 PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0};
9879 PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
9880 PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
9881 PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0};
9882 PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "checking privileges on cached query", 0};
9883 PSI_stage_info stage_checking_query_cache_for_query= { 0, "checking query cache for query", 0};
9884 PSI_stage_info stage_cleaning_up= { 0, "cleaning up", 0};
9885 PSI_stage_info stage_closing_tables= { 0, "closing tables", 0};
9886 PSI_stage_info stage_compressing_gtid_table= { 0, "Compressing gtid_executed table", 0};
9887 PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0};
9888 PSI_stage_info stage_converting_heap_to_ondisk= { 0, "converting HEAP to ondisk", 0};
9889 PSI_stage_info stage_copying_to_group_table= { 0, "Copying to group table", 0};
9890 PSI_stage_info stage_copying_to_tmp_table= { 0, "Copying to tmp table", 0};
9891 PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", PSI_FLAG_STAGE_PROGRESS};
9892 PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0};
9893 PSI_stage_info stage_creating_table= { 0, "creating table", 0};
9894 PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0};
9895 PSI_stage_info stage_deleting_from_main_table= { 0, "deleting from main table", 0};
9896 PSI_stage_info stage_deleting_from_reference_tables= { 0, "deleting from reference tables", 0};
9897 PSI_stage_info stage_discard_or_import_tablespace= { 0, "discard_or_import_tablespace", 0};
9898 PSI_stage_info stage_end= { 0, "end", 0};
9899 PSI_stage_info stage_executing= { 0, "executing", 0};
9900 PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0};
9901 PSI_stage_info stage_explaining= { 0, "explaining", 0};
9902 PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0};
9903 PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0};
9904 PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0};
9905 PSI_stage_info stage_freeing_items= { 0, "freeing items", 0};
9906 PSI_stage_info stage_fulltext_initialization= { 0, "FULLTEXT initialization", 0};
9907 PSI_stage_info stage_got_handler_lock= { 0, "got handler lock", 0};
9908 PSI_stage_info stage_got_old_table= { 0, "got old table", 0};
9909 PSI_stage_info stage_init= { 0, "init", 0};
9910 PSI_stage_info stage_insert= { 0, "insert", 0};
9911 PSI_stage_info stage_invalidating_query_cache_entries_table= { 0, "invalidating query cache entries (table)", 0};
9912 PSI_stage_info stage_invalidating_query_cache_entries_table_list= { 0, "invalidating query cache entries (table list)", 0};
9913 PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0};
9914 PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0};
9915 PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE", 0};
9916 PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE", 0};
9917 PSI_stage_info stage_manage_keys= { 0, "manage keys", 0};
9918 PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for more updates", 0};
9919 PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0};
9920 PSI_stage_info stage_optimizing= { 0, "optimizing", 0};
9921 PSI_stage_info stage_preparing= { 0, "preparing", 0};
9922 PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0};
9923 PSI_stage_info stage_query_end= { 0, "query end", 0};
9924 PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0};
9925 PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0};
9926 PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0};
9927 PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0};
9928 PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0};
9929 PSI_stage_info stage_rename= { 0, "rename", 0};
9930 PSI_stage_info stage_rename_result_table= { 0, "rename result table", 0};
9931 PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0};
9932 PSI_stage_info stage_reschedule= { 0, "reschedule", 0};
9933 PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0};
9934 PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0};
9935 PSI_stage_info stage_sending_cached_result_to_client= { 0, "sending cached result to client", 0};
9936 PSI_stage_info stage_sending_data= { 0, "Sending data", 0};
9937 PSI_stage_info stage_setup= { 0, "setup", 0};
9938 PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for more updates", 0};
9939 PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0};
9940 PSI_stage_info stage_slave_waiting_for_workers_to_process_queue= { 0, "Waiting for slave workers to process their queues", 0};
9941 PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0};
9942 PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0};
9943 PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0};
9944 PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0};
9945 PSI_stage_info stage_sorting_for_group= { 0, "Sorting for group", 0};
9946 PSI_stage_info stage_sorting_for_order= { 0, "Sorting for order", 0};
9947 PSI_stage_info stage_sorting_result= { 0, "Sorting result", 0};
9948 PSI_stage_info stage_statistics= { 0, "statistics", 0};
9949 PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0 };
9950 PSI_stage_info stage_storing_result_in_query_cache= { 0, "storing result in query cache", 0};
9951 PSI_stage_info stage_storing_row_into_queue= { 0, "storing row into queue", 0};
9952 PSI_stage_info stage_system_lock= { 0, "System lock", 0};
9953 PSI_stage_info stage_update= { 0, "update", 0};
9954 PSI_stage_info stage_updating= { 0, "updating", 0};
9955 PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0};
9956 PSI_stage_info stage_updating_reference_tables= { 0, "updating reference tables", 0};
9957 PSI_stage_info stage_upgrading_lock= { 0, "upgrading lock", 0};
9958 PSI_stage_info stage_user_sleep= { 0, "User sleep", 0};
9959 PSI_stage_info stage_verifying_table= { 0, "verifying table", 0};
9960 PSI_stage_info stage_waiting_for_gtid_to_be_committed= { 0, "Waiting for GTID to be committed", 0};
9961 PSI_stage_info stage_waiting_for_handler_insert= { 0, "waiting for handler insert", 0};
9962 PSI_stage_info stage_waiting_for_handler_lock= { 0, "waiting for handler lock", 0};
9963 PSI_stage_info stage_waiting_for_handler_open= { 0, "waiting for handler open", 0};
9964 PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0};
9965 PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0};
9966 PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0};
9967 PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0};
9968 PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0};
9969 PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0};
9970 PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0};
9971 PSI_stage_info stage_waiting_for_query_cache_lock= { 0, "Waiting for query cache lock", 0};
9972 PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0};
9973 PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0};
9974 PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0};
9975 PSI_stage_info stage_worker_waiting_for_its_turn_to_commit= { 0, "Waiting for preceding transaction to commit", 0};
9976 PSI_stage_info stage_worker_waiting_for_commit_parent= { 0, "Waiting for dependent transaction to commit", 0};
9977 PSI_stage_info stage_suspending= { 0, "Suspending", 0};
9978 PSI_stage_info stage_starting= { 0, "starting", 0};
9979 PSI_stage_info stage_waiting_for_no_channel_reference= { 0, "Waiting for no channel reference.", 0};
9980 
9981 #ifdef HAVE_PSI_INTERFACE
9982 
9983 PSI_stage_info *all_server_stages[]=
9984 {
9985   & stage_after_create,
9986   & stage_allocating_local_table,
9987   & stage_alter_inplace_prepare,
9988   & stage_alter_inplace,
9989   & stage_alter_inplace_commit,
9990   & stage_changing_master,
9991   & stage_checking_master_version,
9992   & stage_checking_permissions,
9993   & stage_checking_privileges_on_cached_query,
9994   & stage_checking_query_cache_for_query,
9995   & stage_cleaning_up,
9996   & stage_closing_tables,
9997   & stage_compressing_gtid_table,
9998   & stage_connecting_to_master,
9999   & stage_converting_heap_to_ondisk,
10000   & stage_copying_to_group_table,
10001   & stage_copying_to_tmp_table,
10002   & stage_copy_to_tmp_table,
10003   & stage_creating_sort_index,
10004   & stage_creating_table,
10005   & stage_creating_tmp_table,
10006   & stage_deleting_from_main_table,
10007   & stage_deleting_from_reference_tables,
10008   & stage_discard_or_import_tablespace,
10009   & stage_end,
10010   & stage_executing,
10011   & stage_execution_of_init_command,
10012   & stage_explaining,
10013   & stage_finished_reading_one_binlog_switching_to_next_binlog,
10014   & stage_flushing_relay_log_and_master_info_repository,
10015   & stage_flushing_relay_log_info_file,
10016   & stage_freeing_items,
10017   & stage_fulltext_initialization,
10018   & stage_got_handler_lock,
10019   & stage_got_old_table,
10020   & stage_init,
10021   & stage_insert,
10022   & stage_invalidating_query_cache_entries_table,
10023   & stage_invalidating_query_cache_entries_table_list,
10024   & stage_killing_slave,
10025   & stage_logging_slow_query,
10026   & stage_making_temp_file_append_before_load_data,
10027   & stage_making_temp_file_create_before_load_data,
10028   & stage_manage_keys,
10029   & stage_master_has_sent_all_binlog_to_slave,
10030   & stage_opening_tables,
10031   & stage_optimizing,
10032   & stage_preparing,
10033   & stage_purging_old_relay_logs,
10034   & stage_query_end,
10035   & stage_queueing_master_event_to_the_relay_log,
10036   & stage_reading_event_from_the_relay_log,
10037   & stage_registering_slave_on_master,
10038   & stage_removing_duplicates,
10039   & stage_removing_tmp_table,
10040   & stage_rename,
10041   & stage_rename_result_table,
10042   & stage_requesting_binlog_dump,
10043   & stage_reschedule,
10044   & stage_searching_rows_for_update,
10045   & stage_sending_binlog_event_to_slave,
10046   & stage_sending_cached_result_to_client,
10047   & stage_sending_data,
10048   & stage_setup,
10049   & stage_slave_has_read_all_relay_log,
10050   & stage_slave_waiting_event_from_coordinator,
10051   & stage_slave_waiting_for_workers_to_process_queue,
10052   & stage_slave_waiting_worker_queue,
10053   & stage_slave_waiting_worker_to_free_events,
10054   & stage_slave_waiting_worker_to_release_partition,
10055   & stage_slave_waiting_workers_to_exit,
10056   & stage_sorting_for_group,
10057   & stage_sorting_for_order,
10058   & stage_sorting_result,
10059   & stage_sql_thd_waiting_until_delay,
10060   & stage_statistics,
10061   & stage_storing_result_in_query_cache,
10062   & stage_storing_row_into_queue,
10063   & stage_system_lock,
10064   & stage_update,
10065   & stage_updating,
10066   & stage_updating_main_table,
10067   & stage_updating_reference_tables,
10068   & stage_upgrading_lock,
10069   & stage_user_sleep,
10070   & stage_verifying_table,
10071   & stage_waiting_for_gtid_to_be_committed,
10072   & stage_waiting_for_handler_insert,
10073   & stage_waiting_for_handler_lock,
10074   & stage_waiting_for_handler_open,
10075   & stage_waiting_for_insert,
10076   & stage_waiting_for_master_to_send_event,
10077   & stage_waiting_for_master_update,
10078   & stage_waiting_for_relay_log_space,
10079   & stage_waiting_for_slave_mutex_on_exit,
10080   & stage_waiting_for_slave_thread_to_start,
10081   & stage_waiting_for_table_flush,
10082   & stage_waiting_for_query_cache_lock,
10083   & stage_waiting_for_the_next_event_in_relay_log,
10084   & stage_waiting_for_the_slave_thread_to_advance_position,
10085   & stage_waiting_to_finalize_termination,
10086   & stage_worker_waiting_for_its_turn_to_commit,
10087   & stage_worker_waiting_for_commit_parent,
10088   & stage_suspending,
10089   & stage_starting,
10090   & stage_waiting_for_no_channel_reference
10091 };
10092 
10093 PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;
10094 
10095 static PSI_socket_info all_server_sockets[]=
10096 {
10097   { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_GLOBAL},
10098   { &key_socket_unix, "server_unix_socket", PSI_FLAG_GLOBAL},
10099   { &key_socket_client_connection, "client_connection", 0}
10100 };
10101 #endif /* HAVE_PSI_INTERFACE */
10102 
10103 PSI_memory_key key_memory_locked_table_list;
10104 PSI_memory_key key_memory_locked_thread_list;
10105 PSI_memory_key key_memory_thd_transactions;
10106 PSI_memory_key key_memory_delegate;
10107 PSI_memory_key key_memory_acl_mem;
10108 PSI_memory_key key_memory_acl_memex;
10109 PSI_memory_key key_memory_acl_cache;
10110 PSI_memory_key key_memory_thd_main_mem_root;
10111 PSI_memory_key key_memory_help;
10112 PSI_memory_key key_memory_new_frm_mem;
10113 PSI_memory_key key_memory_table_share;
10114 PSI_memory_key key_memory_gdl;
10115 PSI_memory_key key_memory_table_triggers_list;
10116 PSI_memory_key key_memory_servers;
10117 PSI_memory_key key_memory_prepared_statement_map;
10118 PSI_memory_key key_memory_prepared_statement_main_mem_root;
10119 PSI_memory_key key_memory_protocol_rset_root;
10120 PSI_memory_key key_memory_warning_info_warn_root;
10121 PSI_memory_key key_memory_sp_cache;
10122 PSI_memory_key key_memory_sp_head_main_root;
10123 PSI_memory_key key_memory_sp_head_execute_root;
10124 PSI_memory_key key_memory_sp_head_call_root;
10125 PSI_memory_key key_memory_table_mapping_root;
10126 PSI_memory_key key_memory_quick_range_select_root;
10127 PSI_memory_key key_memory_quick_index_merge_root;
10128 PSI_memory_key key_memory_quick_ror_intersect_select_root;
10129 PSI_memory_key key_memory_quick_ror_union_select_root;
10130 PSI_memory_key key_memory_quick_group_min_max_select_root;
10131 PSI_memory_key key_memory_test_quick_select_exec;
10132 PSI_memory_key key_memory_prune_partitions_exec;
10133 PSI_memory_key key_memory_binlog_recover_exec;
10134 PSI_memory_key key_memory_blob_mem_storage;
10135 PSI_memory_key key_memory_NAMED_ILINK_name;
10136 PSI_memory_key key_memory_Sys_var_charptr_value;
10137 PSI_memory_key key_memory_queue_item;
10138 PSI_memory_key key_memory_THD_db;
10139 PSI_memory_key key_memory_user_var_entry;
10140 PSI_memory_key key_memory_Slave_job_group_group_relay_log_name;
10141 PSI_memory_key key_memory_Relay_log_info_group_relay_log_name;
10142 PSI_memory_key key_memory_binlog_cache_mngr;
10143 PSI_memory_key key_memory_Row_data_memory_memory;
10144 PSI_memory_key key_memory_Gtid_state_to_string;
10145 PSI_memory_key key_memory_Owned_gtids_to_string;
10146 PSI_memory_key key_memory_Sort_param_tmp_buffer;
10147 PSI_memory_key key_memory_Filesort_info_merge;
10148 PSI_memory_key key_memory_Filesort_info_record_pointers;
10149 PSI_memory_key key_memory_handler_errmsgs;
10150 PSI_memory_key key_memory_handlerton;
10151 PSI_memory_key key_memory_XID;
10152 PSI_memory_key key_memory_host_cache_hostname;
10153 PSI_memory_key key_memory_user_var_entry_value;
10154 PSI_memory_key key_memory_User_level_lock;
10155 PSI_memory_key key_memory_MYSQL_LOG_name;
10156 PSI_memory_key key_memory_TC_LOG_MMAP_pages;
10157 PSI_memory_key key_memory_my_bitmap_map;
10158 PSI_memory_key key_memory_QUICK_RANGE_SELECT_mrr_buf_desc;
10159 PSI_memory_key key_memory_Event_queue_element_for_exec_names;
10160 PSI_memory_key key_memory_my_str_malloc;
10161 PSI_memory_key key_memory_MYSQL_BIN_LOG_basename;
10162 PSI_memory_key key_memory_MYSQL_BIN_LOG_index;
10163 PSI_memory_key key_memory_MYSQL_RELAY_LOG_basename;
10164 PSI_memory_key key_memory_MYSQL_RELAY_LOG_index;
10165 PSI_memory_key key_memory_rpl_filter;
10166 PSI_memory_key key_memory_errmsgs;
10167 PSI_memory_key key_memory_Gis_read_stream_err_msg;
10168 PSI_memory_key key_memory_Geometry_objects_data;
10169 PSI_memory_key key_memory_MYSQL_LOCK;
10170 PSI_memory_key key_memory_Event_scheduler_scheduler_param;
10171 PSI_memory_key key_memory_Owned_gtids_sidno_to_hash;
10172 PSI_memory_key key_memory_Mutex_cond_array_Mutex_cond;
10173 PSI_memory_key key_memory_TABLE_RULE_ENT;
10174 PSI_memory_key key_memory_Rpl_info_table;
10175 PSI_memory_key key_memory_Rpl_info_file_buffer;
10176 PSI_memory_key key_memory_db_worker_hash_entry;
10177 PSI_memory_key key_memory_rpl_slave_check_temp_dir;
10178 PSI_memory_key key_memory_rpl_slave_command_buffer;
10179 PSI_memory_key key_memory_binlog_ver_1_event;
10180 PSI_memory_key key_memory_SLAVE_INFO;
10181 PSI_memory_key key_memory_binlog_pos;
10182 PSI_memory_key key_memory_HASH_ROW_ENTRY;
10183 PSI_memory_key key_memory_binlog_statement_buffer;
10184 PSI_memory_key key_memory_partition_syntax_buffer;
10185 PSI_memory_key key_memory_READ_INFO;
10186 PSI_memory_key key_memory_JOIN_CACHE;
10187 PSI_memory_key key_memory_TABLE_sort_io_cache;
10188 PSI_memory_key key_memory_frm;
10189 PSI_memory_key key_memory_Unique_sort_buffer;
10190 PSI_memory_key key_memory_Unique_merge_buffer;
10191 PSI_memory_key key_memory_TABLE;
10192 PSI_memory_key key_memory_frm_extra_segment_buff;
10193 PSI_memory_key key_memory_frm_form_pos;
10194 PSI_memory_key key_memory_frm_string;
10195 PSI_memory_key key_memory_LOG_name;
10196 PSI_memory_key key_memory_DATE_TIME_FORMAT;
10197 PSI_memory_key key_memory_DDL_LOG_MEMORY_ENTRY;
10198 PSI_memory_key key_memory_ST_SCHEMA_TABLE;
10199 PSI_memory_key key_memory_ignored_db;
10200 PSI_memory_key key_memory_PROFILE;
10201 PSI_memory_key key_memory_st_mysql_plugin_dl;
10202 PSI_memory_key key_memory_st_mysql_plugin;
10203 PSI_memory_key key_memory_global_system_variables;
10204 PSI_memory_key key_memory_THD_variables;
10205 PSI_memory_key key_memory_Security_context;
10206 PSI_memory_key key_memory_shared_memory_name;
10207 PSI_memory_key key_memory_bison_stack;
10208 PSI_memory_key key_memory_THD_handler_tables_hash;
10209 PSI_memory_key key_memory_hash_index_key_buffer;
10210 PSI_memory_key key_memory_dboptions_hash;
10211 PSI_memory_key key_memory_user_conn;
10212 PSI_memory_key key_memory_LOG_POS_COORD;
10213 PSI_memory_key key_memory_XID_STATE;
10214 PSI_memory_key key_memory_MPVIO_EXT_auth_info;
10215 PSI_memory_key key_memory_opt_bin_logname;
10216 PSI_memory_key key_memory_Query_cache;
10217 PSI_memory_key key_memory_READ_RECORD_cache;
10218 PSI_memory_key key_memory_Quick_ranges;
10219 PSI_memory_key key_memory_File_query_log_name;
10220 PSI_memory_key key_memory_Table_trigger_dispatcher;
10221 PSI_memory_key key_memory_show_slave_status_io_gtid_set;
10222 PSI_memory_key key_memory_write_set_extraction;
10223 PSI_memory_key key_memory_thd_timer;
10224 PSI_memory_key key_memory_THD_Session_tracker;
10225 PSI_memory_key key_memory_THD_Session_sysvar_resource_manager;
10226 #ifdef WITH_WSREP
10227 PSI_memory_key key_memory_wsrep;
10228 #endif /* WITH_WSREP */
10229 PSI_memory_key key_memory_get_all_tables;
10230 PSI_memory_key key_memory_fill_schema_schemata;
10231 PSI_memory_key key_memory_native_functions;
10232 PSI_memory_key key_memory_JSON;
10233 
10234 #ifdef HAVE_PSI_INTERFACE
10235 static PSI_memory_info all_server_memory[]=
10236 {
10237   { &key_memory_locked_table_list, "Locked_tables_list::m_locked_tables_root", 0},
10238   { &key_memory_locked_thread_list, "display_table_locks", PSI_FLAG_THREAD},
10239   { &key_memory_thd_transactions, "THD::transactions::mem_root", PSI_FLAG_THREAD},
10240   { &key_memory_delegate, "Delegate::memroot", 0},
10241   { &key_memory_acl_mem, "sql_acl_mem", PSI_FLAG_GLOBAL},
10242   { &key_memory_acl_memex, "sql_acl_memex", PSI_FLAG_GLOBAL},
10243   { &key_memory_acl_cache, "acl_cache", PSI_FLAG_GLOBAL},
10244   { &key_memory_thd_main_mem_root, "thd::main_mem_root", PSI_FLAG_THREAD},
10245   { &key_memory_help, "help", 0},
10246   { &key_memory_new_frm_mem, "new_frm_mem", 0},
10247   { &key_memory_table_share, "TABLE_SHARE::mem_root", PSI_FLAG_GLOBAL}, /* table definition cache */
10248   { &key_memory_gdl, "gdl", 0},
10249   { &key_memory_table_triggers_list, "Table_triggers_list", 0},
10250   { &key_memory_servers, "servers", 0},
10251   { &key_memory_prepared_statement_map, "Prepared_statement_map", PSI_FLAG_THREAD},
10252   { &key_memory_prepared_statement_main_mem_root, "Prepared_statement::main_mem_root", PSI_FLAG_THREAD},
10253   { &key_memory_protocol_rset_root, "Protocol_local::m_rset_root", PSI_FLAG_THREAD},
10254   { &key_memory_warning_info_warn_root, "Warning_info::m_warn_root", PSI_FLAG_THREAD},
10255   { &key_memory_sp_cache, "THD::sp_cache", 0},
10256   { &key_memory_sp_head_main_root, "sp_head::main_mem_root", 0},
10257   { &key_memory_sp_head_execute_root, "sp_head::execute_mem_root", PSI_FLAG_THREAD},
10258   { &key_memory_sp_head_call_root, "sp_head::call_mem_root", PSI_FLAG_THREAD},
10259   { &key_memory_table_mapping_root, "table_mapping::m_mem_root", 0},
10260   { &key_memory_quick_range_select_root, "QUICK_RANGE_SELECT::alloc", PSI_FLAG_THREAD},
10261   { &key_memory_quick_index_merge_root, "QUICK_INDEX_MERGE_SELECT::alloc", PSI_FLAG_THREAD},
10262   { &key_memory_quick_ror_intersect_select_root, "QUICK_ROR_INTERSECT_SELECT::alloc", PSI_FLAG_THREAD},
10263   { &key_memory_quick_ror_union_select_root, "QUICK_ROR_UNION_SELECT::alloc", PSI_FLAG_THREAD},
10264   { &key_memory_quick_group_min_max_select_root, "QUICK_GROUP_MIN_MAX_SELECT::alloc", PSI_FLAG_THREAD},
10265   { &key_memory_test_quick_select_exec, "test_quick_select", PSI_FLAG_THREAD},
10266   { &key_memory_prune_partitions_exec, "prune_partitions::exec", 0},
10267   { &key_memory_binlog_recover_exec, "MYSQL_BIN_LOG::recover", 0},
10268   { &key_memory_blob_mem_storage, "Blob_mem_storage::storage", 0},
10269 
10270   { &key_memory_NAMED_ILINK_name, "NAMED_ILINK::name", 0},
10271   { &key_memory_String_value, "String::value", 0},
10272   { &key_memory_Sys_var_charptr_value, "Sys_var_charptr::value", 0},
10273   { &key_memory_queue_item, "Queue::queue_item", 0},
10274   { &key_memory_THD_db, "THD::db", 0},
10275   { &key_memory_user_var_entry, "user_var_entry", 0},
10276   { &key_memory_Slave_job_group_group_relay_log_name, "Slave_job_group::group_relay_log_name", 0},
10277   { &key_memory_Relay_log_info_group_relay_log_name, "Relay_log_info::group_relay_log_name", 0},
10278   { &key_memory_binlog_cache_mngr, "binlog_cache_mngr", 0},
10279   { &key_memory_Row_data_memory_memory, "Row_data_memory::memory", 0},
10280 
10281   { &key_memory_Gtid_set_to_string, "Gtid_set::to_string", 0},
10282   { &key_memory_Gtid_state_to_string, "Gtid_state::to_string", 0},
10283   { &key_memory_Owned_gtids_to_string, "Owned_gtids::to_string", 0},
10284   { &key_memory_log_event, "Log_event", 0},
10285   { &key_memory_Incident_log_event_message, "Incident_log_event::message", 0},
10286   { &key_memory_Rows_query_log_event_rows_query, "Rows_query_log_event::rows_query", 0},
10287 
10288   { &key_memory_Sort_param_tmp_buffer, "Sort_param::tmp_buffer", 0},
10289   { &key_memory_Filesort_info_merge, "Filesort_info::merge", 0},
10290   { &key_memory_Filesort_info_record_pointers, "Filesort_info::record_pointers", 0},
10291   { &key_memory_Filesort_buffer_sort_keys, "Filesort_buffer::sort_keys", 0},
10292   { &key_memory_handler_errmsgs, "handler::errmsgs", 0},
10293   { &key_memory_handlerton, "handlerton", 0},
10294   { &key_memory_XID, "XID", 0},
10295   { &key_memory_host_cache_hostname, "host_cache::hostname", 0},
10296   { &key_memory_user_var_entry_value, "user_var_entry::value", 0},
10297   { &key_memory_User_level_lock, "User_level_lock", 0},
10298   { &key_memory_MYSQL_LOG_name, "MYSQL_LOG::name", 0},
10299   { &key_memory_TC_LOG_MMAP_pages, "TC_LOG_MMAP::pages", 0},
10300   { &key_memory_my_bitmap_map, "my_bitmap_map", 0},
10301   { &key_memory_QUICK_RANGE_SELECT_mrr_buf_desc, "QUICK_RANGE_SELECT::mrr_buf_desc", 0},
10302   { &key_memory_Event_queue_element_for_exec_names, "Event_queue_element_for_exec::names", 0},
10303   { &key_memory_my_str_malloc, "my_str_malloc", 0},
10304   { &key_memory_MYSQL_BIN_LOG_basename, "MYSQL_BIN_LOG::basename", 0},
10305   { &key_memory_MYSQL_BIN_LOG_index, "MYSQL_BIN_LOG::index", 0},
10306   { &key_memory_MYSQL_RELAY_LOG_basename, "MYSQL_RELAY_LOG::basename", 0},
10307   { &key_memory_MYSQL_RELAY_LOG_index, "MYSQL_RELAY_LOG::index", 0},
10308   { &key_memory_rpl_filter, "rpl_filter memory", 0},
10309   { &key_memory_errmsgs, "errmsgs", 0},
10310   { &key_memory_Gis_read_stream_err_msg, "Gis_read_stream::err_msg", 0},
10311   { &key_memory_Geometry_objects_data, "Geometry::ptr_and_wkb_data", 0},
10312   { &key_memory_MYSQL_LOCK, "MYSQL_LOCK", 0},
10313   { &key_memory_NET_buff, "NET::buff", 0},
10314   { &key_memory_NET_compress_packet, "NET::compress_packet", 0},
10315   { &key_memory_Event_scheduler_scheduler_param, "Event_scheduler::scheduler_param", 0},
10316   { &key_memory_Gtid_set_Interval_chunk, "Gtid_set::Interval_chunk", 0},
10317   { &key_memory_Owned_gtids_sidno_to_hash, "Owned_gtids::sidno_to_hash", 0},
10318   { &key_memory_Sid_map_Node, "Sid_map::Node", 0},
10319   { &key_memory_Gtid_state_group_commit_sidno, "Gtid_state::group_commit_sidno_locks", 0},
10320   { &key_memory_Mutex_cond_array_Mutex_cond, "Mutex_cond_array::Mutex_cond", 0},
10321   { &key_memory_TABLE_RULE_ENT, "TABLE_RULE_ENT", 0},
10322 
10323   { &key_memory_Rpl_info_table, "Rpl_info_table", 0},
10324   { &key_memory_Rpl_info_file_buffer, "Rpl_info_file::buffer", 0},
10325   { &key_memory_db_worker_hash_entry, "db_worker_hash_entry", 0},
10326   { &key_memory_rpl_slave_check_temp_dir, "rpl_slave::check_temp_dir", 0},
10327   { &key_memory_rpl_slave_command_buffer, "rpl_slave::command_buffer", 0},
10328   { &key_memory_binlog_ver_1_event, "binlog_ver_1_event", 0},
10329   { &key_memory_SLAVE_INFO, "SLAVE_INFO", 0},
10330   { &key_memory_binlog_pos, "binlog_pos", 0},
10331   { &key_memory_HASH_ROW_ENTRY, "HASH_ROW_ENTRY", 0},
10332   { &key_memory_binlog_statement_buffer, "binlog_statement_buffer", 0},
10333   { &key_memory_partition_syntax_buffer, "partition_syntax_buffer", 0},
10334   { &key_memory_READ_INFO, "READ_INFO", 0},
10335   { &key_memory_JOIN_CACHE, "JOIN_CACHE", 0},
10336   { &key_memory_TABLE_sort_io_cache, "TABLE::sort_io_cache", 0},
10337   { &key_memory_frm, "frm", 0},
10338   { &key_memory_Unique_sort_buffer, "Unique::sort_buffer", 0},
10339   { &key_memory_Unique_merge_buffer, "Unique::merge_buffer", 0},
10340   { &key_memory_TABLE, "TABLE", PSI_FLAG_GLOBAL}, /* Table cache */
10341   { &key_memory_frm_extra_segment_buff, "frm::extra_segment_buff", 0},
10342   { &key_memory_frm_form_pos, "frm::form_pos", 0},
10343   { &key_memory_frm_string, "frm::string", 0},
10344   { &key_memory_LOG_name, "LOG_name", 0},
10345   { &key_memory_DATE_TIME_FORMAT, "DATE_TIME_FORMAT", 0},
10346   { &key_memory_DDL_LOG_MEMORY_ENTRY, "DDL_LOG_MEMORY_ENTRY", 0},
10347   { &key_memory_ST_SCHEMA_TABLE, "ST_SCHEMA_TABLE", 0},
10348   { &key_memory_ignored_db, "ignored_db", 0},
10349   { &key_memory_PROFILE, "PROFILE", 0},
10350   { &key_memory_global_system_variables, "global_system_variables", 0},
10351   { &key_memory_THD_variables, "THD::variables", 0},
10352   { &key_memory_Security_context, "Security_context", 0},
10353   { &key_memory_shared_memory_name, "Shared_memory_name", 0},
10354   { &key_memory_bison_stack, "bison_stack", 0},
10355   { &key_memory_THD_handler_tables_hash, "THD::handler_tables_hash", 0},
10356   { &key_memory_hash_index_key_buffer, "hash_index_key_buffer", 0},
10357   { &key_memory_dboptions_hash, "dboptions_hash", 0},
10358   { &key_memory_user_conn, "user_conn", 0},
10359   { &key_memory_LOG_POS_COORD, "LOG_POS_COORD", 0},
10360   { &key_memory_XID_STATE, "XID_STATE", 0},
10361   { &key_memory_MPVIO_EXT_auth_info, "MPVIO_EXT::auth_info", 0},
10362   { &key_memory_opt_bin_logname, "opt_bin_logname", 0},
10363   { &key_memory_Query_cache, "Query_cache", PSI_FLAG_GLOBAL},
10364   { &key_memory_READ_RECORD_cache, "READ_RECORD_cache", 0},
10365   { &key_memory_Quick_ranges, "Quick_ranges", 0},
10366   { &key_memory_File_query_log_name, "File_query_log::name", 0},
10367   { &key_memory_Table_trigger_dispatcher, "Table_trigger_dispatcher::m_mem_root", 0},
10368   { &key_memory_thd_timer, "thd_timer", 0},
10369   { &key_memory_THD_Session_tracker, "THD::Session_tracker", 0},
10370   { &key_memory_THD_Session_sysvar_resource_manager, "THD::Session_sysvar_resource_manager", 0},
10371   { &key_memory_show_slave_status_io_gtid_set, "show_slave_status_io_gtid_set", 0},
10372 #ifdef WITH_WSREP
10373   { &key_memory_wsrep, "wsrep", 0},
10374 #endif /* WITH_WSREP */
10375   { &key_memory_write_set_extraction, "write_set_extraction", 0},
10376   { &key_memory_get_all_tables, "get_all_tables", 0},
10377   { &key_memory_fill_schema_schemata, "fill_schema_schemata", 0},
10378   { &key_memory_native_functions, "native_functions", PSI_FLAG_GLOBAL},
10379   { &key_memory_JSON, "JSON", 0 },
10380 };
10381 
10382 /* TODO: find a good header */
10383 extern "C" void init_client_psi_keys(void);
10384 
10385 /**
10386   Initialise all the performance schema instrumentation points
10387   used by the server.
10388 */
init_server_psi_keys(void)10389 void init_server_psi_keys(void)
10390 {
10391   const char* category= "sql";
10392   int count;
10393 
10394   count= array_elements(all_server_mutexes);
10395   mysql_mutex_register(category, all_server_mutexes, count);
10396 
10397   count= array_elements(all_server_rwlocks);
10398   mysql_rwlock_register(category, all_server_rwlocks, count);
10399 
10400   count= array_elements(all_server_conds);
10401   mysql_cond_register(category, all_server_conds, count);
10402 
10403   count= array_elements(all_server_threads);
10404   mysql_thread_register(category, all_server_threads, count);
10405 
10406   count= array_elements(all_server_files);
10407   mysql_file_register(category, all_server_files, count);
10408 
10409   count= array_elements(all_server_stages);
10410   mysql_stage_register(category, all_server_stages, count);
10411 
10412   count= array_elements(all_server_sockets);
10413   mysql_socket_register(category, all_server_sockets, count);
10414 
10415   count= array_elements(all_server_memory);
10416   mysql_memory_register(category, all_server_memory, count);
10417 
10418 #ifdef HAVE_PSI_STATEMENT_INTERFACE
10419   init_sql_statement_info();
10420   count= array_elements(sql_statement_info);
10421   mysql_statement_register(category, sql_statement_info, count);
10422 
10423   init_sp_psi_keys();
10424 
10425   init_scheduler_psi_keys();
10426 
10427   category= "com";
10428   init_com_statement_info();
10429 
10430   /*
10431     Register [0 .. COM_QUERY - 1] as "statement/com/..."
10432   */
10433   count= (int) COM_QUERY;
10434   mysql_statement_register(category, com_statement_info, count);
10435 
10436   /*
10437     Register [COM_QUERY + 1 .. COM_END] as "statement/com/..."
10438   */
10439   count= (int) COM_END - (int) COM_QUERY;
10440   mysql_statement_register(category, & com_statement_info[(int) COM_QUERY + 1], count);
10441 
10442   category= "abstract";
10443   /*
10444     Register [COM_QUERY] as "statement/abstract/com_query"
10445   */
10446   mysql_statement_register(category, & com_statement_info[(int) COM_QUERY], 1);
10447 
10448   /*
10449     When a new packet is received,
10450     it is instrumented as "statement/abstract/new_packet".
10451     Based on the packet type found, it later mutates to the
10452     proper narrow type, for example
10453     "statement/abstract/query" or "statement/com/ping".
10454     In cases of "statement/abstract/query", SQL queries are given to
10455     the parser, which mutates the statement type to an even more
10456     narrow classification, for example "statement/sql/select".
10457   */
10458   stmt_info_new_packet.m_key= 0;
10459   stmt_info_new_packet.m_name= "new_packet";
10460   stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE;
10461   mysql_statement_register(category, &stmt_info_new_packet, 1);
10462 
10463   /*
10464     Statements processed from the relay log are initially instrumented as
10465     "statement/abstract/relay_log". The parser will mutate the statement type to
10466     a more specific classification, for example "statement/sql/insert".
10467   */
10468   stmt_info_rpl.m_key= 0;
10469   stmt_info_rpl.m_name= "relay_log";
10470   stmt_info_rpl.m_flags= PSI_FLAG_MUTABLE;
10471   mysql_statement_register(category, &stmt_info_rpl, 1);
10472 #endif
10473 
10474   /* Common client and server code. */
10475   init_client_psi_keys();
10476   /* Vio */
10477   init_vio_psi_keys();
10478 }
10479 
10480 #endif /* HAVE_PSI_INTERFACE */
10481 
10482 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
10483 // update_named_pipe_full_access_group returns false on success, true on failure
update_named_pipe_full_access_group(const char * new_group_name)10484 bool update_named_pipe_full_access_group(const char *new_group_name)
10485 {
10486   if (named_pipe_acceptor) {
10487     return named_pipe_listener->update_named_pipe_full_access_group(
10488       new_group_name);
10489   }
10490   return true;
10491 }
10492 
10493 #endif  /* _WIN32 && !EMBEDDED_LIBRARY */
10494 
10495 
set_mysqld_opt_tracking_mode()10496 void set_mysqld_opt_tracking_mode()
10497 {
10498   my_atomic_store64(&mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode,
10499           static_cast<int64>(mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode_value));
10500 }
10501