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