mysqld.cc 329 KB
Newer Older
1
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
2
   Copyright (c) 2008, 2019, MariaDB Corporation.
3

unknown's avatar
unknown committed
4 5
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
6
   the Free Software Foundation; version 2 of the License.
7

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
12

unknown's avatar
unknown committed
13 14
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
15
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
unknown's avatar
unknown committed
16

17
#include "sql_plugin.h"                         // Includes mariadb.h
18 19 20 21 22 23
#include "sql_priv.h"
#include "unireg.h"
#include <signal.h>
#ifndef __WIN__
#include <netdb.h>        // getservbyname, servent
#endif
24
#include "sql_parse.h"    // path_starts_from_data_home_dir
25 26 27 28 29 30
#include "sql_cache.h"    // query_cache, query_cache_*
#include "sql_locale.h"   // MY_LOCALES, my_locales, my_locale_by_name
#include "sql_show.h"     // free_status_vars, add_status_vars,
                          // reset_status_vars
#include "strfunc.h"      // find_set_from_flags
#include "parse_file.h"   // File_parser_dummy_hook
31 32
#include "sql_db.h"       // my_dboptions_cache_free
                          // my_dboptions_cache_init
33 34 35 36 37 38 39 40 41 42
#include "sql_table.h"    // release_ddl_log, execute_ddl_log_recovery
#include "sql_connect.h"  // free_max_user_conn, init_max_user_conn,
                          // handle_one_connection
#include "sql_time.h"     // known_date_time_formats,
                          // get_date_time_format_str,
                          // date_time_format_make
#include "tztime.h"       // my_tz_free, my_tz_init, my_tz_SYSTEM
#include "hostname.h"     // hostname_cache_free, hostname_cache_init
#include "sql_acl.h"      // acl_free, grant_free, acl_init,
                          // grant_init
43
#include "sql_base.h"
44 45 46 47 48 49 50
#include "sql_test.h"     // mysql_print_status
#include "item_create.h"  // item_create_cleanup, item_create_init
#include "sql_servers.h"  // servers_free, servers_init
#include "init.h"         // unireg_init
#include "derror.h"       // init_errmessage
#include "des_key_file.h" // load_des_key_file
#include "sql_manager.h"  // stop_handle_manager, start_handle_manager
51
#include "sql_expression_cache.h" // subquery_cache_miss, subquery_cache_hit
52
#include "sys_vars_shared.h"
Sergei Golubchik's avatar
Sergei Golubchik committed
53

unknown's avatar
unknown committed
54
#include <m_ctype.h>
55
#include <my_dir.h>
56
#include <my_bit.h>
57
#include "slave.h"
58
#include "rpl_mi.h"
59
#include "sql_repl.h"
unknown's avatar
unknown committed
60
#include "rpl_filter.h"
61
#include "client_settings.h"
62
#include "repl_failsafe.h"
63
#include <sql_common.h>
64
#include <my_stacktrace.h>
65
#include "mysqld_suffix.h"
unknown's avatar
Merge  
unknown committed
66
#include "mysys_err.h"
67
#include "events.h"
68
#include "sql_audit.h"
69
#include "probes_mysql.h"
70
#include "scheduler.h"
71
#include <waiting_threads.h>
72
#include "debug_sync.h"
73 74
#include "wsrep_mysqld.h"
#include "wsrep_var.h"
Brave Galera Crew's avatar
Brave Galera Crew committed
75
#ifdef WITH_WSREP
76 77
#include "wsrep_thd.h"
#include "wsrep_sst.h"
Brave Galera Crew's avatar
Brave Galera Crew committed
78
#endif /* WITH_WSREP */
79
#include "proxy_protocol.h"
80

81
#include "sql_callback.h"
82
#include "threadpool.h"
83

Sergei Golubchik's avatar
Sergei Golubchik committed
84 85 86 87
#ifdef HAVE_OPENSSL
#include <ssl_compat.h>
#endif

Marc Alff's avatar
Marc Alff committed
88 89 90
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
#include "../storage/perfschema/pfs_server.h"
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
91 92 93 94
#include <mysql/psi/mysql_idle.h>
#include <mysql/psi/mysql_socket.h>
#include <mysql/psi/mysql_statement.h>
#include "mysql_com_server.h"
Marc Alff's avatar
Marc Alff committed
95

96
#include "keycaches.h"
97
#include "../storage/myisam/ha_myisam.h"
98
#include "set_var.h"
99

100
#include "rpl_injector.h"
101 102
#include "semisync_master.h"
#include "semisync_slave.h"
He Zhenxing's avatar
He Zhenxing committed
103

104 105
#include "transaction.h"

106 107
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
108 109
#endif

unknown's avatar
unknown committed
110 111
#include <thr_alarm.h>
#include <ft_global.h>
112
#include <errmsg.h>
unknown's avatar
Merge  
unknown committed
113 114
#include "sp_rcontext.h"
#include "sp_cache.h"
115
#include "sql_reload.h"  // reload_acl_and_cache
116
#include "pcre.h"
unknown's avatar
unknown committed
117

118 119
#ifdef HAVE_POLL_H
#include <poll.h>
120 121
#endif

122 123 124 125
#ifdef _WIN32
#include <handle_connections_win.h>
#endif

126
#include <my_service_manager.h>
127

unknown's avatar
unknown committed
128
#define mysqld_charset &my_charset_latin1
129

130
/* We have HAVE_valgrind below as this speeds up the shutdown of MySQL */
131

132
#if defined(HAVE_valgrind) && defined(__linux__)
unknown's avatar
unknown committed
133
#define HAVE_CLOSE_SERVER_SOCK 1
134
#endif
unknown's avatar
unknown committed
135

unknown's avatar
unknown committed
136 137 138
extern "C" {					// Because of SCO 3.2V4.2
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
139
#define __GNU_LIBRARY__				// Skip warnings in getopt.h
unknown's avatar
unknown committed
140
#endif
141
#include <my_getopt.h>
unknown's avatar
unknown committed
142 143 144 145
#ifdef HAVE_SYSENT_H
#include <sysent.h>
#endif
#ifdef HAVE_PWD_H
146
#include <pwd.h>				// For struct passwd
unknown's avatar
unknown committed
147
#endif
unknown's avatar
Merge  
unknown committed
148
#include <my_net.h>
unknown's avatar
unknown committed
149

150
#if !defined(__WIN__)
unknown's avatar
unknown committed
151 152
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
153
#include <sys/un.h>
unknown's avatar
unknown committed
154 155
#endif
#ifdef HAVE_SELECT_H
156
#include <select.h>
unknown's avatar
unknown committed
157 158 159 160 161
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/utsname.h>
unknown's avatar
unknown committed
162
#endif /* __WIN__ */
unknown's avatar
unknown committed
163

164
#include <my_libwrap.h>
unknown's avatar
unknown committed
165

166 167 168 169
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

170 171 172 173
#ifdef __WIN__ 
#include <crtdbg.h>
#endif

174 175 176 177 178 179 180 181 182 183
#ifdef HAVE_SOLARIS_LARGE_PAGES
#include <sys/mman.h>
#if defined(__sun__) && defined(__GNUC__) && defined(__cplusplus) \
    && defined(_XOPEN_SOURCE)
extern int getpagesizes(size_t *, int);
extern int getpagesizes2(size_t *, int);
extern int memcntl(caddr_t, size_t, int, caddr_t, int, int);
#endif /* __sun__ ... */
#endif /* HAVE_SOLARIS_LARGE_PAGES */

unknown's avatar
unknown committed
184
#ifdef _AIX41
unknown's avatar
unknown committed
185
int initgroups(const char *,unsigned int);
unknown's avatar
unknown committed
186 187
#endif

188
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
unknown's avatar
unknown committed
189 190 191 192
#include <ieeefp.h>
#ifdef HAVE_FP_EXCEPT				// Fix type conflict
typedef fp_except fp_except_t;
#endif
193
#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
194 195 196 197
#ifdef HAVE_SYS_FPU_H
/* for IRIX to use set_fpc_csr() */
#include <sys/fpu.h>
#endif
198 199 200
#ifdef HAVE_FPU_CONTROL_H
#include <fpu_control.h>
#endif
201 202 203 204
#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
# define fpu_control_t unsigned int
# define _FPU_EXTENDED 0x300
# define _FPU_DOUBLE 0x200
205
# if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
206 207
#  define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
#  define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
208 209 210 211 212
# else
#  define _FPU_GETCW(cw) (cw= 0)
#  define _FPU_SETCW(cw)
# endif
#endif
unknown's avatar
unknown committed
213

Sergei Golubchik's avatar
Sergei Golubchik committed
214 215 216 217
#ifndef HAVE_FCNTL
#define fcntl(X,Y,Z) 0
#endif

218 219 220
extern "C" my_bool reopen_fstreams(const char *filename,
                                   FILE *outstream, FILE *errstream);

221
inline void setup_fpu()
unknown's avatar
unknown committed
222
{
223
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
unknown's avatar
unknown committed
224
  /* We can't handle floating point exceptions with threads, so disable
unknown's avatar
unknown committed
225
     this on freebsd
226 227
     Don't fall for overflow, underflow,divide-by-zero or loss of precision.
     fpsetmask() is deprecated in favor of fedisableexcept() in C99.
unknown's avatar
unknown committed
228
  */
229
#if defined(FP_X_DNML)
unknown's avatar
unknown committed
230 231
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
	      FP_X_IMP));
unknown's avatar
unknown committed
232
#else
233 234
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
235 236 237 238 239 240
#endif /* FP_X_DNML */
#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */

#ifdef HAVE_FEDISABLEEXCEPT
  fedisableexcept(FE_ALL_EXCEPT);
#endif
241

242 243 244 245
#ifdef HAVE_FESETROUND
    /* Set FPU rounding mode to "round-to-nearest" */
  fesetround(FE_TONEAREST);
#endif /* HAVE_FESETROUND */
246 247

  /*
248 249 250 251
    x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
    (double precision) for portable results of floating point operations.
    However, there is no need to do so if compiler is using SSE2 for floating
    point, double values will be stored and processed in 64 bits anyway.
252
  */
253
#if defined(__i386__) && !defined(__SSE2_MATH__)
254 255 256 257 258 259 260 261 262 263 264 265
#if defined(_WIN32)
#if !defined(_WIN64)
  _control87(_PC_53, MCW_PC);
#endif /* !_WIN64 */
#else /* !_WIN32 */
  fpu_control_t cw;
  _FPU_GETCW(cw);
  cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
  _FPU_SETCW(cw);
#endif /* _WIN32 && */
#endif /* __i386__ */

266
#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
267
  /* Enable denormalized DOUBLE values support for IRIX */
268 269 270 271 272
  union fpc_csr n;
  n.fc_word = get_fpc_csr();
  n.fc_struct.flush = 0;
  set_fpc_csr(n.fc_word);
#endif
273
}
unknown's avatar
unknown committed
274

unknown's avatar
unknown committed
275 276
} /* cplusplus */

unknown's avatar
unknown committed
277
#define MYSQL_KILL_SIGNAL SIGTERM
unknown's avatar
unknown committed
278 279 280 281 282 283 284

#include <my_pthread.h>			// For thr_setconcurency()

#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif

285
extern "C" sig_handler handle_fatal_signal(int sig);
286

287 288 289
#if defined(__linux__)
#define ENABLE_TEMP_POOL 1
#else
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
290
#define ENABLE_TEMP_POOL 0
291 292
#endif

293 294
int init_io_cache_encryption();

unknown's avatar
unknown committed
295
/* Constants */
296

297 298
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE

unknown's avatar
unknown committed
299
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
300

unknown's avatar
unknown committed
301 302
static const char *tc_heuristic_recover_names[]=
{
303
  "OFF", "COMMIT", "ROLLBACK", NullS
unknown's avatar
unknown committed
304 305 306 307 308 309
};
static TYPELIB tc_heuristic_recover_typelib=
{
  array_elements(tc_heuristic_recover_names)-1,"",
  tc_heuristic_recover_names, NULL
};
unknown's avatar
unknown committed
310

311
const char *first_keyword= "first";
unknown's avatar
unknown committed
312
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
313

unknown's avatar
unknown committed
314
bool opt_large_files= sizeof(my_off_t) > 4;
315
static my_bool opt_autocommit; ///< for --autocommit command-line option
316 317 318 319

/*
  Used with --help for detailed option
*/
320
static my_bool opt_verbose= 0;
321

322 323 324
/* Timer info to be used by the SQL layer */
MY_TIMER_INFO sys_timer_info;

unknown's avatar
unknown committed
325 326
/* static variables */

Marc Alff's avatar
Marc Alff committed
327
#ifdef HAVE_PSI_INTERFACE
328
#ifdef HAVE_OPENSSL10
329 330
static PSI_rwlock_key key_rwlock_openssl;
#endif
Marc Alff's avatar
Marc Alff committed
331 332
#endif /* HAVE_PSI_INTERFACE */

333 334 335 336
#ifdef HAVE_NPTL
volatile sig_atomic_t ld_assume_kernel_is_set= 0;
#endif

Sergei Golubchik's avatar
Sergei Golubchik committed
337 338 339 340 341 342 343
/**
  Statement instrumentation key for replication.
*/
#ifdef HAVE_PSI_STATEMENT_INTERFACE
PSI_statement_info stmt_info_rpl;
#endif

344
/* the default log output is log tables */
unknown's avatar
unknown committed
345
static bool lower_case_table_names_used= 0;
346
static bool max_long_data_size_used= false;
unknown's avatar
unknown committed
347 348
static bool volatile select_thread_in_use, signal_thread_in_use;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
349
static my_bool opt_short_log_format= 0, opt_silent_startup= 0;
350
bool my_disable_leak_check= false;
351

352 353
uint kill_cached_threads;
static uint wake_thread;
Michael Widenius's avatar
Michael Widenius committed
354
ulong max_used_connections;
Monty's avatar
Monty committed
355
volatile ulong cached_thread_count= 0;
356
static char *mysqld_user, *mysqld_chroot;
unknown's avatar
unknown committed
357
static char *default_character_set_name;
unknown's avatar
unknown committed
358
static char *character_set_filesystem_name;
359
static char *lc_messages;
360
static char *lc_time_names_name;
361
char *my_bind_addr_str;
362
int server_socket_ai_family;
363
static char *default_collation_name;
364
char *default_storage_engine, *default_tmp_storage_engine;
365
char *enforced_storage_engine=NULL;
366 367
char *gtid_pos_auto_engines;
plugin_ref *opt_gtid_pos_auto_plugins;
368
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
369
static I_List<CONNECT> thread_cache;
370 371
static bool binlog_format_used= false;
LEX_STRING opt_init_connect, opt_init_slave;
372 373
mysql_cond_t COND_thread_cache;
static mysql_cond_t COND_flush_thread_cache;
374
mysql_cond_t COND_slave_background;
375
static DYNAMIC_ARRAY all_options;
376
static longlong start_memory_used;
unknown's avatar
unknown committed
377

unknown's avatar
unknown committed
378
/* Global variables */
unknown's avatar
unknown committed
379

380
bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0;
vinchen's avatar
vinchen committed
381 382
bool opt_bin_log_compress;
uint opt_bin_log_compress_min_len;
383
my_bool opt_log, debug_assert_if_crashed_table= 0, opt_help= 0;
384
my_bool debug_assert_on_not_freed_memory= 0;
Monty's avatar
Monty committed
385
my_bool disable_log_notes, opt_support_flashback= 0;
386
static my_bool opt_abort;
387
ulonglong log_output_options;
Sergei Golubchik's avatar
Sergei Golubchik committed
388
my_bool opt_userstat_running;
389
bool opt_error_log= IF_WIN(1,0);
unknown's avatar
unknown committed
390
bool opt_disable_networking=0, opt_skip_show_db=0;
391
bool opt_skip_name_resolve=0;
392
my_bool opt_character_set_client_handshake= 1;
393
bool opt_endinfo, using_udf_functions;
394
my_bool locked_in_memory;
395
bool opt_using_transactions;
unknown's avatar
unknown committed
396
bool volatile abort_loop;
Sergei Golubchik's avatar
Sergei Golubchik committed
397
uint volatile global_disable_checkpoint;
398 399 400
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
ulong slow_start_timeout;
#endif
401 402 403 404
/**
   @brief 'grant_option' is used to indicate if privileges needs
   to be checked, in which case the lock, LOCK_grant, is used
   to protect access to the grant table.
405
   @note This flag is dropped in 5.1
406 407 408
   @see grant_init()
 */
bool volatile grant_option;
unknown's avatar
unknown committed
409

unknown's avatar
unknown committed
410
my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
unknown's avatar
unknown committed
411
my_bool opt_reckless_slave = 0;
unknown's avatar
unknown committed
412 413
my_bool opt_enable_named_pipe= 0;
my_bool opt_local_infile, opt_slave_compressed_protocol;
414 415
my_bool opt_safe_user_create = 0;
my_bool opt_show_slave_auth_info;
416
my_bool opt_log_slave_updates= 0;
417
my_bool opt_replicate_annotate_row_events= 0;
418
my_bool opt_mysql56_temporal_format=0, strict_password_validation= 1;
419
my_bool opt_explicit_defaults_for_timestamp= 0;
420
char *opt_slave_skip_errors;
421
char *opt_slave_transaction_retry_errors;
422

423 424 425 426 427
/*
  Legacy global handlerton. These will be removed (please do not add more).
*/
handlerton *heap_hton;
handlerton *myisam_hton;
428
handlerton *partition_hton;
429

430 431
my_bool read_only= 0, opt_readonly= 0;
my_bool use_temp_pool, relay_log_purge;
432
my_bool relay_log_recovery;
unknown's avatar
unknown committed
433
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
434
my_bool opt_secure_auth= 0;
435
char* opt_secure_file_priv;
unknown's avatar
unknown committed
436
my_bool lower_case_file_system= 0;
437
my_bool opt_large_pages= 0;
438
my_bool opt_super_large_pages= 0;
unknown's avatar
unknown committed
439
my_bool opt_myisam_use_mmap= 0;
440
uint   opt_large_page_size= 0;
441
#if defined(ENABLED_DEBUG_SYNC)
442
MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
443
#endif /* defined(ENABLED_DEBUG_SYNC) */
444
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
445
ulong opt_replicate_events_marked_for_skip;
446

unknown's avatar
Merge  
unknown committed
447 448 449 450 451
/*
  True if there is at least one per-hour limit for some user, so we should
  check them before each query (and possibly reset counters when hour is
  changed). False otherwise.
*/
unknown's avatar
unknown committed
452
volatile bool mqh_used = 0;
453
my_bool opt_noacl;
unknown's avatar
Merge  
unknown committed
454
my_bool sp_automatic_privileges= 1;
455

456
ulong opt_binlog_rows_event_max_size;
457 458
my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1;
unknown's avatar
unknown committed
459
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
460
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
461
uint mysqld_port, select_errors, dropping_tables, ha_open_options;
462
uint mysqld_extra_port;
463
uint mysqld_port_timeout;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
464
ulong delay_key_write_options;
465
uint protocol_version;
unknown's avatar
unknown committed
466
uint lower_case_table_names;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
467
ulong tc_heuristic_recover= 0;
468
Atomic_counter<uint32_t> thread_count;
Michael Widenius's avatar
Michael Widenius committed
469
int32 slave_open_temp_tables;
470
ulong thread_created;
471
ulong back_log, connect_timeout, concurrency, server_id;
472
ulong what_to_log;
Michael Widenius's avatar
Michael Widenius committed
473
ulong slow_launch_time;
474
ulong open_files_limit, max_binlog_size;
475
ulong slave_trans_retries;
476
ulong slave_trans_retry_interval;
477
uint  slave_net_timeout;
478
ulong slave_exec_mode_options;
479
ulong slave_run_triggers_for_rbr= 0;
480
ulong slave_ddl_exec_mode_options= SLAVE_EXEC_MODE_IDEMPOTENT;
unknown's avatar
unknown committed
481
ulonglong slave_type_conversions_options;
482
ulong thread_cache_size=0;
483
ulonglong binlog_cache_size=0;
484
ulonglong binlog_file_cache_size=0;
485
ulonglong max_binlog_cache_size=0;
486
ulong slave_max_allowed_packet= 0;
487 488
ulonglong binlog_stmt_cache_size=0;
ulonglong  max_binlog_stmt_cache_size=0;
489
ulonglong test_flags;
490
ulonglong query_cache_size=0;
491
ulong query_cache_limit=0;
492
ulong executed_events=0;
493
query_id_t global_query_id;
unknown's avatar
unknown committed
494
ulong aborted_threads, aborted_connects;
unknown's avatar
unknown committed
495 496
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
unknown's avatar
unknown committed
497
ulong delayed_insert_errors,flush_time;
unknown's avatar
Merge  
unknown committed
498
ulong specialflag=0;
499
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
500
ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
unknown's avatar
unknown committed
501
ulong max_connections, max_connect_errors;
502
uint max_password_errors;
503
ulong extra_max_connections;
504
uint max_digest_length= 0;
505
ulong slave_retried_transactions;
506 507 508
ulong transactions_multi_engine;
ulong rpl_transactions_multi_engine;
ulong transactions_gtid_foreign_engine;
509
ulonglong slave_skipped_errors;
510
ulong feature_files_opened_with_delayed_keys= 0, feature_check_constraint= 0;
511
ulonglong denied_connections;
Sergei Golubchik's avatar
Sergei Golubchik committed
512
my_decimal decimal_zero;
513
long opt_secure_timestamp;
514
uint default_password_lifetime;
515
my_bool disconnect_on_expired_password;
Sergei Golubchik's avatar
Sergei Golubchik committed
516

517 518 519 520 521
/*
  Maximum length of parameter value which can be set through
  mysql_send_long_data() call.
*/
ulong max_long_data_size;
Sergei Golubchik's avatar
Sergei Golubchik committed
522

523
bool max_user_connections_checking=0;
unknown's avatar
unknown committed
524
/**
525 526 527
  Limit of the total number of prepared statements in the server.
  Is necessary to protect the server against out-of-memory attacks.
*/
528
uint max_prepared_stmt_count;
unknown's avatar
unknown committed
529
/**
530 531 532 533 534 535 536 537 538
  Current total number of prepared statements in the server. This number
  is exact, and therefore may not be equal to the difference between
  `com_stmt_prepare' and `com_stmt_close' (global status variables), as
  the latter ones account for all registered attempts to prepare
  a statement (including unsuccessful ones).  Prepared statements are
  currently connection-local: if the same SQL query text is prepared in
  two different connections, this counts as two distinct prepared
  statements.
*/
539
uint prepared_stmt_count=0;
540
my_thread_id global_thread_id= 0;
541
ulong current_pid;
542
ulong slow_launch_threads = 0;
543 544
uint sync_binlog_period= 0, sync_relaylog_period= 0,
     sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
unknown's avatar
unknown committed
545
ulong expire_logs_days = 0;
546 547 548 549 550
/**
  Soft upper limit for number of sp_head objects that can be stored
  in the sp_cache for one connection.
*/
ulong stored_program_cache_size= 0;
unknown's avatar
unknown committed
551

552
ulong opt_slave_parallel_threads= 0;
unknown's avatar
unknown committed
553
ulong opt_slave_domain_parallel_threads= 0;
554
ulong opt_slave_parallel_mode= SLAVE_PARALLEL_CONSERVATIVE;
555 556
ulong opt_binlog_commit_wait_count= 0;
ulong opt_binlog_commit_wait_usec= 0;
unknown's avatar
unknown committed
557
ulong opt_slave_parallel_max_queued= 131072;
558
my_bool opt_gtid_ignore_duplicates= FALSE;
559
uint opt_gtid_cleanup_batch_size= 64;
560

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
const double log_10[] = {
  1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
  1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
  1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
  1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
  1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
  1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
  1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
  1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
  1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
  1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
  1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
  1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
  1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
  1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
  1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
  1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
  1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
  1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
  1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
  1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
  1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
  1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
  1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
  1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
  1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
  1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
  1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
  1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
  1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
  1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
  1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
};
unknown's avatar
unknown committed
594

595
time_t server_start_time, flush_status_time;
596

597 598
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
char *default_tz_name;
599
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN], *opt_log_basename;
unknown's avatar
unknown committed
600
char mysql_real_data_home[FN_REFLEN],
601 602
     lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
     mysql_charsets_dir[FN_REFLEN],
603
     *opt_init_file, *opt_tc_log_file;
604
char *lc_messages_dir_ptr= lc_messages_dir, *log_error_file_ptr;
605
char mysql_unpacked_real_data_home[FN_REFLEN];
606
size_t mysql_unpacked_real_data_home_len;
607
uint mysql_real_data_home_len, mysql_data_home_len= 1;
608
uint reg_ext_length;
609 610 611
const key_map key_map_empty(0);
key_map key_map_full(0);                        // Will be initialized later

612 613
DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
Time_zone *default_tz;
614

615
const char *mysql_real_data_home_ptr= mysql_real_data_home;
616
char server_version[SERVER_VERSION_LENGTH], *server_version_ptr;
617
bool using_custom_server_version= false;
618
char *mysqld_unix_port, *opt_mysql_tmpdir;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
619
ulong thread_handling;
620

621
my_bool encrypt_binlog;
622
my_bool encrypt_tmp_disk_tables, encrypt_tmp_files;
Monty's avatar
Monty committed
623

624
/** name of reference on left expression in rewritten IN subquery */
625
const LEX_CSTRING in_left_expr_name= {STRING_WITH_LEN("<left expr>") };
unknown's avatar
unknown committed
626
/** name of additional condition */
627 628
const LEX_CSTRING in_having_cond= {STRING_WITH_LEN("<IN HAVING>") };
const LEX_CSTRING in_additional_cond= {STRING_WITH_LEN("<IN COND>") };
629

unknown's avatar
unknown committed
630 631 632 633 634 635 636 637 638 639 640 641 642
/** Number of connection errors when selecting on the listening port */
ulong connection_errors_select= 0;
/** Number of connection errors when accepting sockets in the listening port. */
ulong connection_errors_accept= 0;
/** Number of connection errors from TCP wrappers. */
ulong connection_errors_tcpwrap= 0;
/** Number of connection errors from internal server errors. */
ulong connection_errors_internal= 0;
/** Number of connection errors from the server max_connection limit. */
ulong connection_errors_max_connection= 0;
/** Number of errors when reading the peer address. */
ulong connection_errors_peer_addr= 0;

unknown's avatar
unknown committed
643 644 645 646 647 648 649 650
/* classes for comparation parsing/processing */
Eq_creator eq_creator;
Ne_creator ne_creator;
Gt_creator gt_creator;
Lt_creator lt_creator;
Ge_creator ge_creator;
Le_creator le_creator;

651
THD_list server_threads;
652 653
Rpl_filter* cur_rpl_filter;
Rpl_filter* global_rpl_filter;
unknown's avatar
unknown committed
654
Rpl_filter* binlog_filter;
unknown's avatar
unknown committed
655

unknown's avatar
unknown committed
656
struct system_variables global_system_variables;
657 658 659 660 661 662 663 664
/**
  Following is just for options parsing, used with a difference against
  global_system_variables.

  TODO: something should be done to get rid of following variables
*/
const char *current_dbug_option="";

unknown's avatar
unknown committed
665
struct system_variables max_system_variables;
unknown's avatar
Merge  
unknown committed
666
struct system_status_var global_status_var;
unknown's avatar
unknown committed
667

unknown's avatar
unknown committed
668
MY_TMPDIR mysql_tmpdir_list;
669
MY_BITMAP temp_pool;
unknown's avatar
unknown committed
670

671 672
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
unknown's avatar
unknown committed
673
CHARSET_INFO *character_set_filesystem;
Marc Alff's avatar
Marc Alff committed
674
CHARSET_INFO *error_message_charset_info;
675

676
MY_LOCALE *my_default_lc_messages;
677 678
MY_LOCALE *my_default_lc_time_names;

679
SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
680
SHOW_COMP_OPTION have_geometry, have_rtree_keys;
unknown's avatar
unknown committed
681
SHOW_COMP_OPTION have_crypt, have_compress;
682
SHOW_COMP_OPTION have_profiling;
683
SHOW_COMP_OPTION have_openssl;
unknown's avatar
unknown committed
684

685 686
static std::atomic<char*> shutdown_user;

unknown's avatar
unknown committed
687
/* Thread specific variables */
688

unknown's avatar
unknown committed
689
pthread_key(THD*, THR_THD);
690 691 692 693 694 695 696 697 698 699 700 701 702

/*
  LOCK_start_thread is used to syncronize thread start and stop with
  other threads.

  It also protects these variables:
  select_thread_in_use
  slave_init_thread_running
  check_temp_dir() call
*/
mysql_mutex_t  LOCK_start_thread;

mysql_mutex_t LOCK_thread_cache;
703
mysql_mutex_t
704
  LOCK_status, LOCK_error_log, LOCK_short_uuid_generator,
Marc Alff's avatar
Marc Alff committed
705 706 707
  LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
  LOCK_crypt,
  LOCK_global_system_variables,
Sergey Vojtovich's avatar
Sergey Vojtovich committed
708
  LOCK_user_conn,
709
  LOCK_connection_count, LOCK_error_messages, LOCK_slave_background;
Sergei Golubchik's avatar
Sergei Golubchik committed
710 711
mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats,
              LOCK_global_table_stats, LOCK_global_index_stats;
712

713 714 715
/* This protects against changes in master_info_index */
mysql_mutex_t LOCK_active_mi;

716 717 718
/* This protects connection id.*/
mysql_mutex_t LOCK_thread_id;

unknown's avatar
unknown committed
719
/**
720 721 722 723 724 725
  The below lock protects access to two global server variables:
  max_prepared_stmt_count and prepared_stmt_count. These variables
  set the limit and hold the current total number of prepared statements
  in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
  server may be fairly high, we need a dedicated lock.
*/
Marc Alff's avatar
Marc Alff committed
726
mysql_mutex_t LOCK_prepared_stmt_count;
727
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
728
mysql_mutex_t LOCK_des_key_file;
729
#endif
Marc Alff's avatar
Marc Alff committed
730
mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
731
mysql_rwlock_t LOCK_ssl_refresh;
732
mysql_rwlock_t LOCK_all_status_vars;
733
mysql_prlock_t LOCK_system_variables_hash;
734
mysql_cond_t COND_start_thread;
unknown's avatar
unknown committed
735 736
pthread_t signal_thread;
pthread_attr_t connection_attrib;
Marc Alff's avatar
Marc Alff committed
737 738
mysql_mutex_t LOCK_server_started;
mysql_cond_t COND_server_started;
unknown's avatar
unknown committed
739

740
int mysqld_server_started=0, mysqld_server_initialized= 0;
741 742
File_parser_dummy_hook file_parser_dummy_hook;

unknown's avatar
unknown committed
743
/* replication parameters, if master_host is not NULL, we are a slave */
744
uint report_port= 0;
unknown's avatar
unknown committed
745
ulong master_retry_count=0;
746
char *master_info_file;
unknown's avatar
unknown committed
747
char *relay_log_info_file, *report_user, *report_password, *report_host;
unknown's avatar
unknown committed
748
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
749
char *opt_logname, *opt_slow_logname, *opt_bin_logname;
750
char *opt_binlog_index_name=0;
unknown's avatar
unknown committed
751 752 753

/* Static variables */

Michael Widenius's avatar
Michael Widenius committed
754
my_bool opt_stack_trace;
755 756
my_bool opt_expect_abort= 0, opt_bootstrap= 0;
static my_bool opt_myisam_log;
unknown's avatar
unknown committed
757
static int cleanup_done;
758 759
static ulong opt_specialflag;
char *mysql_home_ptr, *pidfile_name_ptr;
Marc Alff's avatar
Marc Alff committed
760
/** Initial command line arguments (count), after load_defaults().*/
unknown's avatar
unknown committed
761
static int defaults_argc;
Marc Alff's avatar
Marc Alff committed
762 763 764 765 766 767 768 769
/**
  Initial command line arguments (arguments), after load_defaults().
  This memory is allocated by @c load_defaults() and should be freed
  using @c free_defaults().
  Do not modify defaults_argc / defaults_argv,
  use remaining_argc / remaining_argv instead to parse the command
  line arguments in multiple steps.
*/
unknown's avatar
unknown committed
770
static char **defaults_argv;
Marc Alff's avatar
Marc Alff committed
771 772 773 774
/** Remaining command line arguments (count), filtered by handle_options().*/
static int remaining_argc;
/** Remaining command line arguments (arguments), filtered by handle_options().*/
static char **remaining_argv;
unknown's avatar
unknown committed
775

776 777 778
int orig_argc;
char **orig_argv;

779
static struct my_option pfs_early_options[]=
780
{
781
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
  {"performance_schema_instrument", OPT_PFS_INSTRUMENT,
    "Default startup value for a performance schema instrument.",
    &pfs_param.m_pfs_instrument, &pfs_param.m_pfs_instrument, 0, GET_STR,
    OPT_ARG, 0, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_stages_current", 0,
    "Default startup value for the events_stages_current consumer.",
    &pfs_param.m_consumer_events_stages_current_enabled,
    &pfs_param.m_consumer_events_stages_current_enabled, 0, GET_BOOL,
    OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_stages_history", 0,
    "Default startup value for the events_stages_history consumer.",
    &pfs_param.m_consumer_events_stages_history_enabled,
    &pfs_param.m_consumer_events_stages_history_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_stages_history_long", 0,
    "Default startup value for the events_stages_history_long consumer.",
    &pfs_param.m_consumer_events_stages_history_long_enabled,
    &pfs_param.m_consumer_events_stages_history_long_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_statements_current", 0,
    "Default startup value for the events_statements_current consumer.",
    &pfs_param.m_consumer_events_statements_current_enabled,
    &pfs_param.m_consumer_events_statements_current_enabled, 0,
    GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_statements_history", 0,
    "Default startup value for the events_statements_history consumer.",
    &pfs_param.m_consumer_events_statements_history_enabled,
    &pfs_param.m_consumer_events_statements_history_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_statements_history_long", 0,
    "Default startup value for the events_statements_history_long consumer.",
    &pfs_param.m_consumer_events_statements_history_long_enabled,
    &pfs_param.m_consumer_events_statements_history_long_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_waits_current", 0,
    "Default startup value for the events_waits_current consumer.",
    &pfs_param.m_consumer_events_waits_current_enabled,
    &pfs_param.m_consumer_events_waits_current_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_waits_history", 0,
    "Default startup value for the events_waits_history consumer.",
    &pfs_param.m_consumer_events_waits_history_enabled,
    &pfs_param.m_consumer_events_waits_history_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_events_waits_history_long", 0,
    "Default startup value for the events_waits_history_long consumer.",
    &pfs_param.m_consumer_events_waits_history_long_enabled,
    &pfs_param.m_consumer_events_waits_history_long_enabled, 0,
    GET_BOOL, OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_global_instrumentation", 0,
    "Default startup value for the global_instrumentation consumer.",
    &pfs_param.m_consumer_global_instrumentation_enabled,
    &pfs_param.m_consumer_global_instrumentation_enabled, 0,
    GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_thread_instrumentation", 0,
    "Default startup value for the thread_instrumentation consumer.",
    &pfs_param.m_consumer_thread_instrumentation_enabled,
    &pfs_param.m_consumer_thread_instrumentation_enabled, 0,
    GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0},
  {"performance_schema_consumer_statements_digest", 0,
    "Default startup value for the statements_digest consumer.",
    &pfs_param.m_consumer_statement_digest_enabled,
    &pfs_param.m_consumer_statement_digest_enabled, 0,
845
    GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0},
846
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
847 848 849 850
  {"getopt-prefix-matching", 0,
    "Recognize command-line options by their unambiguos prefixes.",
    &my_getopt_prefix_matching, &my_getopt_prefix_matching, 0, GET_BOOL,
    NO_ARG, 1, 0, 1, 0, 0, 0}
851 852
};

853 854
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
855 856
PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool,
  key_LOCK_pending_checkpoint;
857 858 859 860 861 862
#endif /* HAVE_MMAP */

#ifdef HAVE_OPENSSL
PSI_mutex_key key_LOCK_des_key_file;
#endif /* HAVE_OPENSSL */

863
PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
864
  key_BINLOG_LOCK_binlog_background_thread,
865
  key_LOCK_binlog_end_pos,
866 867 868 869 870 871
  key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
  key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
  key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
  key_LOCK_gdl, key_LOCK_global_system_variables,
  key_LOCK_manager,
  key_LOCK_prepared_stmt_count,
872
  key_LOCK_rpl_status, key_LOCK_server_started,
873
  key_LOCK_status,
874
  key_LOCK_system_variables_hash, key_LOCK_thd_data, key_LOCK_thd_kill,
875 876
  key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log,
  key_master_info_data_lock, key_master_info_run_lock,
877
  key_master_info_sleep_lock, key_master_info_start_stop_lock,
878
  key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
Michael Widenius's avatar
Michael Widenius committed
879
  key_rpl_group_info_sleep_lock,
880
  key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
881
  key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
882
  key_LOCK_error_messages,
883
  key_LOCK_start_thread,
884
  key_LOCK_thread_cache,
885 886
  key_PARTITION_LOCK_auto_inc;
PSI_mutex_key key_RELAYLOG_LOCK_index;
887
PSI_mutex_key key_LOCK_relaylog_end_pos;
888
PSI_mutex_key key_LOCK_thread_id;
889
PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
890
  key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry;
891
PSI_mutex_key key_LOCK_binlog;
892 893 894

PSI_mutex_key key_LOCK_stats,
  key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
Sergei Golubchik's avatar
Sergei Golubchik committed
895
  key_LOCK_global_index_stats,
896
  key_LOCK_wakeup_ready, key_LOCK_wait_commit;
897
PSI_mutex_key key_LOCK_gtid_waiting;
Sergei Golubchik's avatar
Sergei Golubchik committed
898

899
PSI_mutex_key key_LOCK_after_binlog_sync;
900
PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered,
901
  key_LOCK_slave_background;
Sergei Golubchik's avatar
Sergei Golubchik committed
902
PSI_mutex_key key_TABLE_SHARE_LOCK_share;
903
PSI_mutex_key key_LOCK_ack_receiver;
904

905 906 907
PSI_mutex_key key_TABLE_SHARE_LOCK_rotation;
PSI_cond_key key_TABLE_SHARE_COND_rotation;

908 909 910 911 912 913 914
static PSI_mutex_info all_server_mutexes[]=
{
#ifdef HAVE_MMAP
  { &key_PAGE_lock, "PAGE::lock", 0},
  { &key_LOCK_sync, "TC_LOG_MMAP::LOCK_sync", 0},
  { &key_LOCK_active, "TC_LOG_MMAP::LOCK_active", 0},
  { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pool", 0},
915
  { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pending_checkpoint", 0},
916 917 918 919 920 921 922
#endif /* HAVE_MMAP */

#ifdef HAVE_OPENSSL
  { &key_LOCK_des_key_file, "LOCK_des_key_file", PSI_FLAG_GLOBAL},
#endif /* HAVE_OPENSSL */

  { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0},
923
  { &key_BINLOG_LOCK_xid_list, "MYSQL_BIN_LOG::LOCK_xid_list", 0},
924
  { &key_BINLOG_LOCK_binlog_background_thread, "MYSQL_BIN_LOG::LOCK_binlog_background_thread", 0},
925
  { &key_LOCK_binlog_end_pos, "MYSQL_BIN_LOG::LOCK_binlog_end_pos", 0 },
926
  { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
927
  { &key_LOCK_relaylog_end_pos, "MYSQL_RELAY_LOG::LOCK_binlog_end_pos", 0},
928 929 930 931
  { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
  { &key_hash_filo_lock, "hash_filo::lock", 0},
  { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL},
  { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL},
932
  { &key_LOCK_thread_id, "LOCK_thread_id", PSI_FLAG_GLOBAL},
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
  { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
  { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL},
  { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL},
  { &key_LOCK_delayed_status, "LOCK_delayed_status", PSI_FLAG_GLOBAL},
  { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL},
  { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
  { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
  { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
  { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
  { &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
  { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL},
  { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL},
  { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
  { &key_LOCK_stats, "LOCK_stats", PSI_FLAG_GLOBAL},
  { &key_LOCK_global_user_client_stats, "LOCK_global_user_client_stats", PSI_FLAG_GLOBAL},
  { &key_LOCK_global_table_stats, "LOCK_global_table_stats", PSI_FLAG_GLOBAL},
  { &key_LOCK_global_index_stats, "LOCK_global_index_stats", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
950
  { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
951
  { &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0},
952
  { &key_LOCK_gtid_waiting, "gtid_waiting::LOCK_gtid_waiting", 0},
953
  { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
954
  { &key_LOCK_thd_kill, "THD::LOCK_thd_kill", 0},
955
  { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
956
  { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
957 958
  { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
  { &key_master_info_data_lock, "Master_info::data_lock", 0},
959
  { &key_master_info_start_stop_lock, "Master_info::start_stop_lock", 0},
960
  { &key_master_info_run_lock, "Master_info::run_lock", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
961
  { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
962 963 964 965
  { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
  { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0},
  { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0},
  { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0},
Michael Widenius's avatar
Michael Widenius committed
966
  { &key_rpl_group_info_sleep_lock, "Rpl_group_info::sleep_lock", 0},
967 968
  { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
  { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
969
  { &key_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0},
970
  { &key_TABLE_SHARE_LOCK_rotation, "TABLE_SHARE::LOCK_rotation", 0},
971
  { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
972
  { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL},
973
  { &key_LOCK_after_binlog_sync, "LOCK_after_binlog_sync", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
974
  { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
975
  { &key_LOCK_slave_background, "LOCK_slave_background", PSI_FLAG_GLOBAL},
Michael Widenius's avatar
Michael Widenius committed
976
  { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL},
977
  { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0},
unknown's avatar
unknown committed
978
  { &key_LOCK_slave_state, "LOCK_slave_state", 0},
979
  { &key_LOCK_start_thread, "LOCK_start_thread", PSI_FLAG_GLOBAL},
980 981
  { &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
  { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
982
  { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
983
  { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0},
984
  { &key_LOCK_ack_receiver, "Ack_receiver::mutex", 0},
985
  { &key_LOCK_binlog, "LOCK_binlog", 0}
986 987 988 989
};

PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
  key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
990
  key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
991
  key_LOCK_SEQUENCE,
992
  key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial,
993
  key_rwlock_LOCK_ssl_refresh,
994 995
  key_rwlock_THD_list,
  key_rwlock_LOCK_all_status_vars;
996 997 998

static PSI_rwlock_info all_server_rwlocks[]=
{
999
#ifdef HAVE_OPENSSL10
1000 1001 1002 1003 1004 1005
  { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
#endif
  { &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL},
  { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
  { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
  { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
1006
  { &key_LOCK_SEQUENCE, "LOCK_SEQUENCE", 0},
1007
  { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
1008 1009
  { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0},
  { &key_rwlock_LOCK_vers_stats, "Vers_field_stats::lock", 0},
1010
  { &key_rwlock_LOCK_stat_serial, "TABLE_SHARE::LOCK_stat_serial", 0},
1011
  { &key_rwlock_LOCK_ssl_refresh, "LOCK_ssl_refresh", PSI_FLAG_GLOBAL },
1012 1013
  { &key_rwlock_THD_list, "THD_list::lock", PSI_FLAG_GLOBAL },
  { &key_rwlock_LOCK_all_status_vars, "LOCK_all_status_vars", PSI_FLAG_GLOBAL }
1014 1015 1016
};

#ifdef HAVE_MMAP
1017
PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
1018 1019
#endif /* HAVE_MMAP */

1020 1021
PSI_cond_key key_BINLOG_COND_xid_list,
  key_BINLOG_COND_bin_log_updated, key_BINLOG_COND_relay_log_updated,
1022 1023
  key_BINLOG_COND_binlog_background_thread,
  key_BINLOG_COND_binlog_background_thread_end,
1024 1025 1026 1027 1028
  key_COND_cache_status_changed, key_COND_manager,
  key_COND_rpl_status, key_COND_server_started,
  key_delayed_insert_cond, key_delayed_insert_cond_client,
  key_item_func_sleep_cond, key_master_info_data_cond,
  key_master_info_start_cond, key_master_info_stop_cond,
Sergei Golubchik's avatar
Sergei Golubchik committed
1029
  key_master_info_sleep_cond,
1030 1031
  key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
  key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
Michael Widenius's avatar
Michael Widenius committed
1032
  key_rpl_group_info_sleep_cond,
1033
  key_TABLE_SHARE_cond, key_user_level_lock_cond,
1034
  key_COND_thread_cache, key_COND_flush_thread_cache,
1035
  key_COND_start_thread, key_COND_binlog_send,
1036
  key_BINLOG_COND_queue_busy;
1037 1038
PSI_cond_key key_RELAYLOG_COND_relay_log_updated,
  key_RELAYLOG_COND_bin_log_updated, key_COND_wakeup_ready,
1039
  key_COND_wait_commit;
1040 1041
PSI_cond_key key_RELAYLOG_COND_queue_busy;
PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
unknown's avatar
unknown committed
1042
PSI_cond_key key_COND_rpl_thread_queue, key_COND_rpl_thread,
Monty's avatar
Monty committed
1043
  key_COND_rpl_thread_stop, key_COND_rpl_thread_pool,
unknown's avatar
unknown committed
1044
  key_COND_parallel_entry, key_COND_group_commit_orderer,
1045
  key_COND_prepare_ordered, key_COND_slave_background;
1046
PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates;
1047
PSI_cond_key key_COND_ack_receiver;
1048 1049 1050 1051 1052 1053 1054

static PSI_cond_info all_server_conds[]=
{
#ifdef HAVE_MMAP
  { &key_PAGE_cond, "PAGE::cond", 0},
  { &key_COND_active, "TC_LOG_MMAP::COND_active", 0},
  { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0},
1055
  { &key_TC_LOG_MMAP_COND_queue_busy, "TC_LOG_MMAP::COND_queue_busy", 0},
1056
#endif /* HAVE_MMAP */
1057
  { &key_BINLOG_COND_bin_log_updated, "MYSQL_BIN_LOG::COND_bin_log_updated", 0}, { &key_BINLOG_COND_relay_log_updated, "MYSQL_BIN_LOG::COND_relay_log_updated", 0},
1058
  { &key_BINLOG_COND_xid_list, "MYSQL_BIN_LOG::COND_xid_list", 0},
1059 1060
  { &key_BINLOG_COND_binlog_background_thread, "MYSQL_BIN_LOG::COND_binlog_background_thread", 0},
  { &key_BINLOG_COND_binlog_background_thread_end, "MYSQL_BIN_LOG::COND_binlog_background_thread_end", 0},
1061
  { &key_BINLOG_COND_queue_busy, "MYSQL_BIN_LOG::COND_queue_busy", 0},
1062 1063
  { &key_RELAYLOG_COND_relay_log_updated, "MYSQL_RELAY_LOG::COND_relay_log_updated", 0},
  { &key_RELAYLOG_COND_bin_log_updated, "MYSQL_RELAY_LOG::COND_bin_log_updated", 0},
1064
  { &key_RELAYLOG_COND_queue_busy, "MYSQL_RELAY_LOG::COND_queue_busy", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
1065
  { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 0},
1066
  { &key_COND_wait_commit, "wait_for_commit::COND_wait_commit", 0},
1067 1068 1069 1070 1071 1072 1073 1074 1075
  { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
  { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
  { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
  { &key_delayed_insert_cond, "Delayed_insert::cond", 0},
  { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0},
  { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0},
  { &key_master_info_data_cond, "Master_info::data_cond", 0},
  { &key_master_info_start_cond, "Master_info::start_cond", 0},
  { &key_master_info_stop_cond, "Master_info::stop_cond", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
1076
  { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
1077 1078 1079 1080
  { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0},
  { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0},
  { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0},
  { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0},
Michael Widenius's avatar
Michael Widenius committed
1081
  { &key_rpl_group_info_sleep_cond, "Rpl_group_info::sleep_cond", 0},
1082 1083 1084
  { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
  { &key_user_level_lock_cond, "User_level_lock::cond", 0},
  { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL},
1085 1086
  { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL},
  { &key_COND_rpl_thread, "COND_rpl_thread", 0},
unknown's avatar
unknown committed
1087
  { &key_COND_rpl_thread_queue, "COND_rpl_thread_queue", 0},
Monty's avatar
Monty committed
1088
  { &key_COND_rpl_thread_stop, "COND_rpl_thread_stop", 0},
1089
  { &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0},
1090
  { &key_COND_parallel_entry, "COND_parallel_entry", 0},
unknown's avatar
unknown committed
1091
  { &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0},
1092
  { &key_COND_prepare_ordered, "COND_prepare_ordered", 0},
1093
  { &key_COND_slave_background, "COND_slave_background", 0},
1094
  { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL},
1095
  { &key_COND_wait_gtid, "COND_wait_gtid", 0},
1096
  { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0},
1097
  { &key_COND_ack_receiver, "Ack_receiver::cond", 0},
1098
  { &key_COND_binlog_send, "COND_binlog_send", 0},
1099
  { &key_TABLE_SHARE_COND_rotation, "TABLE_SHARE::COND_rotation", 0}
1100 1101
};

Sergey Vojtovich's avatar
Sergey Vojtovich committed
1102
PSI_thread_key key_thread_delayed_insert,
1103
  key_thread_handle_manager, key_thread_main,
1104
  key_thread_one_connection, key_thread_signal_hand,
1105
  key_thread_slave_background, key_rpl_parallel_thread;
1106
PSI_thread_key key_thread_ack_receiver;
1107 1108 1109 1110 1111 1112 1113

static PSI_thread_info all_server_threads[]=
{
  { &key_thread_delayed_insert, "delayed_insert", 0},
  { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL},
  { &key_thread_main, "main", PSI_FLAG_GLOBAL},
  { &key_thread_one_connection, "one_connection", 0},
1114
  { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL},
1115
  { &key_thread_slave_background, "slave_background", PSI_FLAG_GLOBAL},
1116
  { &key_thread_ack_receiver, "Ack_receiver", PSI_FLAG_GLOBAL},
1117
  { &key_rpl_parallel_thread, "rpl_parallel_thread", 0}
1118 1119
};

1120 1121 1122 1123
#ifdef HAVE_MMAP
PSI_file_key key_file_map;
#endif /* HAVE_MMAP */

1124 1125 1126 1127 1128 1129 1130 1131 1132
PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
  key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
  key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
  key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
  key_file_master_info, key_file_misc, key_file_partition,
  key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
  key_file_trg, key_file_trn, key_file_init;
PSI_file_key key_file_query_log, key_file_slow_log;
PSI_file_key key_file_relaylog, key_file_relaylog_index;
1133
PSI_file_key key_file_binlog_state;
1134

1135
#endif /* HAVE_PSI_INTERFACE */
1136

1137 1138 1139 1140 1141 1142
#ifdef HAVE_PSI_STATEMENT_INTERFACE
PSI_statement_info stmt_info_new_packet;
#endif

#ifndef EMBEDDED_LIBRARY
void net_before_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */)
1143
{
1144 1145 1146
  THD *thd;
  thd= static_cast<THD*> (user_data);
  DBUG_ASSERT(thd != NULL);
1147

1148 1149 1150 1151 1152 1153 1154 1155 1156
  /*
    We only come where when the server is IDLE, waiting for the next command.
    Technically, it is a wait on a socket, which may take a long time,
    because the call is blocking.
    Disable the socket instrumentation, to avoid recording a SOCKET event.
    Instead, start explicitly an IDLE event.
  */
  MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE);
  MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state);
1157
}
1158

1159 1160
void net_after_header_psi(struct st_net *net, void *user_data,
                          size_t /* unused: count */, my_bool rc)
1161 1162 1163 1164
{
  THD *thd;
  thd= static_cast<THD*> (user_data);
  DBUG_ASSERT(thd != NULL);
1165

1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
  /*
    The server just got data for a network packet header,
    from the network layer.
    The IDLE event is now complete, since we now have a message to process.
    We need to:
    - start a new STATEMENT event
    - start a new STAGE event, within this statement,
    - start recording SOCKET WAITS events, within this stage.
    The proper order is critical to get events numbered correctly,
    and nested in the proper parent.
  */
  MYSQL_END_IDLE_WAIT(thd->m_idle_psi);
1178

1179
  if (! rc)
1180
  {
1181 1182
    thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
                                                stmt_info_new_packet.m_key,
1183
                                                thd->get_db(), thd->db.length,
1184
                                                thd->charset());
1185

1186
    THD_STAGE_INFO(thd, stage_init);
1187
  }
1188 1189 1190 1191 1192 1193

  /*
    TODO: consider recording a SOCKET event for the bytes just read,
    by also passing count here.
  */
  MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE);
1194 1195
}

1196

1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
void init_net_server_extension(THD *thd)
{
  /* Start with a clean state for connection events. */
  thd->m_idle_psi= NULL;
  thd->m_statement_psi= NULL;
  /* Hook up the NET_SERVER callback in the net layer. */
  thd->m_net_server_extension.m_user_data= thd;
  thd->m_net_server_extension.m_before_header= net_before_header_psi;
  thd->m_net_server_extension.m_after_header= net_after_header_psi;
  /* Activate this private extension for the mysqld server. */
  thd->net.extension= & thd->m_net_server_extension;
}
1209 1210 1211 1212
#else
void init_net_server_extension(THD *thd)
{
}
1213
#endif /* EMBEDDED_LIBRARY */
1214

1215

Marc Alff's avatar
Marc Alff committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
/**
  A log message for the error log, buffered in memory.
  Log messages are temporarily buffered when generated before the error log
  is initialized, and then printed once the error log is ready.
*/
class Buffered_log : public Sql_alloc
{
public:
  Buffered_log(enum loglevel level, const char *message);

  ~Buffered_log()
  {}

  void print(void);

private:
  /** Log message level. */
  enum loglevel m_level;
  /** Log message text. */
  String m_message;
};

/**
  Constructor.
  @param level          the message log level
  @param message        the message text
*/
Buffered_log::Buffered_log(enum loglevel level, const char *message)
  : m_level(level), m_message()
{
  m_message.copy(message, strlen(message), &my_charset_latin1);
}

/**
  Print a buffered log to the real log file.
*/
void Buffered_log::print()
{
  /*
    Since messages are buffered, they can be printed out
    of order with other entries in the log.
    Add "Buffered xxx" to the message text to prevent confusion.
  */
  switch(m_level)
  {
  case ERROR_LEVEL:
Monty's avatar
Monty committed
1262
    sql_print_error("Buffered error: %s", m_message.c_ptr_safe());
Marc Alff's avatar
Marc Alff committed
1263 1264
    break;
  case WARNING_LEVEL:
Monty's avatar
Monty committed
1265
    sql_print_warning("Buffered warning: %s", m_message.c_ptr_safe());
Marc Alff's avatar
Marc Alff committed
1266 1267
    break;
  case INFORMATION_LEVEL:
1268 1269 1270 1271 1272 1273 1274 1275 1276
    /*
      Messages printed as "information" still end up in the mysqld *error* log,
      but with a [Note] tag instead of an [ERROR] tag.
      While this is probably fine for a human reading the log,
      it is upsetting existing automated scripts used to parse logs,
      because such scripts are likely to not already handle [Note] properly.
      INFORMATION_LEVEL messages are simply silenced, on purpose,
      to avoid un needed verbosity.
    */
Marc Alff's avatar
Marc Alff committed
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
    break;
  }
}

/**
  Collection of all the buffered log messages.
*/
class Buffered_logs
{
public:
  Buffered_logs()
  {}

  ~Buffered_logs()
  {}

  void init();
  void cleanup();

  void buffer(enum loglevel m_level, const char *msg);
  void print();
private:
  /**
    Memory root to use to store buffered logs.
    This memory root lifespan is between init and cleanup.
    Once the buffered logs are printed, they are not needed anymore,
    and all the memory used is reclaimed.
  */
  MEM_ROOT m_root;
  /** List of buffered log messages. */
  List<Buffered_log> m_list;
};

void Buffered_logs::init()
{
1312
  init_alloc_root(&m_root, "Buffered_logs", 1024, 0, MYF(0));
Marc Alff's avatar
Marc Alff committed
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
}

void Buffered_logs::cleanup()
{
  m_list.delete_elements();
  free_root(&m_root, MYF(0));
}

/**
  Add a log message to the buffer.
*/
void Buffered_logs::buffer(enum loglevel level, const char *msg)
{
  /*
    Do not let Sql_alloc::operator new(size_t) allocate memory,
    there is no memory root associated with the main() thread.
    Give explicitly the proper memory root to use to
    Sql_alloc::operator new(size_t, MEM_ROOT *) instead.
  */
  Buffered_log *log= new (&m_root) Buffered_log(level, msg);
  if (log)
    m_list.push_back(log, &m_root);
}

/**
  Print buffered log messages.
*/
void Buffered_logs::print()
{
  Buffered_log *log;
  List_iterator_fast<Buffered_log> it(m_list);
  while ((log= it++))
    log->print();
}

/** Logs reported before a logger is available. */
static Buffered_logs buffered_logs;

1351 1352
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()

1353
#ifndef EMBEDDED_LIBRARY
1354
MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
Marc Alff's avatar
Marc Alff committed
1355 1356 1357 1358 1359
/**
  Error reporter that buffer log messages.
  @param level          log message level
  @param format         log message format string
*/
1360
C_MODE_START
1361 1362
static void buffered_option_error_reporter(enum loglevel level,
                                           const char *format, ...)
Marc Alff's avatar
Marc Alff committed
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
{
  va_list args;
  char buffer[1024];

  va_start(args, format);
  my_vsnprintf(buffer, sizeof(buffer), format, args);
  va_end(args);
  buffered_logs.buffer(level, buffer);
}

1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399

/**
  Character set and collation error reporter that prints to sql error log.
  @param level          log message level
  @param format         log message format string

  This routine is used to print character set and collation
  warnings and errors inside an already running mysqld server,
  e.g. when a character set or collation is requested for the very first time
  and its initialization does not go well for some reasons.

  Note: At early mysqld initialization stage,
  when error log is not yet available,
  we use buffered_option_error_reporter() instead,
  to print general character set subsystem initialization errors,
  such as Index.xml syntax problems, bad XML tag hierarchy, etc.
*/
static void charset_error_reporter(enum loglevel level,
                                   const char *format, ...)
{
  va_list args;
  va_start(args, format);
  vprint_msg_to_log(level, format, args);
  va_end(args);                      
}
C_MODE_END

unknown's avatar
unknown committed
1400 1401 1402 1403
struct passwd *user_info;
static pthread_t select_thread;
#endif

unknown's avatar
unknown committed
1404 1405
/* OS specific variables */

unknown's avatar
unknown committed
1406 1407 1408
#ifdef __WIN__
#undef	 getpid
#include <process.h>
unknown's avatar
unknown committed
1409 1410 1411 1412 1413

static bool start_mode=0, use_opt_args;
static int opt_argc;
static char **opt_argv;

unknown's avatar
unknown committed
1414
#if !defined(EMBEDDED_LIBRARY)
1415
HANDLE hEventShutdown;
1416
static char shutdown_event_name[40];
unknown's avatar
unknown committed
1417
#include "nt_servc.h"
unknown's avatar
unknown committed
1418
static	 NTService  Service;	      ///< Service object for WinNT
unknown's avatar
unknown committed
1419 1420 1421 1422
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */

#ifndef EMBEDDED_LIBRARY
1423
bool mysqld_embedded=0;
unknown's avatar
unknown committed
1424
#else
1425
bool mysqld_embedded=1;
unknown's avatar
unknown committed
1426 1427
#endif

1428
my_bool plugins_are_initialized= FALSE;
1429

unknown's avatar
unknown committed
1430
#ifndef DBUG_OFF
1431
static const char* default_dbug_option;
unknown's avatar
unknown committed
1432 1433
#endif
#ifdef HAVE_LIBWRAP
1434
const char *libwrapName= NULL;
1435 1436
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
unknown's avatar
unknown committed
1437 1438 1439 1440 1441
#endif
#ifdef HAVE_QUERY_CACHE
ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
Query_cache query_cache;
#endif
1442

unknown's avatar
unknown committed
1443

1444 1445
my_bool opt_use_ssl  = 0;
char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
1446 1447 1448
  *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL,
  *opt_ssl_crlpath= NULL;

1449

Sergei Golubchik's avatar
Sergei Golubchik committed
1450 1451 1452
static scheduler_functions thread_scheduler_struct, extra_thread_scheduler_struct;
scheduler_functions *thread_scheduler= &thread_scheduler_struct,
                    *extra_thread_scheduler= &extra_thread_scheduler_struct;
unknown's avatar
unknown committed
1453

unknown's avatar
unknown committed
1454
#ifdef HAVE_OPENSSL
1455
#include <openssl/crypto.h>
1456
#ifdef HAVE_OPENSSL10
1457 1458
typedef struct CRYPTO_dynlock_value
{
Marc Alff's avatar
Marc Alff committed
1459
  mysql_rwlock_t lock;
1460 1461 1462 1463 1464 1465 1466
} openssl_lock_t;

static openssl_lock_t *openssl_stdlocks;
static openssl_lock_t *openssl_dynlock_create(const char *, int);
static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
static void openssl_lock_function(int, int, const char *, int);
static void openssl_lock(int, openssl_lock_t *, const char *, int);
1467
#endif /* HAVE_OPENSSL10 */
unknown's avatar
unknown committed
1468
char *des_key_file;
Konstantin Osipov's avatar
Konstantin Osipov committed
1469
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1470
struct st_VioSSLFd *ssl_acceptor_fd;
Konstantin Osipov's avatar
Konstantin Osipov committed
1471
#endif
unknown's avatar
unknown committed
1472 1473
#endif /* HAVE_OPENSSL */

1474 1475 1476 1477
/**
  Number of currently active user connections. The variable is protected by
  LOCK_connection_count.
*/
1478
uint connection_count= 0, extra_connection_count= 0;
unknown's avatar
unknown committed
1479

1480
my_bool opt_gtid_strict_mode= FALSE;
1481 1482


unknown's avatar
unknown committed
1483 1484
/* Function declarations */

1485
pthread_handler_t signal_hand(void *arg);
1486
static int mysql_init_variables(void);
Marc Alff's avatar
Marc Alff committed
1487 1488
static int get_options(int *argc_ptr, char ***argv_ptr);
static bool add_terminator(DYNAMIC_ARRAY *options);
1489
static bool add_many_options(DYNAMIC_ARRAY *, my_option *, size_t);
1490
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
1491
static int init_thread_environment();
unknown's avatar
unknown committed
1492
static char *get_relative_path(const char *path);
1493
static int fix_paths(void);
1494
#ifndef _WIN32
1495 1496
void handle_connections_sockets();
#endif
1497

unknown's avatar
unknown committed
1498
static bool read_init_file(char *file_name);
1499
pthread_handler_t handle_slave(void *arg);
unknown's avatar
unknown committed
1500
static void clean_up(bool print_message);
1501 1502 1503
static int test_if_case_insensitive(const char *dir_name);

#ifndef EMBEDDED_LIBRARY
1504
static bool pid_file_created= false;
1505
static void usage(void);
1506 1507
static void start_signal_handler(void);
static void close_server_sock();
unknown's avatar
unknown committed
1508
static void clean_up_mutexes(void);
1509
static void wait_for_signal_thread_to_end(void);
1510
static void create_pid_file();
1511
ATTRIBUTE_NORETURN static void mysqld_exit(int exit_code);
1512
#endif
1513
static void delete_pid_file(myf flags);
Konstantin Osipov's avatar
Konstantin Osipov committed
1514
static void end_ssl();
1515

1516 1517

#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1518 1519 1520 1521
/****************************************************************************
** Code to end mysqld
****************************************************************************/

1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563
static my_bool kill_all_threads(THD *thd, void *)
{
  DBUG_PRINT("quit", ("Informing thread %ld that it's time to die",
                      (ulong) thd->thread_id));
  /* We skip slave threads on this first loop through. */
  if (thd->slave_thread)
    return 0;

  if (DBUG_EVALUATE_IF("only_kill_system_threads", !thd->system_thread, 0))
    return 0;

  thd->set_killed(KILL_SERVER_HARD);
  MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd));
  if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
  mysql_mutex_lock(&thd->LOCK_thd_kill);
  if (thd->mysys_var)
  {
    thd->mysys_var->abort= 1;
    mysql_mutex_lock(&thd->mysys_var->mutex);
    if (thd->mysys_var->current_cond)
    {
      for (uint i= 0; i < 2; i++)
      {
        int ret= mysql_mutex_trylock(thd->mysys_var->current_mutex);
        mysql_cond_broadcast(thd->mysys_var->current_cond);
        if (!ret)
        {
          /* Thread has surely got the signal, unlock and abort */
          mysql_mutex_unlock(thd->mysys_var->current_mutex);
          break;
        }
        sleep(1);
      }
    }
    mysql_mutex_unlock(&thd->mysys_var->mutex);
  }
  mysql_mutex_unlock(&thd->LOCK_thd_kill);
  if (WSREP(thd)) mysql_mutex_unlock(&thd->LOCK_thd_data);
  return 0;
}


1564
static my_bool warn_threads_still_active(THD *thd, void *)
1565
{
1566 1567 1568 1569
  sql_print_warning("%s: Thread %llu (user : '%s') did not exit\n", my_progname,
                    (ulonglong) thd->thread_id,
                    (thd->main_security_ctx.user ?
                     thd->main_security_ctx.user : ""));
1570 1571 1572 1573
  return 0;
}


1574 1575 1576 1577 1578 1579 1580 1581 1582
/**
  Kills main thread.

  @note this function is responsible for setting abort_loop and breaking
  poll() in main thread. Shutdown as such is supposed to be performed by main
  thread itself.
*/

static void break_connect_loop()
unknown's avatar
unknown committed
1583 1584 1585 1586 1587
{
#ifdef EXTRA_DEBUG
  int count=0;
#endif

1588
  abort_loop= 1;
1589

1590 1591 1592 1593 1594 1595 1596
#if defined(__WIN__)
  if (!SetEvent(hEventShutdown))
    DBUG_PRINT("error", ("Got error: %ld from SetEvent", GetLastError()));
#else
  /* Avoid waiting for ourselves when thread-handling=no-threads. */
  if (pthread_equal(pthread_self(), select_thread))
    return;
1597 1598
  DBUG_PRINT("quit", ("waiting for select thread: %lu",
                      (ulong)select_thread));
unknown's avatar
unknown committed
1599

1600
  mysql_mutex_lock(&LOCK_start_thread);
unknown's avatar
unknown committed
1601 1602 1603
  while (select_thread_in_use)
  {
    struct timespec abstime;
1604
    int UNINIT_VAR(error);
unknown's avatar
unknown committed
1605
    DBUG_PRINT("info",("Waiting for select thread"));
1606

unknown's avatar
unknown committed
1607
#ifndef DONT_USE_THR_ALARM
1608
    if (pthread_kill(select_thread, thr_client_alarm))
unknown's avatar
unknown committed
1609 1610
      break;					// allready dead
#endif
1611
    set_timespec(abstime, 2);
1612
    for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
unknown's avatar
unknown committed
1613
    {
1614
      error= mysql_cond_timedwait(&COND_start_thread, &LOCK_start_thread,
Marc Alff's avatar
Marc Alff committed
1615
                                  &abstime);
unknown's avatar
unknown committed
1616
      if (error != EINTR)
Brave Galera Crew's avatar
Brave Galera Crew committed
1617
        break;
unknown's avatar
unknown committed
1618 1619
    }
#ifdef EXTRA_DEBUG
1620
    if (error != 0 && error != ETIMEDOUT && !count++)
Marc Alff's avatar
Marc Alff committed
1621
      sql_print_error("Got error %d from mysql_cond_timedwait", error);
unknown's avatar
unknown committed
1622
#endif
unknown's avatar
unknown committed
1623
    close_server_sock();
unknown's avatar
unknown committed
1624
  }
1625
  mysql_mutex_unlock(&LOCK_start_thread);
unknown's avatar
unknown committed
1626
#endif /* __WIN__ */
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
}


/**
  A wrapper around kill_main_thrad().

  Sets shutdown user. This function may be called by multiple threads
  concurrently, thus it performs safe update of shutdown_user
  (first thread wins).
*/
unknown's avatar
unknown committed
1637

1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
void kill_mysql(THD *thd)
{
  char user_host_buff[MAX_USER_HOST_SIZE + 1];
  char *user, *expected_shutdown_user= 0;

  make_user_name(thd, user_host_buff);

  if ((user= my_strdup(user_host_buff, MYF(0))) &&
      !shutdown_user.compare_exchange_strong(expected_shutdown_user,
                                             user,
                                             std::memory_order_relaxed,
                                             std::memory_order_relaxed))
  {
    my_free(user);
  }
  break_connect_loop();
}


static void close_connections(void)
{
  DBUG_ENTER("close_connections");

  /* Clear thread cache */
  kill_cached_threads++;
  flush_thread_cache();
unknown's avatar
unknown committed
1664 1665 1666

  /* Abort listening to new connections */
  DBUG_PRINT("quit",("Closing sockets"));
unknown's avatar
Merge  
unknown committed
1667
  if (!opt_disable_networking )
unknown's avatar
unknown committed
1668
  {
1669
    if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1670
    {
1671 1672
      (void) mysql_socket_close(base_ip_sock);
      base_ip_sock= MYSQL_INVALID_SOCKET;
1673
    }
1674
    if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1675
    {
1676 1677
      (void) mysql_socket_close(extra_ip_sock);
      extra_ip_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1678 1679
    }
  }
1680

unknown's avatar
unknown committed
1681
#ifdef HAVE_SYS_UN_H
1682
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1683
  {
1684
    (void) mysql_socket_close(unix_sock);
1685
    (void) unlink(mysqld_unix_port);
1686
    unix_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1687 1688
  }
#endif
1689
  end_thr_alarm(0);			 // Abort old alarms.
unknown's avatar
unknown committed
1690

1691 1692 1693 1694 1695
  /*
    First signal all threads that it's time to die
    This will give the threads some time to gracefully abort their
    statements and inform their clients that the server is about to die.
  */
1696
  server_threads.iterate(kill_all_threads);
unknown's avatar
unknown committed
1697

1698
  Events::deinit();
1699
  slave_prepare_for_shutdown();
1700
  mysql_bin_log.stop_background_thread();
1701
  ack_receiver.stop();
1702

1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716
  /*
    Give threads time to die.

    In 5.5, this was waiting 100 rounds @ 20 milliseconds/round, so as little
    as 2 seconds, depending on thread scheduling.

    From 10.0, we increase this to 1000 rounds / 20 seconds. The rationale is
    that on a server with heavy I/O load, it is quite possible for eg. an
    fsync() of the binlog or whatever to cause something like LOCK_log to be
    held for more than 2 seconds. We do not want to force kill threads in
    such cases, if it can be avoided. Note that normally, the wait will be
    much smaller than even 2 seconds, this is only a safety fallback against
    stuck threads so server shutdown is not held up forever.
  */
1717
  DBUG_PRINT("info", ("thread_count: %u", uint32_t(thread_count)));
1718

1719
  for (int i= 0; thread_count && i < 1000; i++)
1720
    my_sleep(20000);
unknown's avatar
unknown committed
1721

1722 1723
  if (global_system_variables.log_warnings)
    server_threads.iterate(warn_threads_still_active);
unknown's avatar
unknown committed
1724

Brave Galera Crew's avatar
Brave Galera Crew committed
1725 1726 1727 1728 1729 1730
#ifdef WITH_WSREP
  if (wsrep_inited == 1)
  {
    wsrep_deinit(true);
  }
#endif
unknown's avatar
unknown committed
1731
  /* All threads has now been aborted */
1732 1733
  DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)",
                      uint32_t(thread_count)));
1734

1735
  while (thread_count)
1736
    my_sleep(1000);
unknown's avatar
unknown committed
1737 1738 1739 1740 1741

  DBUG_PRINT("quit",("close_connections thread"));
  DBUG_VOID_RETURN;
}

1742

1743
#ifdef HAVE_CLOSE_SERVER_SOCK
1744
static void close_socket(MYSQL_SOCKET sock, const char *info)
unknown's avatar
unknown committed
1745
{
1746 1747
  DBUG_ENTER("close_socket");

1748
  if (mysql_socket_getfd(sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1749
  {
1750
    DBUG_PRINT("info", ("calling shutdown on %s socket", info));
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1751
    (void) mysql_socket_shutdown(sock, SHUT_RDWR);
unknown's avatar
unknown committed
1752
  }
1753 1754
  DBUG_VOID_RETURN;
}
1755
#endif
1756 1757


1758
static void close_server_sock()
unknown's avatar
unknown committed
1759
{
1760
#ifdef HAVE_CLOSE_SERVER_SOCK
unknown's avatar
unknown committed
1761
  DBUG_ENTER("close_server_sock");
1762 1763 1764 1765 1766

  close_socket(base_ip_sock, "TCP/IP");
  close_socket(extra_ip_sock, "TCP/IP");
  close_socket(unix_sock, "unix/IP");

1767
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
Konstantin Osipov's avatar
Konstantin Osipov committed
1768
    (void) unlink(mysqld_unix_port);
1769
  base_ip_sock= extra_ip_sock= unix_sock= MYSQL_INVALID_SOCKET;
Sergei Golubchik's avatar
Sergei Golubchik committed
1770

unknown's avatar
unknown committed
1771 1772
  DBUG_VOID_RETURN;
#endif
1773
}
unknown's avatar
unknown committed
1774

1775 1776
#endif /*EMBEDDED_LIBRARY*/

1777

1778
extern "C" sig_handler print_signal_warning(int sig)
unknown's avatar
unknown committed
1779
{
unknown's avatar
unknown committed
1780
  if (global_system_variables.log_warnings)
1781
    sql_print_warning("Got signal %d from thread %u", sig,
1782
                      (uint)my_thread_id());
1783
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
1784
  my_sigset(sig,print_signal_warning);		/* int. thread system calls */
unknown's avatar
unknown committed
1785
#endif
1786
#if !defined(__WIN__)
unknown's avatar
unknown committed
1787 1788 1789 1790 1791
  if (sig == SIGALRM)
    alarm(2);					/* reschedule alarm */
#endif
}

unknown's avatar
unknown committed
1792
#ifndef EMBEDDED_LIBRARY
1793
extern "C" void unireg_abort(int exit_code)
unknown's avatar
unknown committed
1794
{
1795
  DBUG_ENTER("unireg_abort");
1796

1797 1798
  if (opt_help)
    usage();
unknown's avatar
unknown committed
1799
  if (exit_code)
Monty's avatar
Monty committed
1800
    sql_print_error("Aborting");
1801 1802
  /* Don't write more notes to the log to not hide error message */
  disable_log_notes= 1;
1803 1804

#ifdef WITH_WSREP
Brave Galera Crew's avatar
Brave Galera Crew committed
1805 1806
  if (WSREP_ON &&
      Wsrep_server_state::instance().state() != wsrep::server_state::s_disconnected)
1807 1808 1809 1810 1811 1812
  {
    /*
      This is an abort situation, we cannot expect to gracefully close all
      wsrep threads here, we can only diconnect from service
    */
    wsrep_close_client_connections(FALSE);
Brave Galera Crew's avatar
Brave Galera Crew committed
1813
    Wsrep_server_state::instance().disconnect();
1814
    WSREP_INFO("Service disconnected.");
1815
    wsrep_close_threads(NULL); /* this won't close all threads */
1816 1817
    sleep(1); /* so give some time to exit for those which can */
    WSREP_INFO("Some threads may fail to exit.");
Brave Galera Crew's avatar
Brave Galera Crew committed
1818 1819 1820
  }
  if (WSREP_ON)
  {
1821
    /* In bootstrap mode we deinitialize wsrep here. */
Brave Galera Crew's avatar
Brave Galera Crew committed
1822 1823 1824 1825
    if (opt_bootstrap || wsrep_recovery)
    {
      if (wsrep_inited) wsrep_deinit(true);
    }
1826 1827 1828
  }
#endif // WITH_WSREP

1829
  clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1830
  DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
1831 1832 1833
  mysqld_exit(exit_code);
}

1834 1835 1836 1837 1838 1839 1840 1841

static void cleanup_tls()
{
  if (THR_THD)
    (void)pthread_key_delete(THR_THD);
}


1842 1843
static void mysqld_exit(int exit_code)
{
1844
  DBUG_ENTER("mysqld_exit");
1845 1846 1847 1848 1849
  /*
    Important note: we wait for the signal thread to end,
    but if a kill -15 signal was sent, the signal thread did
    spawn the kill_server_thread thread, which is running concurrently.
  */
1850
  rpl_deinit_gtid_waiting();
1851
  rpl_deinit_gtid_slave_state();
1852
  wait_for_signal_thread_to_end();
Brave Galera Crew's avatar
Brave Galera Crew committed
1853 1854 1855
#ifdef WITH_WSREP
  wsrep_deinit_server();
#endif /* WITH_WSREP */
1856
  mysql_audit_finalize();
unknown's avatar
unknown committed
1857
  clean_up_mutexes();
1858
  my_end((opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0));
1859
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
1860
  shutdown_performance_schema();        // we do it as late as possible
1861
#endif
1862
  set_malloc_size_cb(NULL);
1863 1864 1865
  if (opt_endinfo && global_status_var.global_memory_used)
    fprintf(stderr, "Warning: Memory not freed: %ld\n",
            (long) global_status_var.global_memory_used);
1866 1867
  if (!opt_debugging && !my_disable_leak_check && exit_code == 0 &&
      debug_assert_on_not_freed_memory)
1868
  {
1869 1870 1871
#ifdef SAFEMALLOC
    sf_report_leaked_memory(0);
#endif
1872
    DBUG_SLOW_ASSERT(global_status_var.global_memory_used == 0);
1873
  }
1874
  cleanup_tls();
1875
  DBUG_LEAVE;
1876
  sd_notify(0, "STATUS=MariaDB server is down");
unknown's avatar
unknown committed
1877 1878
  exit(exit_code); /* purecov: inspected */
}
1879

1880
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1881

1882
static void clean_up(bool print_message)
unknown's avatar
unknown committed
1883 1884 1885 1886
{
  DBUG_PRINT("exit",("clean_up"));
  if (cleanup_done++)
    return; /* purecov: inspected */
unknown's avatar
unknown committed
1887

1888 1889 1890 1891
#ifdef HAVE_REPLICATION
  // We must call end_slave() as clean_up may have been called during startup
  end_slave();
  if (use_slave_mask)
1892
    my_bitmap_free(&slave_error_mask);
1893
#endif
1894
  stop_handle_manager();
1895 1896
  release_ddl_log();

unknown's avatar
unknown committed
1897 1898
  logger.cleanup_base();

1899
  injector::free_instance();
unknown's avatar
unknown committed
1900 1901
  mysql_bin_log.cleanup();

1902
  my_tz_free();
1903
  my_dboptions_cache_free();
1904
  ignore_db_dirs_free();
unknown's avatar
unknown committed
1905
  servers_free(1);
1906
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
1907 1908
  acl_free(1);
  grant_free();
unknown's avatar
unknown committed
1909
#endif
unknown's avatar
unknown committed
1910
  query_cache_destroy();
unknown's avatar
unknown committed
1911
  hostname_cache_free();
1912
  item_func_sleep_free();
unknown's avatar
unknown committed
1913
  lex_free();				/* Free some memory */
1914
  item_create_cleanup();
1915
  tdc_start_shutdown();
1916 1917 1918
#ifdef HAVE_REPLICATION
  semi_sync_master_deinit();
#endif
1919
  plugin_shutdown();
1920
  udf_free();
1921
  ha_end();
unknown's avatar
Merge  
unknown committed
1922 1923
  if (tc_log)
    tc_log->close();
1924
  xid_cache_free();
1925
  tdc_deinit();
Konstantin Osipov's avatar
Konstantin Osipov committed
1926
  mdl_destroy();
1927
  dflt_key_cache= 0;
1928
  key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
1929
  wt_end();
1930
  multi_keycache_free();
1931
  sp_cache_end();
1932
  free_status_vars();
1933
  end_thr_alarm(1);			/* Free allocated memory */
Monty's avatar
Monty committed
1934 1935 1936
#ifndef EMBEDDED_LIBRARY
  end_thr_timer();
#endif
1937
  my_free_open_file_info();
unknown's avatar
unknown committed
1938 1939
  if (defaults_argv)
    free_defaults(defaults_argv);
unknown's avatar
unknown committed
1940
  free_tmpdir(&mysql_tmpdir_list);
1941
  my_bitmap_free(&temp_pool);
unknown's avatar
unknown committed
1942
  free_max_user_conn();
1943 1944 1945 1946
  free_global_user_stats();
  free_global_client_stats();
  free_global_table_stats();
  free_global_index_stats();
Monty's avatar
Monty committed
1947
  delete_dynamic(&all_options);                 // This should be empty
1948
  free_all_rpl_filters();
Monty's avatar
Monty committed
1949
  wsrep_thr_deinit();
1950
  my_uuid_end();
1951
  delete type_handler_data;
unknown's avatar
unknown committed
1952
  delete binlog_filter;
1953
  delete global_rpl_filter;
1954
  end_ssl();
1955
#ifndef EMBEDDED_LIBRARY
1956
  vio_end();
1957
#endif /*!EMBEDDED_LIBRARY*/
1958 1959 1960 1961
#if defined(ENABLED_DEBUG_SYNC)
  /* End the debug sync facility. See debug_sync.cc. */
  debug_sync_end();
#endif /* defined(ENABLED_DEBUG_SYNC) */
unknown's avatar
unknown committed
1962

1963
  delete_pid_file(MYF(0));
1964

1965
  if (print_message && my_default_lc_messages && server_start_time)
1966
    sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
Sergei Golubchik's avatar
Sergei Golubchik committed
1967
  MYSQL_CALLBACK(thread_scheduler, end, ());
1968
  thread_scheduler= 0;
1969
  mysql_library_end();
unknown's avatar
Merge  
unknown committed
1970
  finish_client_errs();
1971 1972
  cleanup_errmsgs();
  free_error_messages();
unknown's avatar
unknown committed
1973
  /* Tell main we are ready */
unknown's avatar
unknown committed
1974
  logger.cleanup_end();
1975
  sys_var_end();
1976
  free_charsets();
1977

1978 1979 1980 1981 1982 1983
  my_free(const_cast<char*>(log_bin_basename));
  my_free(const_cast<char*>(log_bin_index));
#ifndef EMBEDDED_LIBRARY
  my_free(const_cast<char*>(relay_log_basename));
  my_free(const_cast<char*>(relay_log_index));
#endif
1984
  free_list(opt_plugin_load_list_ptr);
1985
  destroy_proxy_protocol_networks();
1986

unknown's avatar
unknown committed
1987 1988 1989 1990
  /*
    The following lines may never be executed as the main thread may have
    killed us
  */
1991
  DBUG_PRINT("quit", ("done with cleanup"));
unknown's avatar
unknown committed
1992 1993 1994
} /* clean_up */


1995 1996
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
1997
/**
1998
  This is mainly needed when running with purify, but it's still nice to
unknown's avatar
unknown committed
1999
  know that all child threads have died when mysqld exits.
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
*/
static void wait_for_signal_thread_to_end()
{
  uint i;
  /*
    Wait up to 10 seconds for signal thread to die. We use this mainly to
    avoid getting warnings that my_thread_end has not been called
  */
  for (i= 0 ; i < 100 && signal_thread_in_use; i++)
  {
2010
    if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) == ESRCH)
2011 2012 2013 2014
      break;
    my_sleep(100);				// Give it time to die
  }
}
2015
#endif /*EMBEDDED_LIBRARY*/
2016

unknown's avatar
unknown committed
2017 2018
static void clean_up_mutexes()
{
2019
  DBUG_ENTER("clean_up_mutexes");
2020
  server_threads.destroy();
Marc Alff's avatar
Marc Alff committed
2021
  mysql_rwlock_destroy(&LOCK_grant);
Michael Widenius's avatar
Michael Widenius committed
2022
  mysql_mutex_destroy(&LOCK_thread_cache);
2023
  mysql_mutex_destroy(&LOCK_start_thread);
Marc Alff's avatar
Marc Alff committed
2024
  mysql_mutex_destroy(&LOCK_status);
2025
  mysql_rwlock_destroy(&LOCK_all_status_vars);
Marc Alff's avatar
Marc Alff committed
2026 2027 2028
  mysql_mutex_destroy(&LOCK_delayed_insert);
  mysql_mutex_destroy(&LOCK_delayed_status);
  mysql_mutex_destroy(&LOCK_delayed_create);
Marc Alff's avatar
Marc Alff committed
2029 2030 2031
  mysql_mutex_destroy(&LOCK_crypt);
  mysql_mutex_destroy(&LOCK_user_conn);
  mysql_mutex_destroy(&LOCK_connection_count);
2032
  mysql_mutex_destroy(&LOCK_thread_id);
Sergei Golubchik's avatar
Sergei Golubchik committed
2033 2034 2035 2036
  mysql_mutex_destroy(&LOCK_stats);
  mysql_mutex_destroy(&LOCK_global_user_client_stats);
  mysql_mutex_destroy(&LOCK_global_table_stats);
  mysql_mutex_destroy(&LOCK_global_index_stats);
2037
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
2038
  mysql_mutex_destroy(&LOCK_des_key_file);
2039
#ifdef HAVE_OPENSSL10
2040
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
2041
    mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
2042
  OPENSSL_free(openssl_stdlocks);
2043
#endif /* HAVE_OPENSSL10 */
Michael Widenius's avatar
Michael Widenius committed
2044
#endif /* HAVE_OPENSSL */
2045
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
2046
  mysql_mutex_destroy(&LOCK_rpl_status);
Michael Widenius's avatar
Michael Widenius committed
2047
#endif /* HAVE_REPLICATION */
Marc Alff's avatar
Marc Alff committed
2048
  mysql_mutex_destroy(&LOCK_active_mi);
2049
  mysql_rwlock_destroy(&LOCK_ssl_refresh);
Marc Alff's avatar
Marc Alff committed
2050 2051 2052
  mysql_rwlock_destroy(&LOCK_sys_init_connect);
  mysql_rwlock_destroy(&LOCK_sys_init_slave);
  mysql_mutex_destroy(&LOCK_global_system_variables);
2053
  mysql_prlock_destroy(&LOCK_system_variables_hash);
Sergei Golubchik's avatar
Sergei Golubchik committed
2054
  mysql_mutex_destroy(&LOCK_short_uuid_generator);
Marc Alff's avatar
Marc Alff committed
2055 2056
  mysql_mutex_destroy(&LOCK_prepared_stmt_count);
  mysql_mutex_destroy(&LOCK_error_messages);
Marc Alff's avatar
Marc Alff committed
2057
  mysql_cond_destroy(&COND_thread_cache);
2058
  mysql_cond_destroy(&COND_start_thread);
Marc Alff's avatar
Marc Alff committed
2059
  mysql_cond_destroy(&COND_flush_thread_cache);
Sergei Golubchik's avatar
Sergei Golubchik committed
2060 2061
  mysql_mutex_destroy(&LOCK_server_started);
  mysql_cond_destroy(&COND_server_started);
Sergei Golubchik's avatar
Sergei Golubchik committed
2062
  mysql_mutex_destroy(&LOCK_prepare_ordered);
2063
  mysql_cond_destroy(&COND_prepare_ordered);
2064
  mysql_mutex_destroy(&LOCK_after_binlog_sync);
Sergei Golubchik's avatar
Sergei Golubchik committed
2065
  mysql_mutex_destroy(&LOCK_commit_ordered);
2066 2067
  mysql_mutex_destroy(&LOCK_slave_background);
  mysql_cond_destroy(&COND_slave_background);
2068 2069 2070
#ifndef EMBEDDED_LIBRARY
  mysql_mutex_destroy(&LOCK_error_log);
#endif
2071
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2072
}
2073 2074


unknown's avatar
unknown committed
2075 2076 2077 2078
/****************************************************************************
** Init IP and UNIX socket
****************************************************************************/

2079
#ifdef EMBEDDED_LIBRARY
2080 2081 2082
void close_connection(THD *thd, uint sql_errno)
{
}
2083
#else
unknown's avatar
unknown committed
2084 2085 2086
static void set_ports()
{
  char	*env;
2087
  if (!mysqld_port && !opt_disable_networking)
unknown's avatar
unknown committed
2088
  {					// Get port if not from commandline
2089
    mysqld_port= MYSQL_PORT;
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101

    /*
      if builder specifically requested a default port, use that
      (even if it coincides with our factory default).
      only if they didn't do we check /etc/services (and, failing
      on that, fall back to the factory default of 3306).
      either default can be overridden by the environment variable
      MYSQL_TCP_PORT, which in turn can be overridden with command
      line options.
    */

#if MYSQL_PORT_DEFAULT == 0
unknown's avatar
unknown committed
2102
    struct  servent *serv_ptr;
2103
    if ((serv_ptr= getservbyname("mysql", "tcp")))
Sergei Golubchik's avatar
Sergei Golubchik committed
2104
      SYSVAR_AUTOSIZE(mysqld_port, ntohs((u_short) serv_ptr->s_port));
2105
#endif
unknown's avatar
unknown committed
2106
    if ((env = getenv("MYSQL_TCP_PORT")))
Sergei Golubchik's avatar
Sergei Golubchik committed
2107 2108
    {
      mysqld_port= (uint) atoi(env);
2109
      set_sys_var_value_origin(&mysqld_port, sys_var::ENV);
Sergei Golubchik's avatar
Sergei Golubchik committed
2110
    }
unknown's avatar
unknown committed
2111
  }
2112
  if (!mysqld_unix_port)
unknown's avatar
unknown committed
2113 2114
  {
#ifdef __WIN__
2115
    mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
unknown's avatar
unknown committed
2116
#else
2117
    mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
unknown's avatar
unknown committed
2118 2119
#endif
    if ((env = getenv("MYSQL_UNIX_PORT")))
Sergei Golubchik's avatar
Sergei Golubchik committed
2120 2121
    {
      mysqld_unix_port= env;
2122
      set_sys_var_value_origin(&mysqld_unix_port, sys_var::ENV);
Sergei Golubchik's avatar
Sergei Golubchik committed
2123
    }
unknown's avatar
unknown committed
2124 2125 2126 2127 2128
  }
}

/* Change to run as another user if started with --user */

2129
static struct passwd *check_user(const char *user)
unknown's avatar
unknown committed
2130
{
2131 2132 2133 2134 2135
  myf flags= 0;
  if (global_system_variables.log_warnings)
    flags|= MY_WME;
  if (!opt_bootstrap && !opt_help)
    flags|= MY_FAE;
unknown's avatar
unknown committed
2136

2137
  struct passwd *tmp_user_info= my_check_user(user, MYF(flags));
unknown's avatar
unknown committed
2138

2139 2140
  if (!tmp_user_info && my_errno==EINVAL && (flags & MY_FAE))
    unireg_abort(1);
2141

unknown's avatar
unknown committed
2142
  return tmp_user_info;
2143
}
2144

2145 2146
static inline void allow_coredumps()
{
2147 2148 2149 2150 2151 2152 2153
#ifdef PR_SET_DUMPABLE
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* inform kernel that process is dumpable */
    (void) prctl(PR_SET_DUMPABLE, 1);
  }
#endif
2154 2155
}

2156

2157
static void set_user(const char *user, struct passwd *user_info_arg)
2158
{
2159 2160 2161 2162 2163 2164
  /*
    We can get a SIGSEGV when calling initgroups() on some systems when NSS
    is configured to use LDAP and the server is statically linked.  We set
    calling_initgroups as a flag to the SIGSEGV handler that is then used to
    output a specific message to help the user resolve this problem.
  */
2165
  calling_initgroups= 1;
2166
  int res= my_set_user(user, user_info_arg, MYF(MY_WME));
2167
  calling_initgroups= 0;
2168
  if (res)
2169
    unireg_abort(1);
2170
  allow_coredumps();
unknown's avatar
unknown committed
2171 2172
}

2173
#if !defined(__WIN__)
2174
static void set_effective_user(struct passwd *user_info_arg)
2175
{
2176 2177
  DBUG_ASSERT(user_info_arg != 0);
  if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
2178
  {
2179
    sql_perror("setregid");
2180
    unireg_abort(1);
unknown's avatar
unknown committed
2181
  }
2182
  if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
2183
  {
2184
    sql_perror("setreuid");
2185 2186
    unireg_abort(1);
  }
2187
  allow_coredumps();
2188
}
2189
#endif
2190

unknown's avatar
unknown committed
2191
/** Change root user if started with @c --chroot . */
unknown's avatar
unknown committed
2192 2193
static void set_root(const char *path)
{
2194
#if !defined(__WIN__)
unknown's avatar
unknown committed
2195 2196 2197 2198 2199
  if (chroot(path) == -1)
  {
    sql_perror("chroot");
    unireg_abort(1);
  }
2200
  my_setwd("/", MYF(0));
unknown's avatar
unknown committed
2201 2202 2203
#endif
}

2204 2205 2206
/**
   Activate usage of a tcp port
*/
2207

2208
static MYSQL_SOCKET activate_tcp_port(uint port)
unknown's avatar
unknown committed
2209
{
Sergei Golubchik's avatar
Sergei Golubchik committed
2210 2211 2212
  struct addrinfo *ai, *a;
  struct addrinfo hints;
  int error;
2213 2214
  int	arg;
  char port_buf[NI_MAXSERV];
2215
  const char *real_bind_addr_str;
2216
  MYSQL_SOCKET ip_sock= MYSQL_INVALID_SOCKET;
2217 2218
  DBUG_ENTER("activate_tcp_port");
  DBUG_PRINT("general",("IP Socket is %d",port));
unknown's avatar
unknown committed
2219

Sergei Golubchik's avatar
Sergei Golubchik committed
2220 2221 2222 2223
  bzero(&hints, sizeof (hints));
  hints.ai_flags= AI_PASSIVE;
  hints.ai_socktype= SOCK_STREAM;
  hints.ai_family= AF_UNSPEC;
2224 2225 2226 2227 2228
  
  if (my_bind_addr_str && strcmp(my_bind_addr_str, "*") == 0)
    real_bind_addr_str= NULL; // windows doesn't seem to support * here
  else
    real_bind_addr_str= my_bind_addr_str;
unknown's avatar
unknown committed
2229

2230
  my_snprintf(port_buf, NI_MAXSERV, "%d", port);
2231
  error= getaddrinfo(real_bind_addr_str, port_buf, &hints, &ai);
2232
  if (unlikely(error != 0))
unknown's avatar
unknown committed
2233
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2234
    DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error));
2235 2236

    sql_print_error("%s: %s", ER_DEFAULT(ER_IPSOCK_ERROR), gai_strerror(error));
Sergei Golubchik's avatar
Sergei Golubchik committed
2237 2238
    unireg_abort(1);				/* purecov: tested */
  }
2239

2240 2241 2242 2243 2244
  /*
    special case: for wildcard addresses prefer ipv6 over ipv4,
    because we later switch off IPV6_V6ONLY, so ipv6 wildcard
    addresses will work for ipv4 too
  */
2245
  if (!real_bind_addr_str && ai->ai_family == AF_INET && ai->ai_next
2246 2247 2248 2249 2250 2251 2252 2253
      && ai->ai_next->ai_family == AF_INET6)
  {
    a= ai;
    ai= ai->ai_next;
    a->ai_next= ai->ai_next;
    ai->ai_next= a;
  }

Sergei Golubchik's avatar
Sergei Golubchik committed
2254 2255
  for (a= ai; a != NULL; a= a->ai_next)
  {
2256 2257
    ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family,
                                 a->ai_socktype, a->ai_protocol);
2258

Sergei Golubchik's avatar
Sergei Golubchik committed
2259
    char ip_addr[INET6_ADDRSTRLEN];
2260 2261 2262 2263 2264 2265
    if (vio_get_normalized_ip_string(a->ai_addr, a->ai_addrlen,
                                     ip_addr, sizeof (ip_addr)))
    {
      ip_addr[0]= 0;
    }

Sergei Golubchik's avatar
Sergei Golubchik committed
2266
    if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2267
    {
2268 2269 2270 2271 2272
      sql_print_message_func func= real_bind_addr_str ? sql_print_error
                                                      : sql_print_warning;
      func("Failed to create a socket for %s '%s': errno: %d.",
           (a->ai_family == AF_INET) ? "IPv4" : "IPv6",
           (const char *) ip_addr, (int) socket_errno);
2273 2274 2275
    }
    else 
    {
2276
      server_socket_ai_family= a->ai_family;
2277 2278
      sql_print_information("Server socket created on IP: '%s'.",
                          (const char *) ip_addr);
Sergei Golubchik's avatar
Sergei Golubchik committed
2279
      break;
2280
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2281
  }
2282

2283
  if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2284 2285
  {
    DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
Sergei Golubchik's avatar
Sergei Golubchik committed
2286
    sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
2287 2288
    unireg_abort(1);				/* purecov: tested */
  }
2289

2290 2291
  mysql_socket_set_thread_owner(ip_sock);

2292
#ifndef __WIN__
2293 2294 2295 2296
  /*
    We should not use SO_REUSEADDR on windows as this would enable a
    user to open two mysqld servers with the same TCP/IP port.
  */
Sergei Golubchik's avatar
Sergei Golubchik committed
2297
  arg= 1;
2298 2299
  (void) mysql_socket_setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
                                 sizeof(arg));
unknown's avatar
unknown committed
2300
#endif /* __WIN__ */
2301 2302

#ifdef IPV6_V6ONLY
Sergei Golubchik's avatar
Sergei Golubchik committed
2303 2304 2305 2306
   /*
     For interoperability with older clients, IPv6 socket should
     listen on both IPv6 and IPv4 wildcard addresses.
     Turn off IPV6_V6ONLY option.
2307

Sergei Golubchik's avatar
Sergei Golubchik committed
2308 2309 2310 2311 2312 2313 2314
     NOTE: this will work starting from Windows Vista only.
     On Windows XP dual stack is not available, so it will not
     listen on the corresponding IPv4-address.
   */
  if (a->ai_family == AF_INET6)
  {
    arg= 0;
2315 2316
    (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
                                   (char*)&arg, sizeof(arg));
Sergei Golubchik's avatar
Sergei Golubchik committed
2317
  }
2318
#endif
2319 2320 2321 2322 2323 2324

#ifdef IP_FREEBIND
  arg= 1;
  (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IP, IP_FREEBIND, (char*) &arg,
                                 sizeof(arg));
#endif
2325 2326 2327 2328 2329 2330 2331 2332
  /*
    Sometimes the port is not released fast enough when stopping and
    restarting the server. This happens quite often with the test suite
    on busy Linux systems. Retry to bind the address at these intervals:
    Sleep intervals: 1, 2, 4,  6,  9, 13, 17, 22, ...
    Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
    Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
  */
2333 2334
  int ret;
  uint waited, retry, this_wait;
2335 2336
  for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
  {
2337
    if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
2338 2339 2340
        (socket_errno != SOCKET_EADDRINUSE) ||
        (waited >= mysqld_port_timeout))
      break;
2341
    sql_print_information("Retrying bind on TCP/IP port %u", port);
2342 2343
    this_wait= retry * retry / 3 + 1;
    sleep(this_wait);
unknown's avatar
unknown committed
2344
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
2345
  freeaddrinfo(ai);
2346 2347
  if (ret < 0)
  {
2348 2349 2350 2351
    char buff[100];
    sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
            (int) socket_errno);
    sql_perror(buff);
2352 2353 2354 2355
    sql_print_error("Do you already have another mysqld server running on "
                    "port: %u ?", port);
    unireg_abort(1);
  }
2356
  if (mysql_socket_listen(ip_sock,(int) back_log) < 0)
2357 2358 2359 2360 2361 2362
  {
    sql_perror("Can't start server: listen() on TCP/IP port");
    sql_print_error("listen() on TCP/IP failed with error %d",
                    socket_errno);
    unireg_abort(1);
  }
2363 2364 2365 2366

#ifdef FD_CLOEXEC
  (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC);
#endif
2367

2368 2369
  DBUG_RETURN(ip_sock);
}
2370

2371 2372 2373 2374
static void network_init(void)
{
#ifdef HAVE_SYS_UN_H
  struct sockaddr_un	UNIXaddr;
2375
  int	arg;
2376
#endif
unknown's avatar
unknown committed
2377
  DBUG_ENTER("network_init");
unknown's avatar
unknown committed
2378

Sergei Golubchik's avatar
Sergei Golubchik committed
2379
  if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
unknown's avatar
unknown committed
2380 2381
    unireg_abort(1);			/* purecov: inspected */

2382
  if (init_proxy_protocol_networks(my_proxy_protocol_networks))
2383 2384
    unireg_abort(1);

unknown's avatar
unknown committed
2385 2386
  set_ports();

Sergei Golubchik's avatar
Sergei Golubchik committed
2387
  if (report_port == 0)
unknown's avatar
unknown committed
2388
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2389
    SYSVAR_AUTOSIZE(report_port, mysqld_port);
unknown's avatar
unknown committed
2390
  }
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
2391 2392 2393
#ifndef DBUG_OFF
  if (!opt_disable_networking)
    DBUG_ASSERT(report_port != 0);
2394
#endif
2395
  if (!opt_disable_networking && !opt_bootstrap)
unknown's avatar
unknown committed
2396
  {
2397 2398 2399 2400
    if (mysqld_port)
      base_ip_sock= activate_tcp_port(mysqld_port);
    if (mysqld_extra_port)
      extra_ip_sock= activate_tcp_port(mysqld_extra_port);
unknown's avatar
unknown committed
2401
  }
2402

2403
#if defined(HAVE_SYS_UN_H)
unknown's avatar
unknown committed
2404 2405 2406
  /*
  ** Create the UNIX socket
  */
2407
  if (mysqld_unix_port[0] && !opt_bootstrap)
unknown's avatar
unknown committed
2408
  {
2409
    size_t port_len;
2410
    DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
unknown's avatar
unknown committed
2411

2412
    if ((port_len= strlen(mysqld_unix_port)) > sizeof(UNIXaddr.sun_path) - 1)
unknown's avatar
unknown committed
2413
    {
2414
      sql_print_error("The socket file path is too long (> %u): %s",
unknown's avatar
unknown committed
2415
                      (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unknown's avatar
unknown committed
2416 2417
      unireg_abort(1);
    }
2418 2419
    unix_sock= mysql_socket_socket(key_socket_unix, AF_UNIX, SOCK_STREAM, 0);
    if (mysql_socket_getfd(unix_sock) < 0)
unknown's avatar
unknown committed
2420 2421 2422 2423
    {
      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
      unireg_abort(1);				/* purecov: inspected */
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2424 2425 2426

    mysql_socket_set_thread_owner(unix_sock);

unknown's avatar
unknown committed
2427 2428
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
2429
    strmov(UNIXaddr.sun_path, mysqld_unix_port);
2430 2431 2432
#if defined(__linux__)
    /* Abstract socket */
    if (mysqld_unix_port[0] == '@')
2433
    {
2434
      UNIXaddr.sun_path[0]= '\0';
2435 2436
      port_len+= offsetof(struct sockaddr_un, sun_path);
    }
2437 2438
    else
#endif
2439
    {
2440
      (void) unlink(mysqld_unix_port);
2441 2442
      port_len= sizeof(UNIXaddr);
    }
2443
    arg= 1;
2444 2445
    (void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,
                                   (char*)&arg, sizeof(arg));
unknown's avatar
unknown committed
2446
    umask(0);
2447 2448
    if (mysql_socket_bind(unix_sock,
                          reinterpret_cast<struct sockaddr *>(&UNIXaddr),
2449
                          port_len) < 0)
unknown's avatar
unknown committed
2450 2451
    {
      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
2452
      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
unknown's avatar
unknown committed
2453 2454 2455 2456
      unireg_abort(1);					/* purecov: tested */
    }
    umask(((~my_umask) & 0666));
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
2457
    (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
unknown's avatar
unknown committed
2458
#endif
2459
    if (mysql_socket_listen(unix_sock,(int) back_log) < 0)
2460
      sql_print_warning("listen() on Unix socket failed with error %d",
unknown's avatar
unknown committed
2461
		      socket_errno);
2462 2463 2464
#ifdef FD_CLOEXEC
    (void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC);
#endif
unknown's avatar
unknown committed
2465 2466 2467 2468 2469 2470
  }
#endif
  DBUG_PRINT("info",("server started"));
  DBUG_VOID_RETURN;
}

Sergei Golubchik's avatar
Sergei Golubchik committed
2471

unknown's avatar
unknown committed
2472 2473
/**
  Close a connection.
2474

2475 2476
  @param thd        Thread handle.
  @param sql_errno  The error code to send before disconnect.
2477

unknown's avatar
unknown committed
2478
  @note
2479 2480
    For the connection that is doing shutdown, this is called twice
*/
2481

2482
void close_connection(THD *thd, uint sql_errno)
unknown's avatar
unknown committed
2483 2484
{
  DBUG_ENTER("close_connection");
2485 2486 2487 2488

  if (sql_errno)
    net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL);

Sergei Golubchik's avatar
Sergei Golubchik committed
2489 2490
  thd->print_aborted_warning(3, sql_errno ? ER_DEFAULT(sql_errno)
                                          : "CLOSE_CONNECTION");
2491

2492 2493 2494 2495
  thd->disconnect();

  MYSQL_CONNECTION_DONE((int) sql_errno, thd->thread_id);

2496 2497 2498 2499
  if (MYSQL_CONNECTION_DONE_ENABLED())
  {
    sleep(0); /* Workaround to avoid tailcall optimisation */
  }
2500
  mysql_audit_notify_connection_disconnect(thd, sql_errno);
unknown's avatar
unknown committed
2501 2502
  DBUG_VOID_RETURN;
}
2503

unknown's avatar
unknown committed
2504

2505
/** Called when mysqld is aborted with ^C */
unknown's avatar
unknown committed
2506
/* ARGSUSED */
2507
extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
unknown's avatar
unknown committed
2508
{
2509
  DBUG_ENTER("end_mysqld_signal");
2510
  /* Don't kill if signal thread is not running */
2511
  if (signal_thread_in_use)
2512
    break_connect_loop();                         // Take down mysqld nicely
unknown's avatar
unknown committed
2513 2514
  DBUG_VOID_RETURN;				/* purecov: deadcode */
}
2515
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
2516

2517 2518 2519 2520 2521 2522 2523
/*
  Decrease number of connections

  SYNOPSIS
    dec_connection_count()
*/

2524
void dec_connection_count(scheduler_functions *scheduler)
2525 2526
{
  mysql_mutex_lock(&LOCK_connection_count);
2527
  (*scheduler->connection_count)--;
2528 2529 2530 2531
  mysql_mutex_unlock(&LOCK_connection_count);
}


unknown's avatar
unknown committed
2532
/*
Monty's avatar
Monty committed
2533
  Unlink thd from global list of available connections
unknown's avatar
unknown committed
2534 2535 2536 2537 2538 2539 2540

  SYNOPSIS
    unlink_thd()
    thd		 Thread handler
*/

void unlink_thd(THD *thd)
unknown's avatar
unknown committed
2541
{
unknown's avatar
unknown committed
2542
  DBUG_ENTER("unlink_thd");
2543
  DBUG_PRINT("enter", ("thd: %p", thd));
2544

2545 2546
  thd->cleanup();
  thd->add_status_to_global();
2547
  server_threads.erase(thd);
2548

Brave Galera Crew's avatar
Brave Galera Crew committed
2549
#ifdef WITH_WSREP
2550
  /*
2551 2552
    Do not decrement when its wsrep system thread. wsrep_applier is set for
    applier as well as rollbacker threads.
2553
  */
Brave Galera Crew's avatar
Brave Galera Crew committed
2554 2555 2556
  if (!thd->wsrep_applier)
#endif /* WITH_WSREP */
  dec_connection_count(thd->scheduler);
2557

Monty's avatar
Monty committed
2558
  thd->free_connection();
Michael Widenius's avatar
Michael Widenius committed
2559

unknown's avatar
unknown committed
2560 2561 2562
  DBUG_VOID_RETURN;
}

2563

unknown's avatar
unknown committed
2564 2565 2566 2567 2568
/*
  Store thread in cache for reuse by new connections

  SYNOPSIS
    cache_thread()
Monty's avatar
Monty committed
2569
    thd		 Thread handler
unknown's avatar
unknown committed
2570 2571

  NOTES
Michael Widenius's avatar
Michael Widenius committed
2572
    LOCK_thread_cache is used to protect the cache variables
unknown's avatar
unknown committed
2573 2574 2575 2576 2577 2578 2579 2580

  RETURN
    0  Thread was not put in cache
    1  Thread is to be reused by new connection.
       (ie, caller should return, not abort with pthread_exit())
*/


Monty's avatar
Monty committed
2581
static bool cache_thread(THD *thd)
unknown's avatar
unknown committed
2582
{
2583
  struct timespec abstime;
Michael Widenius's avatar
Michael Widenius committed
2584
  DBUG_ENTER("cache_thread");
Monty's avatar
Monty committed
2585
  DBUG_ASSERT(thd);
Michael Widenius's avatar
Michael Widenius committed
2586

Michael Widenius's avatar
Michael Widenius committed
2587
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2588
  if (cached_thread_count < thread_cache_size &&
2589
      ! abort_loop && !kill_cached_threads)
unknown's avatar
unknown committed
2590 2591
  {
    /* Don't kill the thread, just put it in cache for reuse */
unknown's avatar
unknown committed
2592
    DBUG_PRINT("info", ("Adding thread to cache"));
unknown's avatar
unknown committed
2593
    cached_thread_count++;
2594 2595 2596 2597 2598

    /*
      Delete the instrumentation for the job that just completed,
      before parking this pthread in the cache (blocked on COND_thread_cache).
    */
2599
    PSI_CALL_delete_current_thread();
2600

2601 2602 2603 2604 2605
#ifndef DBUG_OFF
    while (_db_is_pushed_())
      _db_pop_();
#endif

2606
    set_timespec(abstime, THREAD_CACHE_TIMEOUT);
unknown's avatar
unknown committed
2607
    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620
    {
      int error= mysql_cond_timedwait(&COND_thread_cache, &LOCK_thread_cache,
                                       &abstime);
      if (error == ETIMEDOUT || error == ETIME)
      {
        /*
          If timeout, end thread.
          If a new thread is requested (wake_thread is set), we will handle
          the call, even if we got a timeout (as we are already awake and free)
        */
        break;
      }
    }
unknown's avatar
unknown committed
2621 2622
    cached_thread_count--;
    if (kill_cached_threads)
Marc Alff's avatar
Marc Alff committed
2623
      mysql_cond_signal(&COND_flush_thread_cache);
unknown's avatar
unknown committed
2624 2625
    if (wake_thread)
    {
2626 2627
      CONNECT *connect;

unknown's avatar
unknown committed
2628
      wake_thread--;
2629
      connect= thread_cache.get();
Michael Widenius's avatar
Michael Widenius committed
2630 2631
      mysql_mutex_unlock(&LOCK_thread_cache);

Monty's avatar
Monty committed
2632
      if (!(connect->create_thd(thd)))
2633 2634 2635 2636 2637 2638 2639
      {
        /* Out of resources. Free thread to get more resources */
        connect->close_and_delete();
        DBUG_RETURN(0);
      }
      delete connect;

Monty's avatar
Monty committed
2640 2641 2642 2643 2644
      /*
        We have to call store_globals to update mysys_var->id and lock_info
        with the new thread_id
      */
      thd->store_globals();
2645 2646 2647 2648 2649

      /*
        Create new instrumentation for the new THD job,
        and attach it to this running pthread.
      */
2650
      PSI_thread *psi= PSI_CALL_new_thread(key_thread_one_connection,
2651
                                                   thd, thd->thread_id);
2652
      PSI_CALL_set_thread(psi);
2653

Monty's avatar
Monty committed
2654
      /* reset abort flag for the thread */
2655
      thd->mysys_var->abort= 0;
2656
      thd->thr_create_utime= microsecond_interval_timer();
2657
      thd->start_utime= thd->thr_create_utime;
Michael Widenius's avatar
Michael Widenius committed
2658

2659
      server_threads.insert(thd);
Michael Widenius's avatar
Michael Widenius committed
2660
      DBUG_RETURN(1);
unknown's avatar
unknown committed
2661 2662
    }
  }
Michael Widenius's avatar
Michael Widenius committed
2663
  mysql_mutex_unlock(&LOCK_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2664
  DBUG_RETURN(0);
unknown's avatar
unknown committed
2665 2666 2667 2668 2669 2670 2671 2672
}


/*
  End thread for the current connection

  SYNOPSIS
    one_thread_per_connection_end()
2673
    thd		  Thread handler. This may be null if we run out of resources.
unknown's avatar
unknown committed
2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689
    put_in_cache  Store thread in cache, if there is room in it
                  Normally this is true in all cases except when we got
                  out of resources initializing the current thread

  NOTES
    If thread is cached, we will wait until thread is scheduled to be
    reused and then we will return.
    If thread is not cached, we end the thread.

  RETURN
    0    Signal to handle_one_connection to reuse connection
*/

bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
{
  DBUG_ENTER("one_thread_per_connection_end");
2690

2691
  if (thd)
Monty's avatar
Monty committed
2692 2693
  {
    const bool wsrep_applier= IF_WSREP(thd->wsrep_applier, false);
2694

Monty's avatar
Monty committed
2695 2696 2697 2698 2699
    unlink_thd(thd);
    if (!wsrep_applier && put_in_cache && cache_thread(thd))
      DBUG_RETURN(0);                             // Thread is reused
    delete thd;
  }
unknown's avatar
unknown committed
2700

2701
  DBUG_PRINT("info", ("killing thread"));
2702
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2703
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
2704 2705
  ERR_remove_state(0);
#endif
2706
  my_thread_end();
unknown's avatar
unknown committed
2707 2708

  pthread_exit(0);
2709
  return 0;                                     // Avoid compiler warnings
unknown's avatar
unknown committed
2710 2711 2712 2713 2714
}


void flush_thread_cache()
{
Michael Widenius's avatar
Michael Widenius committed
2715 2716
  DBUG_ENTER("flush_thread_cache");
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2717 2718 2719
  kill_cached_threads++;
  while (cached_thread_count)
  {
Marc Alff's avatar
Marc Alff committed
2720
    mysql_cond_broadcast(&COND_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2721
    mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache);
unknown's avatar
unknown committed
2722 2723
  }
  kill_cached_threads--;
Michael Widenius's avatar
Michael Widenius committed
2724 2725
  mysql_mutex_unlock(&LOCK_thread_cache);
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2726 2727 2728 2729
}


/******************************************************************************
2730 2731 2732
  Setup a signal thread with handles all signals.
  Because Linux doesn't support schemas use a mutex to check that
  the signal thread is ready before continuing
unknown's avatar
unknown committed
2733 2734
******************************************************************************/

2735
#if defined(__WIN__)
2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749


/*
  On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
  with graceful shutdown.
  Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
  provides possibility to pass the exception to just-in-time debugger, collect
  dumps and potentially also the exception and thread context used to output
  callstack.
*/

static BOOL WINAPI console_event_handler( DWORD type ) 
{
  DBUG_ENTER("console_event_handler");
unknown's avatar
unknown committed
2750
#ifndef EMBEDDED_LIBRARY
2751 2752 2753 2754 2755 2756 2757 2758
  if(type == CTRL_C_EVENT)
  {
     /*
       Do not shutdown before startup is finished and shutdown
       thread is initialized. Otherwise there is a race condition 
       between main thread doing initialization and CTRL-C thread doing
       cleanup, which can result into crash.
     */
2759
#ifndef EMBEDDED_LIBRARY
2760
     if(hEventShutdown)
2761
       break_connect_loop();
2762
     else
2763
#endif
2764 2765 2766
       sql_print_warning("CTRL-C ignored during startup");
     DBUG_RETURN(TRUE);
  }
unknown's avatar
unknown committed
2767
#endif
2768 2769 2770 2771 2772 2773 2774 2775 2776
  DBUG_RETURN(FALSE);
}




#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
/*
2777 2778
  Wait for debugger to attach and break into debugger. If debugger is
  not attached, resume after timeout.
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828
*/
static void wait_for_debugger(int timeout_sec)
{
   if(!IsDebuggerPresent())
   {
     int i;
     printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
     fflush(stdout);
     for(i= 0; i < timeout_sec; i++)
     {
       Sleep(1000);
       if(IsDebuggerPresent())
       {
         /* Break into debugger */
         __debugbreak();
         return;
       }
     }
     printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),
       timeout_sec);
     fflush(stdout);
   }
}
#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */

LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
{
   static BOOL first_time= TRUE;
   if(!first_time)
   {
     /*
       This routine can be called twice, typically
       when detaching in JIT debugger.
       Return EXCEPTION_EXECUTE_HANDLER to terminate process.
     */
     return EXCEPTION_EXECUTE_HANDLER;
   }
   first_time= FALSE;
#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
   /*
    Unfortunately there is no clean way to debug unhandled exception filters,
    as debugger does not stop there(also documented in MSDN) 
    To overcome, one could put a MessageBox, but this will not work in service.
    Better solution is to print error message and sleep some minutes 
    until debugger is attached
  */
  wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
  __try
  {
2829
    my_set_exception_pointers(ex_pointers);
2830
    handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848
  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
    DWORD written;
    const char msg[] = "Got exception in exception handler!\n";
    WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1, 
      &written,NULL);
  }
  /*
    Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
    (drwtsn32 or vsjitdebugger) possibility to attach,
    if JIT debugger is configured.
    Windows Error reporting might generate a dump here.
  */
  return EXCEPTION_CONTINUE_SEARCH;
}


2849
void init_signals(void)
unknown's avatar
unknown committed
2850
{
2851 2852
  if(opt_console)
    SetConsoleCtrlHandler(console_event_handler,TRUE);
2853

2854
    /* Avoid MessageBox()es*/
2855 2856 2857 2858 2859 2860
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2861 2862 2863 2864 2865 2866 2867 2868

   /*
     Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
     because it would prevent JIT debugger and Windows error reporting
     from working. We need WER or JIT-debugging, since our own unhandled
     exception filter is not guaranteed to work in all situation
     (like heap corruption or stack overflow)
   */
2869 2870
  SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
                               | SEM_NOOPENFILEERRORBOX);
2871
  SetUnhandledExceptionFilter(my_unhandler_exception_filter);
unknown's avatar
unknown committed
2872 2873
}

unknown's avatar
unknown committed
2874

2875
static void start_signal_handler(void)
2876
{
2877
#ifndef EMBEDDED_LIBRARY
2878 2879 2880
  // Save vm id of this process
  if (!opt_bootstrap)
    create_pid_file();
2881
#endif /* EMBEDDED_LIBRARY */
2882
}
unknown's avatar
unknown committed
2883

unknown's avatar
unknown committed
2884

unknown's avatar
unknown committed
2885 2886
static void check_data_home(const char *path)
{}
2887

2888
#endif /* __WIN__ */
unknown's avatar
unknown committed
2889

unknown's avatar
unknown committed
2890 2891 2892 2893 2894 2895 2896 2897 2898

#if BACKTRACE_DEMANGLE
#include <cxxabi.h>
extern "C" char *my_demangle(const char *mangled_name, int *status)
{
  return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
}
#endif

2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968

/*
  pthread_attr_setstacksize() without so much platform-dependency

  Return: The actual stack size if possible.
*/

#ifndef EMBEDDED_LIBRARY
static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize)
{
  size_t guard_size __attribute__((unused))= 0;

#if defined(__ia64__) || defined(__ia64)
  /*
    On IA64, half of the requested stack size is used for "normal stack"
    and half for "register stack".  The space measured by check_stack_overrun
    is the "normal stack", so double the request to make sure we have the
    caller-expected amount of normal stack.

    NOTE: there is no guarantee that the register stack can't grow faster
    than normal stack, so it's very unclear that we won't dump core due to
    stack overrun despite check_stack_overrun's efforts.  Experimentation
    shows that in the execution_constants test, the register stack grows
    less than half as fast as normal stack, but perhaps other scenarios are
    less forgiving.  If it turns out that more space is needed for the
    register stack, that could be forced (rather inefficiently) by using a
    multiplier higher than 2 here.
  */
  stacksize *= 2;
#endif

  /*
    On many machines, the "guard space" is subtracted from the requested
    stack size, and that space is quite large on some platforms.  So add
    it to our request, if we can find out what it is.
  */
#ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE
  if (pthread_attr_getguardsize(attr, &guard_size))
    guard_size = 0;		/* if can't find it out, treat as 0 */
#endif

  pthread_attr_setstacksize(attr, stacksize + guard_size);

  /* Retrieve actual stack size if possible */
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
  {
    size_t real_stack_size= 0;
    /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */
    if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 &&
	real_stack_size > guard_size)
    {
      real_stack_size -= guard_size;
      if (real_stack_size < stacksize)
      {
	if (global_system_variables.log_warnings)
          sql_print_warning("Asked for %zu thread stack, but got %zu",
                            stacksize, real_stack_size);
	stacksize= real_stack_size;
      }
    }
  }
#endif /* !EMBEDDED_LIBRARY */

#if defined(__ia64__) || defined(__ia64)
  stacksize /= 2;
#endif
  return stacksize;
}
#endif

2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982
#ifdef DBUG_ASSERT_AS_PRINTF
extern "C" void
mariadb_dbug_assert_failed(const char *assert_expr, const char *file,
                           unsigned long line)
{
  fprintf(stderr, "Warning: assertion failed: %s at %s line %lu\n",
          assert_expr, file, line);
  if (opt_stack_trace)
  {
    fprintf(stderr, "Attempting backtrace to find out the reason for the assert:\n");
    my_print_stacktrace(NULL, (ulong) my_thread_stack_size, 1);
  }
}
#endif /* DBUG_ASSERT_AS_PRINT */
2983

2984
#if !defined(__WIN__)
unknown's avatar
unknown committed
2985 2986
#ifndef SA_RESETHAND
#define SA_RESETHAND 0
2987
#endif /* SA_RESETHAND */
unknown's avatar
unknown committed
2988 2989
#ifndef SA_NODEFER
#define SA_NODEFER 0
2990
#endif /* SA_NODEFER */
2991

2992 2993
#ifndef EMBEDDED_LIBRARY

2994
void init_signals(void)
unknown's avatar
unknown committed
2995 2996
{
  sigset_t set;
2997
  struct sigaction sa;
unknown's avatar
unknown committed
2998 2999
  DBUG_ENTER("init_signals");

3000
  my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
unknown's avatar
unknown committed
3001

Michael Widenius's avatar
Michael Widenius committed
3002
  if (opt_stack_trace || (test_flags & TEST_CORE_ON_SIGNAL))
unknown's avatar
unknown committed
3003
  {
unknown's avatar
unknown committed
3004 3005 3006 3007
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
    sigemptyset(&sa.sa_mask);
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);

3008
    my_init_stacktrace();
unknown's avatar
unknown committed
3009
#if defined(__amiga__)
3010
    sa.sa_handler=(void(*)())handle_fatal_signal;
unknown's avatar
unknown committed
3011
#else
3012
    sa.sa_handler=handle_fatal_signal;
unknown's avatar
unknown committed
3013
#endif
unknown's avatar
unknown committed
3014
    sigaction(SIGSEGV, &sa, NULL);
3015
    sigaction(SIGABRT, &sa, NULL);
unknown's avatar
unknown committed
3016
#ifdef SIGBUS
unknown's avatar
unknown committed
3017
    sigaction(SIGBUS, &sa, NULL);
unknown's avatar
unknown committed
3018
#endif
unknown's avatar
unknown committed
3019
    sigaction(SIGILL, &sa, NULL);
3020
    sigaction(SIGFPE, &sa, NULL);
unknown's avatar
unknown committed
3021
  }
3022 3023 3024 3025 3026

#ifdef HAVE_GETRLIMIT
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* Change limits so that we will get a core file */
3027
    STRUCT_RLIMIT rl;
3028
    rl.rlim_cur = rl.rlim_max = (rlim_t) RLIM_INFINITY;
unknown's avatar
unknown committed
3029
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
3030
      sql_print_warning("setrlimit could not change the size of core files to 'infinity';  We may not be able to generate a core file on signals");
3031 3032
  }
#endif
unknown's avatar
unknown committed
3033
  (void) sigemptyset(&set);
3034
  my_sigset(SIGPIPE,SIG_IGN);
unknown's avatar
unknown committed
3035
  sigaddset(&set,SIGPIPE);
3036
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3037 3038
  sigaddset(&set,SIGQUIT);
  sigaddset(&set,SIGHUP);
3039 3040
#endif
  sigaddset(&set,SIGTERM);
3041 3042

  /* Fix signals if blocked by parents (can happen on Mac OS X) */
unknown's avatar
unknown committed
3043
  sigemptyset(&sa.sa_mask);
3044 3045 3046 3047 3048 3049
  sa.sa_flags = 0;
  sa.sa_handler = print_signal_warning;
  sigaction(SIGTERM, &sa, (struct sigaction*) 0);
  sa.sa_flags = 0;
  sa.sa_handler = print_signal_warning;
  sigaction(SIGHUP, &sa, (struct sigaction*) 0);
3050 3051
  if (thd_lib_detected != THD_LIB_LT)
    sigaddset(&set,THR_SERVER_ALARM);
3052
  if (test_flags & TEST_SIGINT)
3053
  {
3054 3055
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    my_sigset(SIGINT, end_mysqld_signal);
unknown's avatar
unknown committed
3056
    sigdelset(&set, SIGINT);
3057
  }
3058
  else
3059
  {
3060
    sigaddset(&set,SIGINT);
3061 3062 3063 3064
#ifdef SIGTSTP
    sigaddset(&set,SIGTSTP);
#endif
  }
unknown's avatar
unknown committed
3065

3066 3067
  sigprocmask(SIG_SETMASK,&set,NULL);
  pthread_sigmask(SIG_SETMASK,&set,NULL);
3068 3069 3070 3071 3072 3073 3074 3075 3076
  DBUG_VOID_RETURN;
}


static void start_signal_handler(void)
{
  int error;
  pthread_attr_t thr_attr;
  DBUG_ENTER("start_signal_handler");
unknown's avatar
unknown committed
3077 3078 3079 3080

  (void) pthread_attr_init(&thr_attr);
  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
  (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
3081
  (void) my_setstacksize(&thr_attr,my_thread_stack_size);
unknown's avatar
unknown committed
3082

3083
  mysql_mutex_lock(&LOCK_start_thread);
3084 3085 3086
  if (unlikely((error= mysql_thread_create(key_thread_signal_hand,
                                           &signal_thread, &thr_attr,
                                           signal_hand, 0))))
unknown's avatar
unknown committed
3087 3088 3089 3090 3091
  {
    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
		    error,errno);
    exit(1);
  }
3092 3093
  mysql_cond_wait(&COND_start_thread, &LOCK_start_thread);
  mysql_mutex_unlock(&LOCK_start_thread);
unknown's avatar
unknown committed
3094 3095 3096 3097 3098 3099

  (void) pthread_attr_destroy(&thr_attr);
  DBUG_VOID_RETURN;
}


3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111
#if defined(USE_ONE_SIGNAL_HAND)
pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
{
  my_thread_init();				// Initialize new thread
  break_connect_loop();
  my_thread_end();
  pthread_exit(0);
  return 0;
}
#endif


unknown's avatar
unknown committed
3112
/** This threads handles all signals and alarms. */
unknown's avatar
unknown committed
3113
/* ARGSUSED */
3114
pthread_handler_t signal_hand(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
3115 3116 3117 3118 3119
{
  sigset_t set;
  int sig;
  my_thread_init();				// Init new thread
  DBUG_ENTER("signal_hand");
unknown's avatar
unknown committed
3120 3121
  signal_thread_in_use= 1;

unknown's avatar
unknown committed
3122 3123
  /*
    Setup alarm handler
3124 3125
    This should actually be '+ max_number_of_slaves' instead of +10,
    but the +10 should be quite safe.
unknown's avatar
unknown committed
3126
  */
Sergei Golubchik's avatar
Sergei Golubchik committed
3127
  init_thr_alarm(thread_scheduler->max_threads + extra_max_connections +
3128
		 global_system_variables.max_insert_delayed_threads + 10);
3129
  if (test_flags & TEST_SIGINT)
3130
  {
3131 3132 3133
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    (void) sigemptyset(&set);
    (void) sigaddset(&set,SIGINT);
3134 3135
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
  }
unknown's avatar
unknown committed
3136 3137 3138 3139
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND
  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
#endif
3140
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3141 3142
  (void) sigaddset(&set,SIGQUIT);
  (void) sigaddset(&set,SIGHUP);
3143 3144
#endif
  (void) sigaddset(&set,SIGTERM);
unknown's avatar
unknown committed
3145 3146 3147
  (void) sigaddset(&set,SIGTSTP);

  /* Save pid to this process (or thread on Linux) */
3148
  if (!opt_bootstrap)
3149 3150
    create_pid_file();

3151 3152 3153 3154
  /*
    signal to start_signal_handler that we are ready
    This works by waiting for start_signal_handler to free mutex,
    after which we signal it that we are ready.
3155
    At this point there is no other threads running, so there
Marc Alff's avatar
Marc Alff committed
3156
    should not be any other mysql_cond_signal() calls.
3157
  */
3158 3159 3160
  mysql_mutex_lock(&LOCK_start_thread);
  mysql_cond_broadcast(&COND_start_thread);
  mysql_mutex_unlock(&LOCK_start_thread);
unknown's avatar
unknown committed
3161

3162
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
unknown's avatar
unknown committed
3163 3164
  for (;;)
  {
3165 3166
    int error;
    int origin;
3167 3168

    while ((error= my_sigwait(&set, &sig, &origin)) == EINTR) /* no-op */;
unknown's avatar
unknown committed
3169
    if (cleanup_done)
3170
    {
3171
      DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
3172
      my_thread_end();
3173
      DBUG_LEAVE;                               // Must match DBUG_ENTER()
Sergei Golubchik's avatar
Sergei Golubchik committed
3174
      signal_thread_in_use= 0;
unknown's avatar
unknown committed
3175
      pthread_exit(0);				// Safety
3176
      return 0;                                 // Avoid compiler warnings
3177
    }
unknown's avatar
unknown committed
3178 3179 3180 3181 3182
    switch (sig) {
    case SIGTERM:
    case SIGQUIT:
    case SIGKILL:
#ifdef EXTRA_DEBUG
3183
      sql_print_information("Got signal %d to shutdown mysqld",sig);
unknown's avatar
unknown committed
3184
#endif
3185
      /* switch to the old log message processing */
Monty's avatar
Monty committed
3186
      logger.set_handlers(LOG_FILE, global_system_variables.sql_log_slow ? LOG_FILE:LOG_NONE,
3187
                          opt_log ? LOG_FILE:LOG_NONE);
unknown's avatar
unknown committed
3188 3189 3190
      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
      if (!abort_loop)
      {
3191
        /* Delete the instrumentation for the signal thread */
3192
        PSI_CALL_delete_current_thread();
unknown's avatar
unknown committed
3193 3194
#ifdef USE_ONE_SIGNAL_HAND
	pthread_t tmp;
3195 3196 3197 3198
        if (unlikely((error= mysql_thread_create(0, /* Not instrumented */
                                                 &tmp, &connection_attrib,
                                                 kill_server_thread,
                                                 (void*) &sig))))
3199 3200
          sql_print_error("Can't create thread to kill server (errno= %d)",
                          error);
unknown's avatar
unknown committed
3201
#else
3202 3203
        my_sigset(sig, SIG_IGN);
        break_connect_loop(); // MIT THREAD has a alarm thread
unknown's avatar
unknown committed
3204 3205 3206 3207
#endif
      }
      break;
    case SIGHUP:
3208
      if (!abort_loop && origin != SI_KERNEL)
unknown's avatar
unknown committed
3209
      {
3210
        int not_used;
unknown's avatar
Merge  
unknown committed
3211
	mysql_print_status();		// Print some debug info
unknown's avatar
unknown committed
3212 3213
	reload_acl_and_cache((THD*) 0,
			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
unknown's avatar
Merge  
unknown committed
3214
			      REFRESH_GRANT |
unknown's avatar
unknown committed
3215
			      REFRESH_THREADS | REFRESH_HOSTS),
unknown's avatar
unknown committed
3216
			     (TABLE_LIST*) 0, &not_used); // Flush logs
3217 3218 3219 3220 3221 3222 3223 3224

        /* reenable logs after the options were reloaded */
        ulonglong fixed_log_output_options=
          log_output_options & LOG_NONE ? LOG_TABLE : log_output_options;

        logger.set_handlers(LOG_FILE, global_system_variables.sql_log_slow
                                      ? fixed_log_output_options : LOG_NONE,
                            opt_log ? fixed_log_output_options : LOG_NONE);
3225
      }
unknown's avatar
unknown committed
3226 3227 3228 3229 3230 3231 3232 3233
      break;
#ifdef USE_ONE_SIGNAL_HAND
    case THR_SERVER_ALARM:
      process_alarm(sig);			// Trigger alarms.
      break;
#endif
    default:
#ifdef EXTRA_DEBUG
3234
      sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
unknown's avatar
unknown committed
3235 3236 3237 3238 3239 3240 3241
#endif
      break;					/* purecov: tested */
    }
  }
  return(0);					/* purecov: deadcode */
}

unknown's avatar
unknown committed
3242
static void check_data_home(const char *path)
unknown's avatar
unknown committed
3243
{}
unknown's avatar
unknown committed
3244

3245
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
3246 3247 3248
#endif	/* __WIN__*/


unknown's avatar
unknown committed
3249
/**
unknown's avatar
Merge  
unknown committed
3250
  All global error messages are sent here where the first one is stored
unknown's avatar
unknown committed
3251
  for the client.
unknown's avatar
unknown committed
3252 3253
*/
/* ARGSUSED */
Marc Alff's avatar
Marc Alff committed
3254
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3255

Marc Alff's avatar
Marc Alff committed
3256
void my_message_sql(uint error, const char *str, myf MyFlags)
unknown's avatar
unknown committed
3257
{
3258
  THD *thd= MyFlags & ME_ERROR_LOG_ONLY ? NULL : current_thd;
3259
  Sql_condition::enum_warning_level level;
3260
  sql_print_message_func func;
unknown's avatar
unknown committed
3261
  DBUG_ENTER("my_message_sql");
3262 3263
  DBUG_PRINT("error", ("error: %u  message: '%s'  Flag: %lu", error, str,
                       MyFlags));
3264 3265

  DBUG_ASSERT(str != NULL);
3266
  DBUG_ASSERT(error != 0);
3267 3268
  DBUG_ASSERT((MyFlags & ~(ME_BELL | ME_ERROR_LOG | ME_ERROR_LOG_ONLY |
                           ME_NOTE | ME_WARNING | ME_FATAL)) == 0);
3269

3270
  if (MyFlags & ME_NOTE)
3271
  {
3272
    level= Sql_condition::WARN_LEVEL_NOTE;
3273 3274
    func= sql_print_information;
  }
3275
  else if (MyFlags & ME_WARNING)
3276
  {
3277
    level= Sql_condition::WARN_LEVEL_WARN;
3278 3279 3280 3281
    func= sql_print_warning;
  }
  else
  {
3282
    level= Sql_condition::WARN_LEVEL_ERROR;
3283 3284
    func= sql_print_error;
  }
3285

3286
  if (likely(thd))
unknown's avatar
unknown committed
3287
  {
3288
    if (unlikely(MyFlags & ME_FATAL))
Marc Alff's avatar
Marc Alff committed
3289
      thd->is_fatal_error= 1;
Sergei Golubchik's avatar
Sergei Golubchik committed
3290
    (void) thd->raise_condition(error, NULL, level, str);
unknown's avatar
unknown committed
3291
  }
3292 3293
  else
    mysql_audit_general(0, MYSQL_AUDIT_GENERAL_ERROR, error, str);
3294 3295

  /* When simulating OOM, skip writing to error log to avoid mtr errors */
3296
  DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
3297

3298
  if (unlikely(!thd) || thd->log_all_errors || (MyFlags & ME_ERROR_LOG))
3299
    (*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
Marc Alff's avatar
Marc Alff committed
3300
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
3301 3302
}

3303

3304 3305 3306
extern "C" void *my_str_malloc_mysqld(size_t size);

void *my_str_malloc_mysqld(size_t size)
3307 3308 3309 3310 3311
{
  return my_malloc(size, MYF(MY_FAE));
}


3312
#include <mysqld_default_groups.h>
unknown's avatar
Merge  
unknown committed
3313

3314
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
3315 3316
static const int load_default_groups_sz=
sizeof(load_default_groups)/sizeof(load_default_groups[0]);
unknown's avatar
Merge  
unknown committed
3317
#endif
unknown's avatar
unknown committed
3318

unknown's avatar
unknown committed
3319

3320 3321 3322
/**
  This function is used to check for stack overrun for pathological
  cases of  regular expressions and 'like' expressions.
3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337
*/
extern "C" int
check_enough_stack_size_slow()
{
  uchar stack_top;
  THD *my_thd= current_thd;
  if (my_thd != NULL)
    return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top);
  return 0;
}


/*
  The call to current_thd in check_enough_stack_size_slow is quite expensive,
  so we try to avoid it for the normal cases.
3338 3339 3340 3341 3342
  The size of  each stack frame for the wildcmp() routines is ~128 bytes,
  so checking  *every* recursive call is not necessary.
 */
extern "C" int
check_enough_stack_size(int recurse_level)
3343
{
3344 3345
  if (recurse_level % 16 != 0)
    return 0;
3346
  return check_enough_stack_size_slow();
3347 3348
}

3349 3350 3351 3352 3353 3354

static void init_libstrings()
{
#ifndef EMBEDDED_LIBRARY
  my_string_stack_guard= check_enough_stack_size;
#endif
3355
}
3356

3357
ulonglong my_pcre_frame_size;
3358 3359 3360 3361

static void init_pcre()
{
  pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld;
3362
  pcre_free= pcre_stack_free= my_free;
3363
  pcre_stack_guard= check_enough_stack_size_slow;
3364
  /* See http://pcre.org/original/doc/html/pcrestack.html */
3365 3366 3367 3368
  my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0);
  // pcre can underestimate its stack usage. Use a safe value, as in the manual
  set_if_bigger(my_pcre_frame_size, 500);
  my_pcre_frame_size += 16; // Again, safety margin, see the manual
3369
}
3370 3371


unknown's avatar
unknown committed
3372 3373
/**
  Initialize one of the global date/time format variables.
3374

unknown's avatar
unknown committed
3375 3376
  @param format_type		What kind of format should be supported
  @param var_ptr		Pointer to variable that should be updated
unknown's avatar
Merge  
unknown committed
3377

unknown's avatar
unknown committed
3378
  @retval
3379
    0 ok
unknown's avatar
unknown committed
3380
  @retval
3381 3382 3383
    1 error
*/

unknown's avatar
unknown committed
3384
static bool init_global_datetime_format(timestamp_type format_type,
3385
                                        DATE_TIME_FORMAT *format)
3386
{
3387 3388 3389 3390 3391
  /*
    Get command line option
    format->format.str is already set by my_getopt
  */
  format->format.length= strlen(format->format.str);
3392

3393
  if (parse_date_time_format(format_type, format))
3394
  {
3395 3396 3397
    fprintf(stderr, "Wrong date/time format specifier: %s\n",
            format->format.str);
    return true;
3398
  }
3399
  return false;
3400 3401
}

3402 3403 3404
#define COM_STATUS(X)  (void*) offsetof(STATUS_VAR, X), SHOW_LONG_STATUS
#define STMT_STATUS(X) COM_STATUS(com_stat[(uint) X])

unknown's avatar
unknown committed
3405
SHOW_VAR com_status_vars[]= {
3406 3407 3408 3409 3410 3411 3412
  {"admin_commands",       COM_STATUS(com_other)},
  {"alter_db",             STMT_STATUS(SQLCOM_ALTER_DB)},
  {"alter_db_upgrade",     STMT_STATUS(SQLCOM_ALTER_DB_UPGRADE)},
  {"alter_event",          STMT_STATUS(SQLCOM_ALTER_EVENT)},
  {"alter_function",       STMT_STATUS(SQLCOM_ALTER_FUNCTION)},
  {"alter_procedure",      STMT_STATUS(SQLCOM_ALTER_PROCEDURE)},
  {"alter_server",         STMT_STATUS(SQLCOM_ALTER_SERVER)},
3413
  {"alter_sequence",       STMT_STATUS(SQLCOM_ALTER_SEQUENCE)},
3414 3415
  {"alter_table",          STMT_STATUS(SQLCOM_ALTER_TABLE)},
  {"alter_tablespace",     STMT_STATUS(SQLCOM_ALTER_TABLESPACE)},
3416
  {"alter_user",           STMT_STATUS(SQLCOM_ALTER_USER)},
3417 3418
  {"analyze",              STMT_STATUS(SQLCOM_ANALYZE)},
  {"assign_to_keycache",   STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)},
3419
  {"backup",               STMT_STATUS(SQLCOM_BACKUP)},
3420
  {"backup_lock",          STMT_STATUS(SQLCOM_BACKUP_LOCK)},
3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433
  {"begin",                STMT_STATUS(SQLCOM_BEGIN)},
  {"binlog",               STMT_STATUS(SQLCOM_BINLOG_BASE64_EVENT)},
  {"call_procedure",       STMT_STATUS(SQLCOM_CALL)},
  {"change_db",            STMT_STATUS(SQLCOM_CHANGE_DB)},
  {"change_master",        STMT_STATUS(SQLCOM_CHANGE_MASTER)},
  {"check",                STMT_STATUS(SQLCOM_CHECK)},
  {"checksum",             STMT_STATUS(SQLCOM_CHECKSUM)},
  {"commit",               STMT_STATUS(SQLCOM_COMMIT)},
  {"compound_sql",         STMT_STATUS(SQLCOM_COMPOUND)},
  {"create_db",            STMT_STATUS(SQLCOM_CREATE_DB)},
  {"create_event",         STMT_STATUS(SQLCOM_CREATE_EVENT)},
  {"create_function",      STMT_STATUS(SQLCOM_CREATE_SPFUNCTION)},
  {"create_index",         STMT_STATUS(SQLCOM_CREATE_INDEX)},
3434 3435
  {"create_package",       STMT_STATUS(SQLCOM_CREATE_PACKAGE)},
  {"create_package_body",  STMT_STATUS(SQLCOM_CREATE_PACKAGE_BODY)},
3436 3437
  {"create_procedure",     STMT_STATUS(SQLCOM_CREATE_PROCEDURE)},
  {"create_role",          STMT_STATUS(SQLCOM_CREATE_ROLE)},
3438
  {"create_sequence",      STMT_STATUS(SQLCOM_CREATE_SEQUENCE)},
3439 3440
  {"create_server",        STMT_STATUS(SQLCOM_CREATE_SERVER)},
  {"create_table",         STMT_STATUS(SQLCOM_CREATE_TABLE)},
3441
  {"create_temporary_table", COM_STATUS(com_create_tmp_table)},
3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454
  {"create_trigger",       STMT_STATUS(SQLCOM_CREATE_TRIGGER)},
  {"create_udf",           STMT_STATUS(SQLCOM_CREATE_FUNCTION)},
  {"create_user",          STMT_STATUS(SQLCOM_CREATE_USER)},
  {"create_view",          STMT_STATUS(SQLCOM_CREATE_VIEW)},
  {"dealloc_sql",          STMT_STATUS(SQLCOM_DEALLOCATE_PREPARE)},
  {"delete",               STMT_STATUS(SQLCOM_DELETE)},
  {"delete_multi",         STMT_STATUS(SQLCOM_DELETE_MULTI)},
  {"do",                   STMT_STATUS(SQLCOM_DO)},
  {"drop_db",              STMT_STATUS(SQLCOM_DROP_DB)},
  {"drop_event",           STMT_STATUS(SQLCOM_DROP_EVENT)},
  {"drop_function",        STMT_STATUS(SQLCOM_DROP_FUNCTION)},
  {"drop_index",           STMT_STATUS(SQLCOM_DROP_INDEX)},
  {"drop_procedure",       STMT_STATUS(SQLCOM_DROP_PROCEDURE)},
3455 3456
  {"drop_package",         STMT_STATUS(SQLCOM_DROP_PACKAGE)},
  {"drop_package_body",    STMT_STATUS(SQLCOM_DROP_PACKAGE_BODY)},
3457 3458
  {"drop_role",            STMT_STATUS(SQLCOM_DROP_ROLE)},
  {"drop_server",          STMT_STATUS(SQLCOM_DROP_SERVER)},
3459
  {"drop_sequence",        STMT_STATUS(SQLCOM_DROP_SEQUENCE)},
3460
  {"drop_table",           STMT_STATUS(SQLCOM_DROP_TABLE)},
3461
  {"drop_temporary_table", COM_STATUS(com_drop_tmp_table)},
3462 3463 3464 3465
  {"drop_trigger",         STMT_STATUS(SQLCOM_DROP_TRIGGER)},
  {"drop_user",            STMT_STATUS(SQLCOM_DROP_USER)},
  {"drop_view",            STMT_STATUS(SQLCOM_DROP_VIEW)},
  {"empty_query",          STMT_STATUS(SQLCOM_EMPTY_QUERY)},
3466
  {"execute_immediate",    STMT_STATUS(SQLCOM_EXECUTE_IMMEDIATE)},
3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481
  {"execute_sql",          STMT_STATUS(SQLCOM_EXECUTE)},
  {"flush",                STMT_STATUS(SQLCOM_FLUSH)},
  {"get_diagnostics",      STMT_STATUS(SQLCOM_GET_DIAGNOSTICS)},
  {"grant",                STMT_STATUS(SQLCOM_GRANT)},
  {"grant_role",           STMT_STATUS(SQLCOM_GRANT_ROLE)},
  {"ha_close",             STMT_STATUS(SQLCOM_HA_CLOSE)},
  {"ha_open",              STMT_STATUS(SQLCOM_HA_OPEN)},
  {"ha_read",              STMT_STATUS(SQLCOM_HA_READ)},
  {"help",                 STMT_STATUS(SQLCOM_HELP)},
  {"insert",               STMT_STATUS(SQLCOM_INSERT)},
  {"insert_select",        STMT_STATUS(SQLCOM_INSERT_SELECT)},
  {"install_plugin",       STMT_STATUS(SQLCOM_INSTALL_PLUGIN)},
  {"kill",                 STMT_STATUS(SQLCOM_KILL)},
  {"load",                 STMT_STATUS(SQLCOM_LOAD)},
  {"lock_tables",          STMT_STATUS(SQLCOM_LOCK_TABLES)},
3482
  {"multi",                COM_STATUS(com_multi)},
3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512
  {"optimize",             STMT_STATUS(SQLCOM_OPTIMIZE)},
  {"preload_keys",         STMT_STATUS(SQLCOM_PRELOAD_KEYS)},
  {"prepare_sql",          STMT_STATUS(SQLCOM_PREPARE)},
  {"purge",                STMT_STATUS(SQLCOM_PURGE)},
  {"purge_before_date",    STMT_STATUS(SQLCOM_PURGE_BEFORE)},
  {"release_savepoint",    STMT_STATUS(SQLCOM_RELEASE_SAVEPOINT)},
  {"rename_table",         STMT_STATUS(SQLCOM_RENAME_TABLE)},
  {"rename_user",          STMT_STATUS(SQLCOM_RENAME_USER)},
  {"repair",               STMT_STATUS(SQLCOM_REPAIR)},
  {"replace",              STMT_STATUS(SQLCOM_REPLACE)},
  {"replace_select",       STMT_STATUS(SQLCOM_REPLACE_SELECT)},
  {"reset",                STMT_STATUS(SQLCOM_RESET)},
  {"resignal",             STMT_STATUS(SQLCOM_RESIGNAL)},
  {"revoke",               STMT_STATUS(SQLCOM_REVOKE)},
  {"revoke_all",           STMT_STATUS(SQLCOM_REVOKE_ALL)},
  {"revoke_role",          STMT_STATUS(SQLCOM_REVOKE_ROLE)},
  {"rollback",             STMT_STATUS(SQLCOM_ROLLBACK)},
  {"rollback_to_savepoint",STMT_STATUS(SQLCOM_ROLLBACK_TO_SAVEPOINT)},
  {"savepoint",            STMT_STATUS(SQLCOM_SAVEPOINT)},
  {"select",               STMT_STATUS(SQLCOM_SELECT)},
  {"set_option",           STMT_STATUS(SQLCOM_SET_OPTION)},
  {"show_authors",         STMT_STATUS(SQLCOM_SHOW_AUTHORS)},
  {"show_binlog_events",   STMT_STATUS(SQLCOM_SHOW_BINLOG_EVENTS)},
  {"show_binlogs",         STMT_STATUS(SQLCOM_SHOW_BINLOGS)},
  {"show_charsets",        STMT_STATUS(SQLCOM_SHOW_CHARSETS)},
  {"show_collations",      STMT_STATUS(SQLCOM_SHOW_COLLATIONS)},
  {"show_contributors",    STMT_STATUS(SQLCOM_SHOW_CONTRIBUTORS)},
  {"show_create_db",       STMT_STATUS(SQLCOM_SHOW_CREATE_DB)},
  {"show_create_event",    STMT_STATUS(SQLCOM_SHOW_CREATE_EVENT)},
  {"show_create_func",     STMT_STATUS(SQLCOM_SHOW_CREATE_FUNC)},
3513 3514
  {"show_create_package",  STMT_STATUS(SQLCOM_SHOW_CREATE_PACKAGE)},
  {"show_create_package_body",STMT_STATUS(SQLCOM_SHOW_CREATE_PACKAGE_BODY)},
3515 3516 3517
  {"show_create_proc",     STMT_STATUS(SQLCOM_SHOW_CREATE_PROC)},
  {"show_create_table",    STMT_STATUS(SQLCOM_SHOW_CREATE)},
  {"show_create_trigger",  STMT_STATUS(SQLCOM_SHOW_CREATE_TRIGGER)},
3518
  {"show_create_user",     STMT_STATUS(SQLCOM_SHOW_CREATE_USER)},
3519 3520 3521 3522 3523 3524 3525 3526
  {"show_databases",       STMT_STATUS(SQLCOM_SHOW_DATABASES)},
  {"show_engine_logs",     STMT_STATUS(SQLCOM_SHOW_ENGINE_LOGS)},
  {"show_engine_mutex",    STMT_STATUS(SQLCOM_SHOW_ENGINE_MUTEX)},
  {"show_engine_status",   STMT_STATUS(SQLCOM_SHOW_ENGINE_STATUS)},
  {"show_errors",          STMT_STATUS(SQLCOM_SHOW_ERRORS)},
  {"show_events",          STMT_STATUS(SQLCOM_SHOW_EVENTS)},
  {"show_explain",         STMT_STATUS(SQLCOM_SHOW_EXPLAIN)},
  {"show_fields",          STMT_STATUS(SQLCOM_SHOW_FIELDS)},
unknown's avatar
unknown committed
3527
#ifndef DBUG_OFF
3528 3529 3530 3531 3532 3533 3534 3535
  {"show_function_code",   STMT_STATUS(SQLCOM_SHOW_FUNC_CODE)},
#endif
  {"show_function_status", STMT_STATUS(SQLCOM_SHOW_STATUS_FUNC)},
  {"show_generic",         STMT_STATUS(SQLCOM_SHOW_GENERIC)},
  {"show_grants",          STMT_STATUS(SQLCOM_SHOW_GRANTS)},
  {"show_keys",            STMT_STATUS(SQLCOM_SHOW_KEYS)},
  {"show_master_status",   STMT_STATUS(SQLCOM_SHOW_MASTER_STAT)},
  {"show_open_tables",     STMT_STATUS(SQLCOM_SHOW_OPEN_TABLES)},
3536 3537 3538 3539 3540
  {"show_package_status",  STMT_STATUS(SQLCOM_SHOW_STATUS_PACKAGE)},
#ifndef DBUG_OFF
  {"show_package_body_code",   STMT_STATUS(SQLCOM_SHOW_PACKAGE_BODY_CODE)},
#endif
  {"show_package_body_status", STMT_STATUS(SQLCOM_SHOW_STATUS_PACKAGE_BODY)},
3541 3542
  {"show_plugins",         STMT_STATUS(SQLCOM_SHOW_PLUGINS)},
  {"show_privileges",      STMT_STATUS(SQLCOM_SHOW_PRIVILEGES)},
unknown's avatar
unknown committed
3543
#ifndef DBUG_OFF
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
  {"show_procedure_code",  STMT_STATUS(SQLCOM_SHOW_PROC_CODE)},
#endif
  {"show_procedure_status",STMT_STATUS(SQLCOM_SHOW_STATUS_PROC)},
  {"show_processlist",     STMT_STATUS(SQLCOM_SHOW_PROCESSLIST)},
  {"show_profile",         STMT_STATUS(SQLCOM_SHOW_PROFILE)},
  {"show_profiles",        STMT_STATUS(SQLCOM_SHOW_PROFILES)},
  {"show_relaylog_events", STMT_STATUS(SQLCOM_SHOW_RELAYLOG_EVENTS)},
  {"show_slave_hosts",     STMT_STATUS(SQLCOM_SHOW_SLAVE_HOSTS)},
  {"show_slave_status",    STMT_STATUS(SQLCOM_SHOW_SLAVE_STAT)},
  {"show_status",          STMT_STATUS(SQLCOM_SHOW_STATUS)},
  {"show_storage_engines", STMT_STATUS(SQLCOM_SHOW_STORAGE_ENGINES)},
  {"show_table_status",    STMT_STATUS(SQLCOM_SHOW_TABLE_STATUS)},
  {"show_tables",          STMT_STATUS(SQLCOM_SHOW_TABLES)},
  {"show_triggers",        STMT_STATUS(SQLCOM_SHOW_TRIGGERS)},
  {"show_variables",       STMT_STATUS(SQLCOM_SHOW_VARIABLES)},
  {"show_warnings",        STMT_STATUS(SQLCOM_SHOW_WARNS)},
  {"shutdown",             STMT_STATUS(SQLCOM_SHUTDOWN)},
  {"signal",               STMT_STATUS(SQLCOM_SIGNAL)},
  {"start_all_slaves",     STMT_STATUS(SQLCOM_SLAVE_ALL_START)},
  {"start_slave",          STMT_STATUS(SQLCOM_SLAVE_START)},
  {"stmt_close",           COM_STATUS(com_stmt_close)},
  {"stmt_execute",         COM_STATUS(com_stmt_execute)},
  {"stmt_fetch",           COM_STATUS(com_stmt_fetch)},
  {"stmt_prepare",         COM_STATUS(com_stmt_prepare)},
  {"stmt_reprepare",       COM_STATUS(com_stmt_reprepare)},
  {"stmt_reset",           COM_STATUS(com_stmt_reset)},
  {"stmt_send_long_data",  COM_STATUS(com_stmt_send_long_data)},
  {"stop_all_slaves",      STMT_STATUS(SQLCOM_SLAVE_ALL_STOP)},
  {"stop_slave",           STMT_STATUS(SQLCOM_SLAVE_STOP)},
  {"truncate",             STMT_STATUS(SQLCOM_TRUNCATE)},
  {"uninstall_plugin",     STMT_STATUS(SQLCOM_UNINSTALL_PLUGIN)},
  {"unlock_tables",        STMT_STATUS(SQLCOM_UNLOCK_TABLES)},
  {"update",               STMT_STATUS(SQLCOM_UPDATE)},
  {"update_multi",         STMT_STATUS(SQLCOM_UPDATE_MULTI)},
  {"xa_commit",            STMT_STATUS(SQLCOM_XA_COMMIT)},
  {"xa_end",               STMT_STATUS(SQLCOM_XA_END)},
  {"xa_prepare",           STMT_STATUS(SQLCOM_XA_PREPARE)},
  {"xa_recover",           STMT_STATUS(SQLCOM_XA_RECOVER)},
  {"xa_rollback",          STMT_STATUS(SQLCOM_XA_ROLLBACK)},
  {"xa_start",             STMT_STATUS(SQLCOM_XA_START)},
3584
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
3585
};
3586

Sergei Golubchik's avatar
Sergei Golubchik committed
3587

3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599
#ifdef HAVE_PSI_STATEMENT_INTERFACE
PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1];
PSI_statement_info com_statement_info[(uint) COM_END + 1];

/**
  Initialize the command names array.
  Since we do not want to maintain a separate array,
  this is populated from data mined in com_status_vars,
  which already has one name for each command.
*/
void init_sql_statement_info()
{
3600 3601 3602 3603 3604
  size_t first_com= offsetof(STATUS_VAR, com_stat[0]);
  size_t last_com=  offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
  int record_size= offsetof(STATUS_VAR, com_stat[1])
                   - offsetof(STATUS_VAR, com_stat[0]);
  size_t ptr;
3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
  uint i;
  uint com_index;

  static const char* dummy= "";
  for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
  {
    sql_statement_info[i].m_name= dummy;
    sql_statement_info[i].m_flags= 0;
  }

  SHOW_VAR *var= &com_status_vars[0];
  while (var->name != NULL)
  {
3618
    ptr= (size_t)(var->value);
Sergei Golubchik's avatar
Sergei Golubchik committed
3619
    if ((first_com <= ptr) && (ptr < last_com))
3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643
    {
      com_index= ((int)(ptr - first_com))/record_size;
      DBUG_ASSERT(com_index < (uint) SQLCOM_END);
      sql_statement_info[com_index].m_name= var->name;
    }
    var++;
  }

  DBUG_ASSERT(strcmp(sql_statement_info[(uint) SQLCOM_SELECT].m_name, "select") == 0);
  DBUG_ASSERT(strcmp(sql_statement_info[(uint) SQLCOM_SIGNAL].m_name, "signal") == 0);

  sql_statement_info[(uint) SQLCOM_END].m_name= "error";
}

void init_com_statement_info()
{
  uint index;

  for (index= 0; index < (uint) COM_END + 1; index++)
  {
    com_statement_info[index].m_name= command_name[index].str;
    com_statement_info[index].m_flags= 0;
  }

Sergei Golubchik's avatar
Sergei Golubchik committed
3644
  /* "statement/abstract/query" can mutate into "statement/sql/..." */
3645 3646 3647 3648 3649
  com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE;
}
#endif


3650 3651 3652 3653 3654 3655 3656 3657 3658
#ifdef SAFEMALLOC
/*
  Return the id for the current THD, to allow safemalloc to associate
  the memory with the right id.
*/

extern "C" my_thread_id mariadb_dbug_id()
{
  THD *thd;
Monty's avatar
Monty committed
3659
  if ((thd= current_thd) && thd->thread_dbug_id)
3660
  {
Monty's avatar
Monty committed
3661
    return thd->thread_dbug_id;
3662 3663 3664 3665 3666
  }
  return my_thread_dbug_id();
}
#endif /* SAFEMALLOC */

Sergei Golubchik's avatar
Sergei Golubchik committed
3667 3668 3669 3670
/* Thread Mem Usage By P.Linux */
extern "C" {
static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific)
{
3671
  THD *thd= current_thd;
3672

3673 3674 3675
  /*
    When thread specific is set, both mysqld_server_initialized and thd
    must be set, and we check that with DBUG_ASSERT.
3676

3677 3678 3679 3680 3681 3682
    However, do not crash, if current_thd is NULL, in release version.
  */
  DBUG_ASSERT(!is_thread_specific || (mysqld_server_initialized && thd));

  if (is_thread_specific && likely(thd))  /* If thread specific memory */
  {
3683 3684 3685 3686
    DBUG_PRINT("info", ("thd memory_used: %lld  size: %lld",
                        (longlong) thd->status_var.local_memory_used,
                        size));
    thd->status_var.local_memory_used+= size;
3687 3688
    set_if_bigger(thd->status_var.max_local_memory_used,
                  thd->status_var.local_memory_used);
3689 3690
    if (size > 0 &&
        thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used &&
3691
        likely(!thd->killed) && !thd->get_stmt_da()->is_set())
3692
    {
3693 3694 3695
      /* Ensure we don't get called here again */
      char buf[50], *buf2;
      thd->set_killed(KILL_QUERY);
3696 3697
      my_snprintf(buf, sizeof(buf), "--max-thread-mem-used=%llu",
                  thd->variables.max_mem_used);
3698 3699 3700 3701 3702
      if ((buf2= (char*) thd->alloc(256)))
      {
        my_snprintf(buf2, 256, ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf);
        thd->set_killed(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, buf2);
      }
3703
    }
3704 3705
    DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0 ||
                !debug_assert_on_not_freed_memory);
Sergei Golubchik's avatar
Sergei Golubchik committed
3706
  }
3707
  else if (likely(thd))
3708 3709
  {
    DBUG_PRINT("info", ("global thd memory_used: %lld  size: %lld",
3710
                        (longlong) thd->status_var.global_memory_used, size));
3711
    thd->status_var.global_memory_used+= size;
3712
  }
3713
  else
3714
    update_global_memory_status(size);
Sergei Golubchik's avatar
Sergei Golubchik committed
3715
}
3716 3717 3718 3719 3720 3721 3722 3723

int json_escape_string(const char *str,const char *str_end,
                       char *json, char *json_end)
{
  return json_escape(system_charset_info,
                     (const uchar *) str, (const uchar *) str_end,
                     &my_charset_utf8mb4_bin,
                     (uchar *) json, (uchar *) json_end);
Sergei Golubchik's avatar
Sergei Golubchik committed
3724 3725
}

3726

3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737
int json_unescape_json(const char *json_str, const char *json_end,
                       char *res, char *res_end)
{
  return json_unescape(&my_charset_utf8mb4_bin,
                       (const uchar *) json_str, (const uchar *) json_end,
                       system_charset_info, (uchar *) res, (uchar *) res_end);
}

} /*extern "C"*/


3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773
/**
  Create a replication file name or base for file names.

  @param[in] opt Value of option, or NULL
  @param[in] def Default value if option value is not set.
  @param[in] ext Extension to use for the path

  @returns Pointer to string containing the full file path, or NULL if
  it was not possible to create the path.
 */
static inline const char *
rpl_make_log_name(const char *opt,
                  const char *def,
                  const char *ext)
{
  DBUG_ENTER("rpl_make_log_name");
  DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt, def, ext));
  char buff[FN_REFLEN];
  const char *base= opt ? opt : def;
  unsigned int options=
    MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH;

  /* mysql_real_data_home_ptr  may be null if no value of datadir has been
     specified through command-line or througha cnf file. If that is the
     case we make mysql_real_data_home_ptr point to mysql_real_data_home
     which, in that case holds the default path for data-dir.
  */
  if(mysql_real_data_home_ptr == NULL)
    mysql_real_data_home_ptr= mysql_real_data_home;

  if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
    DBUG_RETURN(my_strdup(buff, MYF(MY_WME)));
  else
    DBUG_RETURN(NULL);
}

3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789
/* We have to setup my_malloc_size_cb_func early to catch all mallocs */

static int init_early_variables()
{
  if (pthread_key_create(&THR_THD, NULL))
  {
    fprintf(stderr, "Fatal error: Can't create thread-keys\n");
    return 1;
  }
  set_current_thd(0);
  set_malloc_size_cb(my_malloc_size_cb_func);
  global_status_var.global_memory_used= 0;
  return 0;
}


Marc Alff's avatar
Marc Alff committed
3790
static int init_common_variables()
unknown's avatar
unknown committed
3791
{
unknown's avatar
unknown committed
3792
  umask(((~my_umask) & 0666));
unknown's avatar
unknown committed
3793 3794 3795 3796 3797 3798
  connection_errors_select= 0;
  connection_errors_accept= 0;
  connection_errors_tcpwrap= 0;
  connection_errors_internal= 0;
  connection_errors_max_connection= 0;
  connection_errors_peer_addr= 0;
unknown's avatar
Merge  
unknown committed
3799
  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
Sergei Golubchik's avatar
Sergei Golubchik committed
3800

3801
  init_libstrings();
unknown's avatar
unknown committed
3802 3803
  tzset();			// Set tzname

3804 3805
#ifdef SAFEMALLOC
  sf_malloc_dbug_id= mariadb_dbug_id;
3806 3807 3808 3809
#endif /* SAFEMALLOC */
#ifdef DBUG_ASSERT_AS_PRINTF
  my_dbug_assert_failed= mariadb_dbug_assert_failed;
#endif /* DBUG_ASSERT_AS_PRINTF */
3810

3811 3812 3813 3814 3815 3816 3817
  if (!(type_handler_data= new Type_handler_data) ||
      type_handler_data->init())
  {
    sql_perror("Could not allocate type_handler_data");
    return 1;
  }

3818
  max_system_variables.pseudo_thread_id= ~(my_thread_id) 0;
3819
  server_start_time= flush_status_time= my_time(0);
3820
  my_disable_copystat_in_redel= 1;
3821

3822
  global_rpl_filter= new Rpl_filter;
3823
  binlog_filter= new Rpl_filter;
3824
  if (!global_rpl_filter || !binlog_filter)
3825 3826
  {
    sql_perror("Could not allocate replication and binlog filters");
3827
    exit(1);
3828 3829
  }

3830 3831 3832 3833
#ifdef HAVE_OPENSSL
  if (check_openssl_compatibility())
  {
    sql_print_error("Incompatible OpenSSL version. Cannot continue...");
3834
    exit(1);
3835 3836 3837
  }
#endif

3838 3839
  if (init_thread_environment() || mysql_init_variables())
    exit(1);
unknown's avatar
unknown committed
3840

3841
  if (ignore_db_dirs_init())
3842
    exit(1);
3843

unknown's avatar
unknown committed
3844
#ifdef HAVE_TZNAME
3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857
  struct tm tm_tmp;
  localtime_r(&server_start_time,&tm_tmp);
  const char *tz_name=  tzname[tm_tmp.tm_isdst != 0 ? 1 : 0];
#ifdef _WIN32
  /*
    Time zone name may be localized and contain non-ASCII characters,
    Convert from ANSI encoding to UTF8.
  */
  wchar_t wtz_name[sizeof(system_time_zone)];
  mbstowcs(wtz_name, tz_name, sizeof(system_time_zone)-1);
  WideCharToMultiByte(CP_UTF8,0, wtz_name, -1, system_time_zone, 
    sizeof(system_time_zone) - 1, NULL, NULL);
#else
3858
  strmake_buf(system_time_zone, tz_name);
3859 3860
#endif /* _WIN32 */
#endif /* HAVE_TZNAME */
3861

3862
  /*
unknown's avatar
unknown committed
3863
    We set SYSTEM time zone as reasonable default and
3864 3865 3866 3867 3868
    also for failure of my_tz_init() and bootstrap mode.
    If user explicitly set time zone with --default-time-zone
    option we will change this value in my_tz_init().
  */
  global_system_variables.time_zone= my_tz_SYSTEM;
unknown's avatar
unknown committed
3869

3870 3871 3872
#ifdef HAVE_PSI_INTERFACE
  /*
    Complete the mysql_bin_log initialization.
3873 3874 3875
    Instrumentation keys are known only after the performance schema
    initialization, and can not be set in the MYSQL_BIN_LOG
    constructor (called before main()).
3876 3877
  */
  mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
3878 3879
                             key_BINLOG_COND_relay_log_updated,
                             key_BINLOG_COND_bin_log_updated,
3880
                             key_file_binlog,
3881
                             key_file_binlog_index,
3882 3883
                             key_BINLOG_COND_queue_busy,
                             key_LOCK_binlog_end_pos);
3884 3885
#endif

unknown's avatar
unknown committed
3886
  /*
3887
    Init mutexes for the global MYSQL_BIN_LOG objects.
unknown's avatar
unknown committed
3888
    As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3889 3890
    global MYSQL_BIN_LOGs in their constructors, because then they would be
    inited before MY_INIT(). So we do it here.
unknown's avatar
unknown committed
3891 3892
  */
  mysql_bin_log.init_pthread_objects();
3893

3894 3895 3896
  /* TODO: remove this when my_time_t is 64 bit compatible */
  if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
  {
Karim Geiger's avatar
Karim Geiger committed
3897
    sql_print_error("This MySQL server doesn't support dates later than 2038");
3898
    exit(1);
3899 3900
  }

3901 3902
  opt_log_basename= const_cast<char *>("mysql");

3903 3904
  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
  {
3905 3906 3907 3908
    /*
      Get hostname of computer (used by 'show variables') and as default
      basename for the pid file if --log-basename is not given.
    */
3909 3910
    strmake(glob_hostname, STRING_WITH_LEN("localhost"));
    sql_print_warning("gethostname failed, using '%s' as hostname",
3911
                        glob_hostname);
3912
  }
3913
  else if (is_filename_allowed(glob_hostname, strlen(glob_hostname), FALSE))
Sergei Golubchik's avatar
Sergei Golubchik committed
3914
    opt_log_basename= glob_hostname;
3915

Sergei Golubchik's avatar
Sergei Golubchik committed
3916 3917 3918
  strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
  strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
  SYSVAR_AUTOSIZE(pidfile_name_ptr, pidfile_name);
3919
  set_sys_var_value_origin(&opt_tc_log_size, sys_var::AUTO);
unknown's avatar
unknown committed
3920

3921 3922 3923 3924 3925 3926 3927
  /*
    The default-storage-engine entry in my_long_options should have a
    non-null default value. It was earlier intialized as
    (longlong)"MyISAM" in my_long_options but this triggered a
    compiler error in the Sun Studio 12 compiler. As a work-around we
    set the def_value member to 0 in my_long_options and initialize it
    to the correct value here.
3928 3929 3930 3931

    From MySQL 5.5 onwards, the default storage engine is InnoDB
    (except in the embedded server, where the default continues to
    be MyISAM)
3932
  */
Marko Mäkelä's avatar
Marko Mäkelä committed
3933
#if defined(WITH_INNOBASE_STORAGE_ENGINE)
3934
  default_storage_engine= const_cast<char *>("InnoDB");
3935 3936
#else
  default_storage_engine= const_cast<char *>("MyISAM");
3937
#endif
3938
  default_tmp_storage_engine= NULL;
3939
  gtid_pos_auto_engines= const_cast<char *>("");
3940

3941 3942 3943
  /*
    Add server status variables to the dynamic list of
    status variables that is shown by SHOW STATUS.
3944
    Later, in plugin_init, and mysql_install_plugin
3945 3946 3947
    new entries could be added to that list.
  */
  if (add_status_vars(status_vars))
3948
    exit(1); // an error was already reported
3949

unknown's avatar
unknown committed
3950 3951 3952 3953 3954
#ifndef DBUG_OFF
  /*
    We have few debug-only commands in com_status_vars, only visible in debug
    builds. for simplicity we enable the assert only in debug builds

3955
    There are 10 Com_ variables which don't have corresponding SQLCOM_ values:
unknown's avatar
unknown committed
3956 3957 3958
    (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
    that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)

3959 3960 3961 3962 3963 3964 3965 3966 3967 3968
      Com_admin_commands         => com_other
      Com_create_temporary_table => com_create_tmp_table
      Com_drop_temporary_table   => com_drop_tmp_table
      Com_stmt_close             => com_stmt_close
      Com_stmt_execute           => com_stmt_execute
      Com_stmt_fetch             => com_stmt_fetch
      Com_stmt_prepare           => com_stmt_prepare
      Com_stmt_reprepare         => com_stmt_reprepare
      Com_stmt_reset             => com_stmt_reset
      Com_stmt_send_long_data    => com_stmt_send_long_data
unknown's avatar
unknown committed
3969

3970 3971 3972
    With this correction the number of Com_ variables (number of elements in
    the array, excluding the last element - terminator) must match the number
    of SQLCOM_ constants.
unknown's avatar
unknown committed
3973
  */
3974
  compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
3975
                     SQLCOM_END + 11);
unknown's avatar
unknown committed
3976 3977
#endif

Marc Alff's avatar
Marc Alff committed
3978
  if (get_options(&remaining_argc, &remaining_argv))
3979
    exit(1);
3980 3981
  if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
    set_server_version(server_version, sizeof(server_version));
3982

3983
  mysql_real_data_home_len= uint(strlen(mysql_real_data_home));
3984

3985
  if (!opt_abort)
3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998
  {
    if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
      sql_print_information("%s (mysqld %s) starting as process %lu ...",
                            my_progname, server_version, (ulong) getpid());
    else
    {
      char real_server_version[SERVER_VERSION_LENGTH];
      set_server_version(real_server_version, sizeof(real_server_version));
      sql_print_information("%s (mysqld %s as %s) starting as process %lu ...",
                            my_progname, real_server_version, server_version,
                            (ulong) getpid());
    }
  }
3999

4000 4001
  sf_leaking_memory= 0; // no memory leaks from now on

4002
#ifndef EMBEDDED_LIBRARY
4003
  if (opt_abort && !opt_verbose)
4004 4005 4006
    unireg_abort(0);
#endif /*!EMBEDDED_LIBRARY*/

unknown's avatar
unknown committed
4007 4008 4009
  DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
		     server_version, SYSTEM_TYPE,MACHINE_TYPE));

4010
#ifdef HAVE_LINUX_LARGE_PAGES
unknown's avatar
Merge  
unknown committed
4011
  /* Initialize large page size */
Sergei Golubchik's avatar
Sergei Golubchik committed
4012
  if (opt_large_pages)
unknown's avatar
Merge  
unknown committed
4013
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
4014 4015 4016
    SYSVAR_AUTOSIZE(opt_large_page_size, my_get_large_page_size());
    if (opt_large_page_size)
    {
4017 4018
      DBUG_PRINT("info", ("Large page set, large_page_size = %d",
                 opt_large_page_size));
unknown's avatar
Merge  
unknown committed
4019 4020
      my_use_large_pages= 1;
      my_large_page_size= opt_large_page_size;
Sergei Golubchik's avatar
Sergei Golubchik committed
4021 4022 4023
    }
    else
      SYSVAR_AUTOSIZE(opt_large_pages, 0);
4024
  }
4025
#endif /* HAVE_LINUX_LARGE_PAGES */
4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041
#ifdef HAVE_SOLARIS_LARGE_PAGES
#define LARGE_PAGESIZE (4*1024*1024)  /* 4MB */
#define SUPER_LARGE_PAGESIZE (256*1024*1024)  /* 256MB */
  if (opt_large_pages)
  {
  /*
    tell the kernel that we want to use 4/256MB page for heap storage
    and also for the stack. We use 4 MByte as default and if the
    super-large-page is set we increase it to 256 MByte. 256 MByte
    is for server installations with GBytes of RAM memory where
    the MySQL Server will have page caches and other memory regions
    measured in a number of GBytes.
    We use as big pages as possible which isn't bigger than the above
    desired page sizes.
  */
   int nelem;
4042
   size_t max_desired_page_size;
4043
   if (opt_super_large_pages)
4044
     max_desired_page_size= SUPER_LARGE_PAGESIZE;
4045
   else
4046
     max_desired_page_size= LARGE_PAGESIZE;
4047 4048 4049 4050 4051 4052
   nelem = getpagesizes(NULL, 0);
   if (nelem > 0)
   {
     size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
     if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
     {
4053 4054
       size_t max_page_size= 0;
       for (int i= 0; i < nelem; i++)
4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075
       {
         if (pagesize[i] > max_page_size &&
             pagesize[i] <= max_desired_page_size)
            max_page_size= pagesize[i];
       }
       free(pagesize);
       if (max_page_size > 0)
       {
         struct memcntl_mha mpss;

         mpss.mha_cmd= MHA_MAPSIZE_BSSBRK;
         mpss.mha_pagesize= max_page_size;
         mpss.mha_flags= 0;
         memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
         mpss.mha_cmd= MHA_MAPSIZE_STACK;
         memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
       }
     }
   }
  }
#endif /* HAVE_SOLARIS_LARGE_PAGES */
unknown's avatar
Merge  
unknown committed
4076

4077

4078
#if defined(HAVE_POOL_OF_THREADS)
4079 4080 4081 4082
  if (IS_SYSVAR_AUTOSIZE(&threadpool_size))
    SYSVAR_AUTOSIZE(threadpool_size, my_getncpus());
#endif

unknown's avatar
unknown committed
4083 4084
  /* connections and databases needs lots of files */
  {
4085 4086 4087
    uint files, wanted_files, max_open_files, min_tc_size, extra_files,
      min_connections;
    ulong org_max_connections, org_tc_size;
4088

4089 4090 4091
    /* Number of files reserved for temporary files */
    extra_files= 30;
    min_connections= 10;
4092
    /* MyISAM requires two file handles per table. */
4093
    wanted_files= (extra_files + max_connections + extra_max_connections +
4094
                   tc_size * 2);
4095 4096
#if defined(HAVE_POOL_OF_THREADS) && !defined(__WIN__)
    // add epoll or kevent fd for each threadpool group, in case pool of threads is used
4097
    wanted_files+= (thread_handling > SCHEDULER_NO_THREADS) ? 0 : threadpool_size;
4098
#endif
4099

4100 4101 4102 4103
    min_tc_size= MY_MIN(tc_size, TABLE_OPEN_CACHE_MIN);
    org_max_connections= max_connections;
    org_tc_size= tc_size;

4104 4105 4106 4107 4108 4109 4110 4111 4112 4113
    /*
      We are trying to allocate no less than max_connections*5 file
      handles (i.e. we are trying to set the limit so that they will
      be available).  In addition, we allocate no less than how much
      was already allocated.  However below we report a warning and
      recompute values only if we got less file handles than were
      explicitly requested.  No warning and re-computation occur if we
      can't get max_connections*5 but still got no less than was
      requested (value of wanted_files).
    */
4114
    max_open_files= MY_MAX(MY_MAX(wanted_files,
4115 4116
                                  (max_connections + extra_max_connections)*5),
                           open_files_limit);
4117
    files= my_set_max_open_files(max_open_files);
4118
    SYSVAR_AUTOSIZE_IF_CHANGED(open_files_limit, files, ulong);
4119

4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133
    if (files < wanted_files && global_system_variables.log_warnings)
      sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);

    /*
      If we have requested too much file handles than we bring
      max_connections in supported bounds. Still leave at least
      'min_connections' connections
    */
    SYSVAR_AUTOSIZE_IF_CHANGED(max_connections,
                               (ulong) MY_MAX(MY_MIN(files- extra_files-
                                                     min_tc_size*2,
                                                     max_connections),
                                              min_connections),
                               ulong);
4134

4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154
    /*
      Decrease tc_size according to max_connections, but
      not below min_tc_size.  Outer MY_MIN() ensures that we
      never increase tc_size automatically (that could
      happen if max_connections is decreased above).
    */
    SYSVAR_AUTOSIZE_IF_CHANGED(tc_size,
                               (ulong) MY_MIN(MY_MAX((files - extra_files -
                                                      max_connections) / 2,
                                                     min_tc_size),
                                              tc_size), ulong);
    DBUG_PRINT("warning",
               ("Current limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
                files, max_connections, tc_size));
    if (global_system_variables.log_warnings > 1 &&
        (max_connections < org_max_connections ||
         tc_size < org_tc_size))
      sql_print_warning("Changed limits: max_open_files: %u  max_connections: %lu (was %lu)  table_cache: %lu (was %lu)",
			files, max_connections, org_max_connections,
                        tc_size, org_tc_size);
unknown's avatar
unknown committed
4155
  }
4156
  /*
4157
    Max_connections and tc_cache are now set.
4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184
    Now we can fix other variables depending on this variable.
  */

  /* Fix host_cache_size */
  if (IS_SYSVAR_AUTOSIZE(&host_cache_size))
  {
    /*
      The default value is 128.
      The autoset value is 128, plus 1 for a value of max_connections
      up to 500, plus 1 for every increment of 20 over 500 in the
      max_connections value, capped at 2000.
    */
    uint size= (HOST_CACHE_SIZE + MY_MIN(max_connections, 500) +
                MY_MAX(((long) max_connections)-500,0)/20);
    SYSVAR_AUTOSIZE(host_cache_size, size);
  }

  /* Fix back_log (back_log == 0 added for MySQL compatibility) */
  if (back_log == 0 || IS_SYSVAR_AUTOSIZE(&back_log))
  {
    /*
      The default value is 150.
      The autoset value is 50 + max_connections / 5 capped at 900
    */
    SYSVAR_AUTOSIZE(back_log, MY_MIN(900, (50 + max_connections / 5)));
  }

unknown's avatar
unknown committed
4185
  unireg_init(opt_specialflag); /* Set up extern variabels */
4186 4187 4188 4189 4190 4191
  if (!(my_default_lc_messages=
        my_locale_by_name(lc_messages)))
  {
    sql_print_error("Unknown locale: '%s'", lc_messages);
    return 1;
  }
Monty's avatar
Monty committed
4192

4193 4194
  if (init_errmessage())	/* Read error messages from file */
    return 1;
Monty's avatar
Monty committed
4195 4196
  global_system_variables.lc_messages= my_default_lc_messages;
  global_system_variables.errmsgs= my_default_lc_messages->errmsgs->errmsgs;
4197
  init_client_errs();
Sergei Golubchik's avatar
Sergei Golubchik committed
4198
  mysql_library_init(unused,unused,unused); /* for replication */
unknown's avatar
unknown committed
4199
  lex_init();
4200 4201
  if (item_create_init())
    return 1;
unknown's avatar
unknown committed
4202
  item_init();
4203
  init_pcre();
4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230
  /*
    Process a comma-separated character set list and choose
    the first available character set. This is mostly for
    test purposes, to be able to start "mysqld" even if
    the requested character set is not available (see bug#18743).
  */
  for (;;)
  {
    char *next_character_set_name= strchr(default_character_set_name, ',');
    if (next_character_set_name)
      *next_character_set_name++= '\0';
    if (!(default_charset_info=
          get_charset_by_csname(default_character_set_name,
                                MY_CS_PRIMARY, MYF(MY_WME))))
    {
      if (next_character_set_name)
      {
        default_character_set_name= next_character_set_name;
        default_collation_name= 0;          // Ignore collation
      }
      else
        return 1;                           // Eof of the list
    }
    else
      break;
  }

4231 4232
  if (default_collation_name)
  {
unknown's avatar
unknown committed
4233 4234
    CHARSET_INFO *default_collation;
    default_collation= get_charset_by_name(default_collation_name, MYF(0));
unknown's avatar
unknown committed
4235 4236
    if (!default_collation)
    {
4237 4238 4239 4240
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
      buffered_logs.print();
      buffered_logs.cleanup();
#endif
4241
      sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
unknown's avatar
unknown committed
4242 4243 4244
      return 1;
    }
    if (!my_charset_same(default_charset_info, default_collation))
4245
    {
4246
      sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
4247 4248 4249 4250 4251 4252
		      default_collation_name,
		      default_charset_info->csname);
      return 1;
    }
    default_charset_info= default_collation;
  }
4253
  /* Set collactions that depends on the default collation */
4254 4255
  global_system_variables.collation_server= default_charset_info;
  global_system_variables.collation_database= default_charset_info;
4256
  if (is_supported_parser_charset(default_charset_info))
4257
  {
4258 4259 4260
    global_system_variables.collation_connection= default_charset_info;
    global_system_variables.character_set_results= default_charset_info;
    global_system_variables.character_set_client= default_charset_info;
4261 4262
  }
  else
4263
  {
4264 4265 4266 4267
    sql_print_warning("'%s' can not be used as client character set. "
                      "'%s' will be used as default client character set.",
                      default_charset_info->csname,
                      my_charset_latin1.csname);
4268 4269 4270 4271
    global_system_variables.collation_connection= &my_charset_latin1;
    global_system_variables.character_set_results= &my_charset_latin1;
    global_system_variables.character_set_client= &my_charset_latin1;
  }
4272

4273
  if (!(character_set_filesystem=
unknown's avatar
unknown committed
4274 4275 4276 4277 4278
        get_charset_by_csname(character_set_filesystem_name,
                              MY_CS_PRIMARY, MYF(MY_WME))))
    return 1;
  global_system_variables.character_set_filesystem= character_set_filesystem;

4279 4280 4281
  if (!(my_default_lc_time_names=
        my_locale_by_name(lc_time_names_name)))
  {
unknown's avatar
unknown committed
4282
    sql_print_error("Unknown locale: '%s'", lc_time_names_name);
4283 4284 4285
    return 1;
  }
  global_system_variables.lc_time_names= my_default_lc_time_names;
4286

4287
  /* check log options and issue warnings if needed */
4288 4289
  if (opt_log && opt_logname && *opt_logname &&
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4290 4291
    sql_print_warning("Although a path was specified for the "
                      "--log option, log tables are used. "
4292
                      "To enable logging to files use the --log-output option.");
4293

Monty's avatar
Monty committed
4294 4295
  if (global_system_variables.sql_log_slow && opt_slow_logname &&
      *opt_slow_logname &&
4296
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4297
    sql_print_warning("Although a path was specified for the "
Konstantin Osipov's avatar
Konstantin Osipov committed
4298
                      "--log-slow-queries option, log tables are used. "
4299
                      "To enable logging to files use the --log-output=file option.");
4300

Sergei Golubchik's avatar
Sergei Golubchik committed
4301 4302 4303 4304
  if (!opt_logname || !*opt_logname)
    make_default_log_name(&opt_logname, ".log", false);
  if (!opt_slow_logname || !*opt_slow_logname)
    make_default_log_name(&opt_slow_logname, "-slow.log", false);
4305

4306 4307 4308 4309 4310 4311
#if defined(ENABLED_DEBUG_SYNC)
  /* Initialize the debug sync facility. See debug_sync.cc. */
  if (debug_sync_init())
    return 1; /* purecov: tested */
#endif /* defined(ENABLED_DEBUG_SYNC) */

4312
#if (ENABLE_TEMP_POOL)
4313
  if (use_temp_pool && my_bitmap_init(&temp_pool,0,1024,1))
4314
    return 1;
4315 4316 4317 4318
#else
  use_temp_pool= 0;
#endif

4319
  if (my_dboptions_cache_init())
unknown's avatar
unknown committed
4320 4321
    return 1;

4322 4323 4324 4325 4326 4327
  /*
    Ensure that lower_case_table_names is set on system where we have case
    insensitive names.  If this is not done the users MyISAM tables will
    get corrupted if accesses with names of different case.
  */
  DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
Sergei Golubchik's avatar
Sergei Golubchik committed
4328 4329
  SYSVAR_AUTOSIZE(lower_case_file_system,
                  test_if_case_insensitive(mysql_real_data_home));
4330
  if (!lower_case_table_names && lower_case_file_system == 1)
4331 4332 4333
  {
    if (lower_case_table_names_used)
    {
4334 4335
      sql_print_error("The server option 'lower_case_table_names' is "
                      "configured to use case sensitive table names but the "
4336 4337 4338
                      "data directory resides on a case-insensitive file system. "
                      "Please use a case sensitive file system for your data "
                      "directory or switch to a case-insensitive table name "
4339 4340
                      "mode.");
      return 1;
4341 4342 4343 4344
    }
    else
    {
      if (global_system_variables.log_warnings)
Sergei Golubchik's avatar
Sergei Golubchik committed
4345 4346 4347
	sql_print_warning("Setting lower_case_table_names=2 because file "
                  "system for %s is case insensitive", mysql_real_data_home);
      SYSVAR_AUTOSIZE(lower_case_table_names, 2);
4348 4349 4350
    }
  }
  else if (lower_case_table_names == 2 &&
4351
           !(lower_case_file_system= (lower_case_file_system == 1)))
4352 4353 4354 4355 4356 4357
  {
    if (global_system_variables.log_warnings)
      sql_print_warning("lower_case_table_names was set to 2, even though your "
                        "the file system '%s' is case sensitive.  Now setting "
                        "lower_case_table_names to 0 to avoid future problems.",
			mysql_real_data_home);
Sergei Golubchik's avatar
Sergei Golubchik committed
4358
    SYSVAR_AUTOSIZE(lower_case_table_names, 0);
4359
  }
4360 4361
  else
  {
4362
    lower_case_file_system= (lower_case_file_system == 1);
4363
  }
4364 4365 4366 4367 4368 4369

  /* Reset table_alias_charset, now that lower_case_table_names is set. */
  table_alias_charset= (lower_case_table_names ?
			files_charset_info :
			&my_charset_bin);

4370 4371 4372 4373 4374 4375
  if (ignore_db_dirs_process_additions())
  {
    sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
    return 1;
  }

4376 4377
  global_system_variables.in_subquery_conversion_threshold= IN_SUBQUERY_CONVERSION_THRESHOLD;

4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391
#ifdef WITH_WSREP
  /*
    We need to initialize auxiliary variables, that will be
    further keep the original values of auto-increment options
    as they set by the user. These variables used to restore
    user-defined values of the auto-increment options after
    setting of the wsrep_auto_increment_control to 'OFF'.
  */
  global_system_variables.saved_auto_increment_increment=
    global_system_variables.auto_increment_increment;
  global_system_variables.saved_auto_increment_offset=
    global_system_variables.auto_increment_offset;
#endif /* WITH_WSREP */

unknown's avatar
unknown committed
4392 4393
  return 0;
}
unknown's avatar
unknown committed
4394

4395 4396

static int init_thread_environment()
unknown's avatar
unknown committed
4397
{
4398
  DBUG_ENTER("init_thread_environment");
4399
  server_threads.init();
Michael Widenius's avatar
Michael Widenius committed
4400
  mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST);
4401
  mysql_mutex_init(key_LOCK_start_thread, &LOCK_start_thread, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4402
  mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4403
  mysql_mutex_init(key_LOCK_delayed_insert,
Marc Alff's avatar
Marc Alff committed
4404 4405 4406 4407 4408
                   &LOCK_delayed_insert, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_delayed_status,
                   &LOCK_delayed_status, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_delayed_create,
                   &LOCK_delayed_create, MY_MUTEX_INIT_SLOW);
Marc Alff's avatar
Marc Alff committed
4409 4410 4411 4412 4413
  mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_global_system_variables,
                   &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
unknown's avatar
unknown committed
4414
  mysql_mutex_record_order(&LOCK_active_mi, &LOCK_global_system_variables);
4415
  mysql_prlock_init(key_rwlock_LOCK_system_variables_hash,
Marc Alff's avatar
Marc Alff committed
4416 4417 4418 4419 4420
                    &LOCK_system_variables_hash);
  mysql_mutex_init(key_LOCK_prepared_stmt_count,
                   &LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_error_messages,
                   &LOCK_error_messages, MY_MUTEX_INIT_FAST);
4421
  mysql_mutex_init(key_LOCK_uuid_short_generator,
Sergei Golubchik's avatar
Sergei Golubchik committed
4422
                   &LOCK_short_uuid_generator, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4423 4424
  mysql_mutex_init(key_LOCK_connection_count,
                   &LOCK_connection_count, MY_MUTEX_INIT_FAST);
4425 4426
  mysql_mutex_init(key_LOCK_thread_id,
                   &LOCK_thread_id, MY_MUTEX_INIT_FAST);
4427 4428 4429 4430 4431 4432 4433
  mysql_mutex_init(key_LOCK_stats, &LOCK_stats, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_global_user_client_stats,
                   &LOCK_global_user_client_stats, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_global_table_stats,
                   &LOCK_global_table_stats, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_global_index_stats,
                   &LOCK_global_index_stats, MY_MUTEX_INIT_FAST);
Sergei Golubchik's avatar
Sergei Golubchik committed
4434 4435
  mysql_mutex_init(key_LOCK_prepare_ordered, &LOCK_prepare_ordered,
                   MY_MUTEX_INIT_SLOW);
4436
  mysql_cond_init(key_COND_prepare_ordered, &COND_prepare_ordered, NULL);
4437 4438
  mysql_mutex_init(key_LOCK_after_binlog_sync, &LOCK_after_binlog_sync,
                   MY_MUTEX_INIT_SLOW);
Sergei Golubchik's avatar
Sergei Golubchik committed
4439 4440
  mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered,
                   MY_MUTEX_INIT_SLOW);
4441
  mysql_mutex_init(key_LOCK_slave_background, &LOCK_slave_background,
4442
                   MY_MUTEX_INIT_SLOW);
4443
  mysql_cond_init(key_COND_slave_background, &COND_slave_background, NULL);
4444

4445
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
4446 4447
  mysql_mutex_init(key_LOCK_des_key_file,
                   &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
4448
#ifdef HAVE_OPENSSL10
unknown's avatar
unknown committed
4449 4450 4451
  openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
                                                     sizeof(openssl_lock_t));
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
4452
    mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
unknown's avatar
unknown committed
4453 4454 4455 4456
  CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
  CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
  CRYPTO_set_dynlock_lock_callback(openssl_lock);
  CRYPTO_set_locking_callback(openssl_lock_function);
4457 4458
#endif /* HAVE_OPENSSL10 */
#endif /* HAVE_OPENSSL */
Marc Alff's avatar
Marc Alff committed
4459 4460
  mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
  mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
4461
  mysql_rwlock_init(key_rwlock_LOCK_ssl_refresh, &LOCK_ssl_refresh);
Marc Alff's avatar
Marc Alff committed
4462
  mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
4463
  mysql_rwlock_init(key_rwlock_LOCK_all_status_vars, &LOCK_all_status_vars);
Marc Alff's avatar
Marc Alff committed
4464
  mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
4465
  mysql_cond_init(key_COND_start_thread, &COND_start_thread, NULL);
Marc Alff's avatar
Marc Alff committed
4466
  mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
unknown's avatar
SCRUM  
unknown committed
4467
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
4468
  mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
4469
#endif
Marc Alff's avatar
Marc Alff committed
4470 4471 4472
  mysql_mutex_init(key_LOCK_server_started,
                   &LOCK_server_started, MY_MUTEX_INIT_FAST);
  mysql_cond_init(key_COND_server_started, &COND_server_started, NULL);
unknown's avatar
Merge  
unknown committed
4473
  sp_cache_init();
4474
#ifdef HAVE_EVENT_SCHEDULER
4475
  Events::init_mutexes();
4476
#endif
4477
  init_show_explain_psi_keys();
unknown's avatar
unknown committed
4478 4479 4480 4481 4482
  /* Parameter for threads created for connections */
  (void) pthread_attr_init(&connection_attrib);
  (void) pthread_attr_setdetachstate(&connection_attrib,
				     PTHREAD_CREATE_DETACHED);
  pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
unknown's avatar
unknown committed
4483

4484 4485
#ifdef HAVE_REPLICATION
  rpl_init_gtid_slave_state();
4486
  rpl_init_gtid_waiting();
4487 4488
#endif

4489
  DBUG_RETURN(0);
unknown's avatar
unknown committed
4490 4491
}

4492

4493
#ifdef HAVE_OPENSSL10
4494
static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
4495
{
4496
  openssl_lock_t *lock= new openssl_lock_t;
4497
  mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
4498 4499 4500 4501
  return lock;
}


4502
static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
4503 4504
				    int line)
{
4505
  mysql_rwlock_destroy(&lock->lock);
4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521
  delete lock;
}


static void openssl_lock_function(int mode, int n, const char *file, int line)
{
  if (n < 0 || n > CRYPTO_num_locks())
  {
    /* Lock number out of bounds. */
    sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
    abort();
  }
  openssl_lock(mode, &openssl_stdlocks[n], file, line);
}


4522
static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
4523 4524 4525 4526 4527 4528 4529 4530
			 int line)
{
  int err;
  char const *what;

  switch (mode) {
  case CRYPTO_LOCK|CRYPTO_READ:
    what = "read lock";
4531
    err= mysql_rwlock_rdlock(&lock->lock);
4532 4533 4534
    break;
  case CRYPTO_LOCK|CRYPTO_WRITE:
    what = "write lock";
4535
    err= mysql_rwlock_wrlock(&lock->lock);
4536 4537 4538 4539
    break;
  case CRYPTO_UNLOCK|CRYPTO_READ:
  case CRYPTO_UNLOCK|CRYPTO_WRITE:
    what = "unlock";
4540
    err= mysql_rwlock_unlock(&lock->lock);
4541 4542 4543 4544 4545 4546
    break;
  default:
    /* Unknown locking mode. */
    sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
    abort();
  }
4547
  if (err)
4548
  {
4549
    sql_print_error("Fatal: can't %s OpenSSL lock", what);
4550 4551 4552
    abort();
  }
}
4553
#endif /* HAVE_OPENSSL10 */
4554

4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608

struct SSL_ACCEPTOR_STATS
{
  long accept;
  long accept_good;
  long cache_size;
  long verify_mode;
  long verify_depth;
  long zero;
  const char *session_cache_mode;

  SSL_ACCEPTOR_STATS():
    accept(),accept_good(),cache_size(),verify_mode(),verify_depth(),zero(),
    session_cache_mode("NONE")
  {
  }

  void init()
  {
    DBUG_ASSERT(ssl_acceptor_fd !=0 && ssl_acceptor_fd->ssl_context != 0);
    SSL_CTX *ctx= ssl_acceptor_fd->ssl_context;
    accept= 0;
    accept_good= 0;
    verify_mode= SSL_CTX_get_verify_mode(ctx);
    verify_depth= SSL_CTX_get_verify_depth(ctx);
    cache_size= SSL_CTX_sess_get_cache_size(ctx);
    switch (SSL_CTX_get_session_cache_mode(ctx))
    {
    case SSL_SESS_CACHE_OFF:
      session_cache_mode= "OFF"; break;
    case SSL_SESS_CACHE_CLIENT:
      session_cache_mode= "CLIENT"; break;
    case SSL_SESS_CACHE_SERVER:
      session_cache_mode= "SERVER"; break;
    case SSL_SESS_CACHE_BOTH:
      session_cache_mode= "BOTH"; break;
    case SSL_SESS_CACHE_NO_AUTO_CLEAR:
      session_cache_mode= "NO_AUTO_CLEAR"; break;
    case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
      session_cache_mode= "NO_INTERNAL_LOOKUP"; break;
    default:
      session_cache_mode= "Unknown"; break;
    }
  }
};

static SSL_ACCEPTOR_STATS ssl_acceptor_stats;
void ssl_acceptor_stats_update(int sslaccept_ret)
{
  statistic_increment(ssl_acceptor_stats.accept, &LOCK_status);
  if (!sslaccept_ret)
    statistic_increment(ssl_acceptor_stats.accept_good,&LOCK_status);
}

unknown's avatar
unknown committed
4609 4610
static void init_ssl()
{
unknown's avatar
unknown committed
4611
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
4612 4613
  if (opt_use_ssl)
  {
4614 4615
    enum enum_ssl_init_error error= SSL_INITERR_NOERROR;

4616 4617 4618
    /* having ssl_acceptor_fd != 0 signals the use of SSL */
    ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
					  opt_ssl_ca, opt_ssl_capath,
4619 4620
					  opt_ssl_cipher, &error,
                                          opt_ssl_crl, opt_ssl_crlpath);
4621
    DBUG_PRINT("info",("ssl_acceptor_fd: %p", ssl_acceptor_fd));
unknown's avatar
unknown committed
4622
    if (!ssl_acceptor_fd)
4623
    {
4624
      sql_print_warning("Failed to setup SSL");
4625
      sql_print_warning("SSL error: %s", sslGetErrString(error));
unknown's avatar
unknown committed
4626
      opt_use_ssl = 0;
4627
      have_ssl= SHOW_OPTION_DISABLED;
4628
    }
4629 4630 4631
    else
      ssl_acceptor_stats.init();

4632 4633 4634 4635 4636 4637 4638 4639
    if (global_system_variables.log_warnings > 0)
    {
      ulong err;
      while ((err= ERR_get_error()))
        sql_print_warning("SSL error: %s", ERR_error_string(err, NULL));
    }
    else
      ERR_remove_state(0);
4640 4641 4642
  }
  else
  {
4643
    have_ssl= SHOW_OPTION_DISABLED;
unknown's avatar
unknown committed
4644
  }
unknown's avatar
unknown committed
4645 4646
  if (des_key_file)
    load_des_key_file(des_key_file);
unknown's avatar
unknown committed
4647
#endif /* HAVE_OPENSSL && ! EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
4648
}
unknown's avatar
unknown committed
4649

4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675
/* Reinitialize SSL (FLUSH SSL) */
int reinit_ssl()
{
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
  if (!opt_use_ssl)
    return 0;

  enum enum_ssl_init_error error = SSL_INITERR_NOERROR;
  st_VioSSLFd *new_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
    opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher, &error, opt_ssl_crl, opt_ssl_crlpath);

  if (!new_fd)
  {
    my_printf_error(ER_UNKNOWN_ERROR, "Failed to refresh SSL, error: %s", MYF(0),
      sslGetErrString(error));
#ifndef HAVE_YASSL
    ERR_clear_error();
#endif
    return 1;
  }
  mysql_rwlock_wrlock(&LOCK_ssl_refresh);
  free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
  ssl_acceptor_fd= new_fd;
  ssl_acceptor_stats.init();
  mysql_rwlock_unlock(&LOCK_ssl_refresh);
#endif
4676
  return 0;
4677
}
4678

4679 4680 4681
static void end_ssl()
{
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
4682
#ifndef EMBEDDED_LIBRARY
4683 4684 4685 4686 4687
  if (ssl_acceptor_fd)
  {
    free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
    ssl_acceptor_fd= 0;
  }
Konstantin Osipov's avatar
Konstantin Osipov committed
4688
#endif /* ! EMBEDDED_LIBRARY */
4689 4690 4691
#endif /* HAVE_OPENSSL */
}

4692 4693 4694 4695 4696 4697 4698 4699
#ifdef _WIN32
/**
  Registers a file to be collected when Windows Error Reporting creates a crash 
  report.
*/
#include <werapi.h>
static void add_file_to_crash_report(char *file)
{
4700 4701
  wchar_t wfile[MAX_PATH+1]= {0};
  if (mbstowcs(wfile, file, MAX_PATH) != (size_t)-1)
4702
  {
4703
    WerRegisterFile(wfile, WerRegFileTypeOther, WER_FILE_ANONYMOUS_DATA);
4704 4705 4706
  }
}
#endif
4707

4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719
#define init_default_storage_engine(X,Y) \
  init_default_storage_engine_impl(#X, X, &global_system_variables.Y)

static int init_default_storage_engine_impl(const char *opt_name,
                                            char *engine_name, plugin_ref *res)
{
  if (!engine_name)
  {
    *res= 0;
    return 0;
  }

4720
  LEX_CSTRING name= { engine_name, strlen(engine_name) };
4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753
  plugin_ref plugin;
  handlerton *hton;
  if ((plugin= ha_resolve_by_name(0, &name, false)))
    hton= plugin_hton(plugin);
  else
  {
    sql_print_error("Unknown/unsupported storage engine: %s", engine_name);
    return 1;
  }
  if (!ha_storage_engine_is_enabled(hton))
  {
    if (!opt_bootstrap)
    {
      sql_print_error("%s (%s) is not available", opt_name, engine_name);
      return 1;
    }
    DBUG_ASSERT(*res);
  }
  else
  {
    /*
      Need to unlock as global_system_variables.table_plugin
      was acquired during plugin_init()
    */
    mysql_mutex_lock(&LOCK_global_system_variables);
    if (*res)
      plugin_unlock(0, *res);
    *res= plugin;
    mysql_mutex_unlock(&LOCK_global_system_variables);
  }
  return 0;
}

4754 4755 4756 4757 4758 4759

static int
init_gtid_pos_auto_engines(void)
{
  plugin_ref *plugins;

4760 4761 4762 4763 4764 4765 4766 4767
  /*
    For the command-line option --gtid_pos_auto_engines, we allow (and ignore)
    engines that are unknown. This is convenient, since it allows to set
    default auto-create engines that might not be used by particular users.
    The option sets a list of storage engines that will have gtid position
    table auto-created for them if needed. And if the engine is not available,
    then it will certainly not be needed.
  */
4768
  if (gtid_pos_auto_engines)
4769 4770
    plugins= resolve_engine_list(NULL, gtid_pos_auto_engines,
                                 strlen(gtid_pos_auto_engines), false, false);
4771
  else
4772
    plugins= resolve_engine_list(NULL, "", 0, false, false);
4773 4774 4775 4776 4777 4778 4779 4780 4781
  if (!plugins)
    return 1;
  mysql_mutex_lock(&LOCK_global_system_variables);
  opt_gtid_pos_auto_plugins= plugins;
  mysql_mutex_unlock(&LOCK_global_system_variables);
  return 0;
}


unknown's avatar
unknown committed
4782 4783
static int init_server_components()
{
4784
  DBUG_ENTER("init_server_components");
unknown's avatar
unknown committed
4785 4786 4787 4788
  /*
    We need to call each of these following functions to ensure that
    all things are initialized so that unireg_abort() doesn't fail
  */
4789
  mdl_init();
4790
  if (tdc_init() || hostname_cache_init())
4791
    unireg_abort(1);
unknown's avatar
unknown committed
4792

4793
  query_cache_set_min_res_unit(query_cache_min_res_unit);
4794 4795 4796 4797 4798 4799 4800 4801
  query_cache_result_size_limit(query_cache_limit);
  /* if we set size of QC non zero in config then probably we want it ON */
  if (query_cache_size != 0 &&
      global_system_variables.query_cache_type == 0 &&
      !IS_SYSVAR_AUTOSIZE(&query_cache_size))
  {
    global_system_variables.query_cache_type= 1;
  }
unknown's avatar
unknown committed
4802
  query_cache_init();
4803 4804
  DBUG_ASSERT(query_cache_size < ULONG_MAX);
  query_cache_resize((ulong)query_cache_size);
4805
  my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
4806
  setup_fpu();
unknown's avatar
unknown committed
4807
  init_thr_lock();
4808
  backup_init();
Monty's avatar
Monty committed
4809

Monty's avatar
Monty committed
4810 4811 4812 4813 4814 4815 4816 4817
#ifndef EMBEDDED_LIBRARY
  if (init_thr_timer(thread_scheduler->max_threads + extra_max_connections))
  {
    fprintf(stderr, "Can't initialize timers\n");
    unireg_abort(1);
  }
#endif

4818
  my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345);
Sergei Golubchik's avatar
Sergei Golubchik committed
4819
  wt_init();
unknown's avatar
unknown committed
4820

4821 4822
  /* Setup logs */

Monty's avatar
Monty committed
4823 4824
  setup_log_handling();

4825 4826 4827 4828 4829
  /*
    Enable old-fashioned error log, except when the user has requested
    help information. Since the implementation of plugin server
    variables the help output is now written much later.
  */
4830 4831 4832 4833 4834
#ifdef _WIN32
  if (opt_console)
   opt_error_log= false;
#endif

4835
  if (opt_error_log && !opt_abort)
4836 4837
  {
    if (!log_error_file_ptr[0])
Sergei Golubchik's avatar
Sergei Golubchik committed
4838
    {
4839
      fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
4840
                MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
Sergei Golubchik's avatar
Sergei Golubchik committed
4841 4842
      SYSVAR_AUTOSIZE(log_error_file_ptr, log_error_file);
    }
4843
    else
Sergei Golubchik's avatar
Sergei Golubchik committed
4844
    {
4845 4846
      fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
                MY_UNPACK_FILENAME | MY_SAFE_PATH);
Sergei Golubchik's avatar
Sergei Golubchik committed
4847 4848
      log_error_file_ptr= log_error_file;
    }
4849
    if (!log_error_file[0])
4850
      opt_error_log= 0;                         // Too long file name
4851 4852
    else
    {
4853
      my_bool res;
4854
#ifndef EMBEDDED_LIBRARY
4855 4856 4857
      res= reopen_fstreams(log_error_file, stdout, stderr);
#else
      res= reopen_fstreams(log_error_file, NULL, stderr);
4858
#endif
4859 4860 4861

      if (!res)
        setbuf(stderr, NULL);
4862 4863 4864 4865 4866

#ifdef _WIN32
      /* Add error log to windows crash reporting. */
      add_file_to_crash_report(log_error_file);
#endif
4867 4868 4869
    }
  }

4870 4871
  /* set up the hook before initializing plugins which may use it */
  error_handler_hook= my_message_sql;
Sergei Golubchik's avatar
Sergei Golubchik committed
4872
  proc_info_hook= set_thd_stage_info;
4873

Marc Alff's avatar
Marc Alff committed
4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  /*
    Parsing the performance schema command line option may have reported
    warnings/information messages.
    Now that the logger is finally available, and redirected
    to the proper file when the --log--error option is used,
    print the buffered messages to the log.
  */
  buffered_logs.print();
  buffered_logs.cleanup();
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */

4886 4887 4888 4889 4890 4891 4892 4893 4894
#ifndef EMBEDDED_LIBRARY
  /*
    Now that the logger is available, redirect character set
    errors directly to the logger
    (instead of the buffered_logs used at the server startup time).
  */
  my_charset_error_reporter= charset_error_reporter;
#endif

4895
  xid_cache_init();
unknown's avatar
unknown committed
4896

unknown's avatar
unknown committed
4897
  /* need to configure logging before initializing storage engines */
Sergei Golubchik's avatar
Sergei Golubchik committed
4898
  if (!opt_bin_log_used && !WSREP_ON)
unknown's avatar
unknown committed
4899
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
4900
    if (opt_log_slave_updates)
4901 4902
      sql_print_warning("You need to use --log-bin to make "
                        "--log-slave-updates work.");
Sergei Golubchik's avatar
Sergei Golubchik committed
4903
    if (binlog_format_used)
4904 4905
      sql_print_warning("You need to use --log-bin to make "
                        "--binlog-format work.");
4906
  }
4907

4908
  /* Check that we have not let the format to unspecified at this point */
4909
  DBUG_ASSERT((uint)global_system_variables.binlog_format <=
4910
              array_elements(binlog_format_names)-1);
4911

unknown's avatar
unknown committed
4912
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
4913 4914
  if (opt_log_slave_updates && replicate_same_server_id)
  {
4915 4916
    if (opt_bin_log)
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
4917 4918 4919
      sql_print_error("using --replicate-same-server-id in conjunction with "
                      "--log-slave-updates is impossible, it would lead to "
                      "infinite loops in this server.");
4920 4921 4922
      unireg_abort(1);
    }
    else
Sergei Golubchik's avatar
Sergei Golubchik committed
4923 4924 4925 4926
      sql_print_warning("using --replicate-same-server-id in conjunction with "
                        "--log-slave-updates would lead to infinite loops in "
                        "this server. However this will be ignored as the "
                        "--log-bin option is not defined.");
unknown's avatar
unknown committed
4927
  }
unknown's avatar
unknown committed
4928
#endif
4929

unknown's avatar
Merge  
unknown committed
4930
  if (opt_bin_log)
4931
  {
4932 4933
    /* Reports an error and aborts, if the --log-bin's path 
       is a directory.*/
4934
    if (opt_bin_logname[0] && 
4935 4936
        opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
4937 4938
      sql_print_error("Path '%s' is a directory name, please specify "
                      "a file name for --log-bin option", opt_bin_logname);
4939 4940 4941 4942 4943 4944 4945 4946 4947
      unireg_abort(1);
    }

    /* Reports an error and aborts, if the --log-bin-index's path 
       is a directory.*/
    if (opt_binlog_index_name && 
        opt_binlog_index_name[strlen(opt_binlog_index_name) - 1] 
        == FN_LIBCHAR)
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
4948 4949 4950
      sql_print_error("Path '%s' is a directory name, please specify "
                      "a file name for --log-bin-index option",
                      opt_binlog_index_name);
4951 4952 4953
      unireg_abort(1);
    }

unknown's avatar
Merge  
unknown committed
4954 4955 4956
    char buf[FN_REFLEN];
    const char *ln;
    ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
4957
    if (!opt_bin_logname[0] && !opt_binlog_index_name)
4958 4959
    {
      /*
unknown's avatar
Merge  
unknown committed
4960 4961 4962 4963 4964
        User didn't give us info to name the binlog index file.
        Picking `hostname`-bin.index like did in 4.x, causes replication to
        fail if the hostname is changed later. So, we would like to instead
        require a name. But as we don't want to break many existing setups, we
        only give warning, not error.
4965
      */
4966 4967 4968 4969
      sql_print_warning("No argument was provided to --log-bin and "
                        "neither --log-basename or --log-bin-index where "
                        "used;  This may cause repliction to break when this "
                        "server acts as a master and has its hostname "
Sergei Golubchik's avatar
Sergei Golubchik committed
4970
                        "changed! Please use '--log-basename=%s' or "
4971
                        "'--log-bin=%s' to avoid this problem.",
Sergei Golubchik's avatar
Sergei Golubchik committed
4972
                        opt_log_basename, ln);
4973
    }
unknown's avatar
Merge  
unknown committed
4974
    if (ln == buf)
4975
      opt_bin_logname= my_once_strdup(buf, MYF(MY_WME));
4976 4977
  }

4978 4979 4980 4981 4982 4983
  /*
    Since some wsrep threads (THDs) are create before plugins are
    initialized, LOCK_plugin mutex needs to be initialized here.
  */
  plugin_mutex_init();

4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995
  /*
    Wsrep initialization must happen at this point, because:
    - opt_bin_logname must be known when starting replication
      since SST may need it
    - SST may modify binlog index file, so it must be opened
      after SST has happened

    We also (unconditionally) initialize wsrep LOCKs and CONDs.
    It is because they are used while accessing wsrep system
    variables even when a wsrep provider is not loaded.
  */

4996 4997 4998
  /* It's now safe to use thread specific memory */
  mysqld_server_initialized= 1;

Monty's avatar
Monty committed
4999
#ifndef EMBEDDED_LIBRARY
5000
  wsrep_thr_init();
Monty's avatar
Monty committed
5001
#endif
5002

Brave Galera Crew's avatar
Brave Galera Crew committed
5003 5004 5005
#ifdef WITH_WSREP
  if (wsrep_init_server()) unireg_abort(1);
  if (WSREP_ON && !wsrep_recovery && !opt_abort)
5006 5007 5008 5009
  {
    if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
    {
      wsrep_provider_init(WSREP_NONE);
5010 5011
      if (wsrep_init())
        unireg_abort(1);
5012 5013 5014 5015
    }
    else // full wsrep initialization
    {
      // add basedir/bin to PATH to resolve wsrep script names
5016 5017
      char* const tmp_path= (char*)my_alloca(strlen(mysql_home) +
                                             strlen("/bin") + 1);
5018 5019 5020 5021 5022 5023 5024 5025 5026 5027
      if (tmp_path)
      {
        strcpy(tmp_path, mysql_home);
        strcat(tmp_path, "/bin");
        wsrep_prepend_PATH(tmp_path);
      }
      else
      {
        WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
      }
5028
      my_afree(tmp_path);
5029 5030 5031 5032 5033 5034 5035 5036 5037

      if (wsrep_before_SE())
      {
        set_ports(); // this is also called in network_init() later but we need
                     // to know mysqld_port now - lp:1071882
        wsrep_init_startup(true);
      }
    }
  }
Brave Galera Crew's avatar
Brave Galera Crew committed
5038
#endif /* WITH_WSREP */
5039

5040 5041 5042 5043 5044 5045 5046
  if (opt_bin_log)
  {
    if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
                                      TRUE))
    {
      unireg_abort(1);
    }
5047

5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084
    log_bin_basename=
      rpl_make_log_name(opt_bin_logname, pidfile_name,
                        opt_bin_logname ? "" : "-bin");
    log_bin_index=
      rpl_make_log_name(opt_binlog_index_name, log_bin_basename, ".index");
    if (log_bin_basename == NULL || log_bin_index == NULL)
    {
      sql_print_error("Unable to create replication path names:"
                      " out of memory or path names too long"
                      " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
                      " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
      unireg_abort(1);
    }
  }

#ifndef EMBEDDED_LIBRARY
  DBUG_PRINT("debug",
             ("opt_bin_logname: %s, opt_relay_logname: %s, pidfile_name: %s",
              opt_bin_logname, opt_relay_logname, pidfile_name));
  if (opt_relay_logname)
  {
    relay_log_basename=
      rpl_make_log_name(opt_relay_logname, pidfile_name,
                        opt_relay_logname ? "" : "-relay-bin");
    relay_log_index=
      rpl_make_log_name(opt_relaylog_index_name, relay_log_basename, ".index");
    if (relay_log_basename == NULL || relay_log_index == NULL)
    {
      sql_print_error("Unable to create replication path names:"
                      " out of memory or path names too long"
                      " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
                      " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
      unireg_abort(1);
    }
  }
#endif /* !EMBEDDED_LIBRARY */

5085
  /* call ha_init_key_cache() on all key caches to init them */
5086
  process_key_caches(&ha_init_key_cache, 0);
5087

5088 5089 5090
  init_global_table_stats();
  init_global_index_stats();

5091
  /* Allow storage engine to give real error messages */
5092
  if (unlikely(ha_init_errors()))
5093 5094
    DBUG_RETURN(1);

5095 5096
  tc_log= 0; // ha_initialize_handlerton() needs that

Marc Alff's avatar
Marc Alff committed
5097
  if (plugin_init(&remaining_argc, remaining_argv,
5098
                  (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
5099
                  (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
5100 5101 5102
  {
    sql_print_error("Failed to initialize plugins.");
    unireg_abort(1);
unknown's avatar
unknown committed
5103
  }
5104
  plugins_are_initialized= TRUE;  /* Don't separate from init function */
unknown's avatar
unknown committed
5105

5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118
#ifdef HAVE_REPLICATION
  /*
    Semisync is not required by other components, which justifies its
    initialization at this point when thread specific memory is also available.
  */
  if (repl_semisync_master.init_object() ||
      repl_semisync_slave.init_object())
  {
    sql_print_error("Could not initialize semisync.");
    unireg_abort(1);
  }
#endif

5119
#ifndef EMBEDDED_LIBRARY
5120
  {
5121
    if (Session_tracker::server_boot_verify(system_charset_info))
5122 5123 5124 5125 5126 5127
    {
      sql_print_error("The variable session_track_system_variables has "
		      "invalid values.");
      unireg_abort(1);
    }
  }
5128
#endif //EMBEDDED_LIBRARY
5129

unknown's avatar
unknown committed
5130
  /* we do want to exit if there are any other unknown options */
Marc Alff's avatar
Marc Alff committed
5131
  if (remaining_argc > 1)
unknown's avatar
unknown committed
5132 5133
  {
    int ho_error;
unknown's avatar
unknown committed
5134
    struct my_option no_opts[]=
unknown's avatar
unknown committed
5135 5136 5137 5138 5139
    {
      {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
    };
    /*
      We need to eat any 'loose' arguments first before we conclude
unknown's avatar
unknown committed
5140
      that there are unprocessed options.
unknown's avatar
unknown committed
5141 5142
    */
    my_getopt_skip_unknown= 0;
unknown's avatar
unknown committed
5143

Marc Alff's avatar
Marc Alff committed
5144
    if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
5145
                                  mysqld_get_one_option)))
unknown's avatar
unknown committed
5146
      unireg_abort(ho_error);
Marc Alff's avatar
Marc Alff committed
5147 5148 5149
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
5150
    my_getopt_skip_unknown= TRUE;
unknown's avatar
unknown committed
5151

Marc Alff's avatar
Marc Alff committed
5152
    if (remaining_argc > 1)
unknown's avatar
unknown committed
5153
    {
5154
      fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n",
Marc Alff's avatar
Marc Alff committed
5155
              my_progname, remaining_argv[1]);
unknown's avatar
unknown committed
5156 5157
      unireg_abort(1);
    }
unknown's avatar
unknown committed
5158 5159
  }

5160 5161 5162
  if (init_io_cache_encryption())
    unireg_abort(1);

5163
  if (opt_abort)
5164 5165
    unireg_abort(0);

unknown's avatar
unknown committed
5166
  /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
5167 5168
  if (!DEFAULT_ERRMSGS[0][0])
    unireg_abort(1);  
unknown's avatar
unknown committed
5169

unknown's avatar
unknown committed
5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196
  /* We have to initialize the storage engines before CSV logging */
  if (ha_init())
  {
    sql_print_error("Can't init databases");
    unireg_abort(1);
  }

  if (opt_bootstrap)
    log_output_options= LOG_FILE;
  else
    logger.init_log_tables();

  if (log_output_options & LOG_NONE)
  {
    /*
      Issue a warining if there were specified additional options to the
      log-output along with NONE. Probably this wasn't what user wanted.
    */
    if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
      sql_print_warning("There were other values specified to "
                        "log-output besides NONE. Disabling slow "
                        "and general logs anyway.");
    logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
  }
  else
  {
    /* fall back to the log files if tables are not present */
5197
    LEX_CSTRING csv_name={STRING_WITH_LEN("csv")};
unknown's avatar
unknown committed
5198
    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
unknown's avatar
unknown committed
5199
    {
5200
      /* purecov: begin inspected */
unknown's avatar
unknown committed
5201 5202
      sql_print_error("CSV engine is not present, falling back to the "
                      "log files");
Sergei Golubchik's avatar
Sergei Golubchik committed
5203 5204
      SYSVAR_AUTOSIZE(log_output_options, 
                      (log_output_options & ~LOG_TABLE) | LOG_FILE);
5205
      /* purecov: end */
unknown's avatar
unknown committed
5206 5207
    }

Monty's avatar
Monty committed
5208 5209 5210
    logger.set_handlers(LOG_FILE,
                        global_system_variables.sql_log_slow ?
                        log_output_options:LOG_NONE,
unknown's avatar
unknown committed
5211 5212 5213
                        opt_log ? log_output_options:LOG_NONE);
  }

5214
  if (init_default_storage_engine(default_storage_engine, table_plugin))
5215
    unireg_abort(1);
5216 5217 5218 5219

  if (default_tmp_storage_engine && !*default_tmp_storage_engine)
    default_tmp_storage_engine= NULL;

5220 5221 5222
  if (enforced_storage_engine && !*enforced_storage_engine)
    enforced_storage_engine= NULL;

5223 5224 5225
  if (init_default_storage_engine(default_tmp_storage_engine, tmp_table_plugin))
    unireg_abort(1);

5226 5227 5228
  if (init_default_storage_engine(enforced_storage_engine, enforced_table_plugin))
    unireg_abort(1);

5229 5230 5231
  if (init_gtid_pos_auto_engines())
    unireg_abort(1);

Sergei Golubchik's avatar
Sergei Golubchik committed
5232
#ifdef USE_ARIA_FOR_TMP_TABLES
5233
  if (!ha_storage_engine_is_enabled(maria_hton) && !opt_bootstrap)
5234
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
5235
    sql_print_error("Aria engine is not enabled or did not start. The Aria engine must be enabled to continue as mysqld was configured with --with-aria-tmp-tables");
5236 5237 5238
    unireg_abort(1);
  }
#endif
5239

5240
#ifdef WITH_WSREP
5241 5242 5243 5244 5245 5246
  /*
    Now is the right time to initialize members of wsrep startup threads
    that rely on plugins and other related global system variables to be
    initialized. This initialization was not possible before, as plugins
    (and thus some global system variables) are initialized after wsrep
    startup threads are created.
5247 5248
    Note: This only needs to be done for rsync and mariabackup based SST
    methods.
5249
  */
5250 5251
  if (wsrep_before_SE())
    wsrep_plugins_post_init();
5252

5253 5254 5255 5256 5257 5258
  if (WSREP_ON && !opt_bin_log)
  {
    wsrep_emulate_bin_log= 1;
  }
#endif

5259
  tc_log= get_tc_log_implementation();
5260

unknown's avatar
unknown committed
5261
  if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
unknown's avatar
Merge  
unknown committed
5262 5263 5264 5265 5266
  {
    sql_print_error("Can't init tc log");
    unireg_abort(1);
  }

unknown's avatar
unknown committed
5267 5268 5269 5270 5271
  if (ha_recover(0))
  {
    unireg_abort(1);
  }

5272 5273
  if (opt_bin_log)
  {
5274 5275 5276
    int error;
    mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock();
    mysql_mutex_lock(log_lock);
Marko Mäkelä's avatar
Marko Mäkelä committed
5277
    error= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, 0,
5278
                              WRITE_CACHE, max_binlog_size, 0, TRUE);
5279
    mysql_mutex_unlock(log_lock);
5280
    if (unlikely(error))
5281
      unireg_abort(1);
5282
  }
unknown's avatar
Merge  
unknown committed
5283 5284 5285

#ifdef HAVE_REPLICATION
  if (opt_bin_log && expire_logs_days)
5286
  {
5287
    time_t purge_time= server_start_time - expire_logs_days*24*60*60;
unknown's avatar
Merge  
unknown committed
5288 5289
    if (purge_time >= 0)
      mysql_bin_log.purge_logs_before_date(purge_time);
5290
  }
unknown's avatar
Merge  
unknown committed
5291 5292 5293 5294
#endif

  if (opt_myisam_log)
    (void) mi_log(1);
unknown's avatar
unknown committed
5295

unknown's avatar
unknown committed
5296
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
5297
  if (locked_in_memory)
5298
  {
5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309
    int error;
    if (user_info)
    {
      DBUG_ASSERT(!getuid());
      if (setreuid((uid_t) -1, 0) == -1)
      {
        sql_perror("setreuid");
        unireg_abort(1);
      }
      error= mlockall(MCL_CURRENT);
      set_user(mysqld_user, user_info);
5310
    }
5311 5312 5313
    else
      error= mlockall(MCL_CURRENT);

5314
    if (unlikely(error))
5315
    {
5316
      if (global_system_variables.log_warnings)
5317
	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
unknown's avatar
unknown committed
5318
      locked_in_memory= 0;
5319 5320
    }
  }
5321 5322
#else
  locked_in_memory= 0;
5323
#endif
5324

5325
  ft_init_stopwords();
unknown's avatar
unknown committed
5326

unknown's avatar
unknown committed
5327
  init_max_user_conn();
5328
  init_update_queries();
5329 5330
  init_global_user_stats();
  init_global_client_stats();
5331 5332
  if (!opt_bootstrap)
    servers_init(0);
5333
  init_status_vars();
5334
  DBUG_RETURN(0);
unknown's avatar
unknown committed
5335
}
unknown's avatar
unknown committed
5336

5337

5338
#ifndef EMBEDDED_LIBRARY
5339
#ifdef _WIN32
5340
static void create_shutdown_event()
unknown's avatar
unknown committed
5341
{
5342 5343 5344
  hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
  // On "Stop Service" we have to do regular shutdown
  Service.SetShutdownEvent(hEventShutdown);
unknown's avatar
unknown committed
5345
}
5346 5347
#else /*_WIN32*/
#define create_shutdown_event()
5348 5349
#endif
#endif /* EMBEDDED_LIBRARY */
5350

5351
#ifndef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
5352

5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363
#ifndef DBUG_OFF
/*
  Debugging helper function to keep the locale database
  (see sql_locale.cc) and max_month_name_length and
  max_day_name_length variable values in consistent state.
*/
static void test_lc_time_sz()
{
  DBUG_ENTER("test_lc_time_sz");
  for (MY_LOCALE **loc= my_locales; *loc; loc++)
  {
5364 5365
    size_t max_month_len= 0;
    size_t max_day_len= 0;
5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389
    for (const char **month= (*loc)->month_names->type_names; *month; month++)
    {
      set_if_bigger(max_month_len,
                    my_numchars_mb(&my_charset_utf8_general_ci,
                                   *month, *month + strlen(*month)));
    }
    for (const char **day= (*loc)->day_names->type_names; *day; day++)
    {
      set_if_bigger(max_day_len,
                    my_numchars_mb(&my_charset_utf8_general_ci,
                                   *day, *day + strlen(*day)));
    }
    if ((*loc)->max_month_name_length != max_month_len ||
        (*loc)->max_day_name_length != max_day_len)
    {
      DBUG_PRINT("Wrong max day name(or month name) length for locale:",
                 ("%s", (*loc)->name));
      DBUG_ASSERT(0);
    }
  }
  DBUG_VOID_RETURN;
}
#endif//DBUG_OFF

5390

unknown's avatar
unknown committed
5391 5392 5393
#ifdef __WIN__
int win_main(int argc, char **argv)
#else
5394
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5395 5396
#endif
{
5397
#ifndef _WIN32
5398 5399
  /* We can't close stdin just now, because it may be booststrap mode. */
  bool please_close_stdin= fcntl(STDIN_FILENO, F_GETFD) >= 0;
5400
#endif
5401

Marc Alff's avatar
Marc Alff committed
5402 5403 5404 5405 5406
  /*
    Perform basic thread library and malloc initialization,
    to be able to read defaults files and parse options.
  */
  my_progname= argv[0];
5407
  sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early
5408 5409
  mysqld_server_started= mysqld_server_initialized= 0;

5410 5411 5412
  if (init_early_variables())
    exit(1);

5413 5414 5415
#ifdef HAVE_NPTL
  ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
#endif
5416 5417 5418
#ifndef _WIN32
  // For windows, my_init() is called from the win specific mysqld_main
  if (my_init())                 // init my_sys library & pthreads
Marc Alff's avatar
Marc Alff committed
5419
  {
5420
    fprintf(stderr, "my_init() failed.");
Marc Alff's avatar
Marc Alff committed
5421 5422
    return 1;
  }
5423
#endif
5424

Marc Alff's avatar
Marc Alff committed
5425 5426
  orig_argc= argc;
  orig_argv= argv;
5427
  my_getopt_use_args_separator= TRUE;
5428
  load_defaults_or_exit(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv);
5429
  my_getopt_use_args_separator= FALSE;
Marc Alff's avatar
Marc Alff committed
5430 5431 5432 5433 5434 5435 5436 5437 5438 5439
  defaults_argc= argc;
  defaults_argv= argv;
  remaining_argc= argc;
  remaining_argv= argv;

  /* Must be initialized early for comparison of options name */
  system_charset_info= &my_charset_utf8_general_ci;

  sys_var_init();

5440
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5441
  /*
5442
    Initialize the array of performance schema instrument configurations.
Marc Alff's avatar
Marc Alff committed
5443
  */
5444 5445
  init_pfs_instrument_array();
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
Marc Alff's avatar
Marc Alff committed
5446 5447 5448 5449 5450 5451
  /*
    Logs generated while parsing the command line
    options are buffered and printed later.
  */
  buffered_logs.init();
  my_getopt_error_reporter= buffered_option_error_reporter;
5452
  my_charset_error_reporter= buffered_option_error_reporter;
5453
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5454
  pfs_param.m_pfs_instrument= const_cast<char*>("");
5455
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5456
  my_timer_init(&sys_timer_info);
5457

5458
  int ho_error __attribute__((unused))= handle_early_options();
Marc Alff's avatar
Marc Alff committed
5459

5460 5461 5462 5463 5464 5465
  /* fix tdc_size */
  if (IS_SYSVAR_AUTOSIZE(&tdc_size))
  {
    SYSVAR_AUTOSIZE(tdc_size, MY_MIN(400 + tdc_size / 2, 2000));
  }

5466
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5467 5468
  if (ho_error == 0)
  {
5469
    if (pfs_param.m_enabled  && !opt_help && !opt_bootstrap)
Marc Alff's avatar
Marc Alff committed
5470
    {
5471
      /* Add sizing hints from the server sizing parameters. */
5472 5473
      pfs_param.m_hints.m_table_definition_cache= tdc_size;
      pfs_param.m_hints.m_table_open_cache= tc_size;
5474 5475
      pfs_param.m_hints.m_max_connections= max_connections;
      pfs_param.m_hints.m_open_files_limit= open_files_limit;
Marc Alff's avatar
Marc Alff committed
5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503
      PSI_hook= initialize_performance_schema(&pfs_param);
      if (PSI_hook == NULL)
      {
        pfs_param.m_enabled= false;
        buffered_logs.buffer(WARNING_LEVEL,
                             "Performance schema disabled (reason: init failed).");
      }
    }
  }
#else
  /*
    Other provider of the instrumentation interface should
    initialize PSI_hook here:
    - HAVE_PSI_INTERFACE is for the instrumentation interface
    - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
      of the interface,
    but there could be alternate implementations, which is why
    these two defines are kept separate.
  */
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */

#ifdef HAVE_PSI_INTERFACE
  /*
    Obtain the current performance schema instrumentation interface,
    if available.
  */
  if (PSI_hook)
  {
5504 5505 5506 5507
    PSI *psi_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION);
    if (likely(psi_server != NULL))
    {
      set_psi_server(psi_server);
Marc Alff's avatar
Marc Alff committed
5508

5509 5510 5511 5512 5513 5514 5515
      /*
        Now that we have parsed the command line arguments, and have
        initialized the performance schema itself, the next step is to
        register all the server instruments.
      */
      init_server_psi_keys();
      /* Instrument the main thread */
5516 5517
      PSI_thread *psi= PSI_CALL_new_thread(key_thread_main, NULL, 0);
      PSI_CALL_set_thread(psi);
5518 5519 5520 5521 5522 5523 5524 5525

      /*
        Now that some instrumentation is in place,
        recreate objects which were initialised early,
        so that they are instrumented as well.
      */
      my_thread_global_reinit();
    }
Marc Alff's avatar
Marc Alff committed
5526 5527 5528
  }
#endif /* HAVE_PSI_INTERFACE */

5529
  mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST);
5530

5531 5532 5533
  /* Initialize audit interface globals. Audit plugins are inited later. */
  mysql_audit_initialize();

5534 5535 5536 5537 5538 5539
  /*
    Perform basic logger initialization logger. Should be called after
    MY_INIT, as it initializes mutexes. Log tables are inited later.
  */
  logger.init_base();

Marc Alff's avatar
Marc Alff committed
5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  if (ho_error)
  {
    /*
      Parsing command line option failed,
      Since we don't have a workable remaining_argc/remaining_argv
      to continue the server initialization, this is as far as this
      code can go.
      This is the best effort to log meaningful messages:
      - messages will be printed to stderr, which is not redirected yet,
      - messages will be printed in the NT event log, for windows.
    */
    buffered_logs.print();
    buffered_logs.cleanup();
    /*
      Not enough initializations for unireg_abort()
      Using exit() for windows.
    */
    exit (ho_error);
  }
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */

unknown's avatar
unknown committed
5562
#ifdef _CUSTOMSTARTUPCONFIG_
unknown's avatar
unknown committed
5563 5564 5565
  if (_cust_check_startup())
  {
    / * _cust_check_startup will report startup failure error * /
unknown's avatar
Merge  
unknown committed
5566
    exit(1);
unknown's avatar
unknown committed
5567 5568
  }
#endif
unknown's avatar
unknown committed
5569

Marc Alff's avatar
Marc Alff committed
5570
  if (init_common_variables())
5571
    unireg_abort(1);				// Will do exit
unknown's avatar
unknown committed
5572 5573

  init_signals();
5574

Sergei Golubchik's avatar
Sergei Golubchik committed
5575 5576
  ulonglong new_thread_stack_size;
  new_thread_stack_size= my_setstacksize(&connection_attrib,
5577
                                         (size_t)my_thread_stack_size);
Sergei Golubchik's avatar
Sergei Golubchik committed
5578 5579
  if (new_thread_stack_size != my_thread_stack_size)
    SYSVAR_AUTOSIZE(my_thread_stack_size, new_thread_stack_size);
unknown's avatar
unknown committed
5580

5581
  (void) thr_setconcurrency(concurrency);	// 10 by default
unknown's avatar
unknown committed
5582

5583 5584
  select_thread=pthread_self();
  select_thread_in_use=1;
unknown's avatar
unknown committed
5585 5586 5587 5588 5589 5590

#ifdef HAVE_LIBWRAP
  libwrapName= my_progname+dirname_length(my_progname);
  openlog(libwrapName, LOG_PID, LOG_AUTH);
#endif

5591 5592
#ifndef DBUG_OFF
  test_lc_time_sz();
5593
  srand((uint) time(NULL)); 
5594 5595
#endif

unknown's avatar
unknown committed
5596 5597 5598
  /*
    We have enough space for fiddling with the argv, continue
  */
unknown's avatar
unknown committed
5599
  check_data_home(mysql_real_data_home);
5600
  if (my_setwd(mysql_real_data_home, opt_abort ? 0 : MYF(MY_WME)) && !opt_abort)
unknown's avatar
unknown committed
5601
    unireg_abort(1);				/* purecov: inspected */
unknown's avatar
unknown committed
5602

5603 5604 5605
  /* Atomic write initialization must be done as root */
  my_init_atomic_write();

unknown's avatar
unknown committed
5606 5607 5608 5609 5610 5611 5612 5613 5614 5615
  if ((user_info= check_user(mysqld_user)))
  {
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
    if (locked_in_memory) // getuid() == 0 here
      set_effective_user(user_info);
    else
#endif
      set_user(mysqld_user, user_info);
  }

Brave Galera Crew's avatar
Brave Galera Crew committed
5616
  if (WSREP_ON && wsrep_check_opts()) unireg_abort(1);
5617

5618 5619 5620 5621 5622 5623 5624 5625
  /* 
   The subsequent calls may take a long time : e.g. innodb log read.
   Thus set the long running service control manager timeout
  */
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetSlowStarting(slow_start_timeout);
#endif

unknown's avatar
unknown committed
5626
  if (init_server_components())
unknown's avatar
unknown committed
5627
    unireg_abort(1);
unknown's avatar
unknown committed
5628

5629
  init_ssl();
unknown's avatar
unknown committed
5630 5631
  network_init();

unknown's avatar
unknown committed
5632 5633 5634 5635
#ifdef __WIN__
  if (!opt_console)
  {
    FreeConsole();				// Remove window
5636
  }
5637 5638 5639 5640 5641 5642

  if (fileno(stdin) >= 0)
  {
    /* Disable CRLF translation (MDEV-9409). */
    _setmode(fileno(stdin), O_BINARY);
  }
unknown's avatar
unknown committed
5643 5644
#endif

Kristian Nielsen's avatar
Kristian Nielsen committed
5645
#ifdef WITH_WSREP
5646 5647
  // Recover and exit.
  if (wsrep_recovery)
5648 5649
  {
    select_thread_in_use= 0;
5650 5651 5652 5653
    if (WSREP_ON)
      wsrep_recover();
    else
      sql_print_information("WSREP: disabled, skipping position recovery");
5654 5655
    unireg_abort(0);
  }
Kristian Nielsen's avatar
Kristian Nielsen committed
5656
#endif
5657

unknown's avatar
unknown committed
5658 5659 5660 5661 5662
  /*
    init signals & alarm
    After this we can't quit by a simple unireg_abort
  */
  start_signal_handler();				// Creates pidfile
5663

5664
  if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
5665
      my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
5666
    unireg_abort(1);
5667

unknown's avatar
unknown committed
5668
  if (!opt_noacl)
5669
    (void) grant_init();
unknown's avatar
unknown committed
5670

5671
  udf_init();
5672

unknown's avatar
unknown committed
5673 5674
  if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
    opt_skip_slave_start= 1;
5675 5676

  binlog_unsafe_map_init();
5677

Marc Alff's avatar
Marc Alff committed
5678 5679 5680 5681 5682 5683
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  initialize_performance_schema_acl(opt_bootstrap);
#endif

  initialize_information_schema_acl();

5684 5685
  execute_ddl_log_recovery();

5686 5687 5688 5689 5690 5691 5692 5693 5694
  /*
    Change EVENTS_ORIGINAL to EVENTS_OFF (the default value) as there is no
    point in using ORIGINAL during startup
  */
  if (Events::opt_event_scheduler == Events::EVENTS_ORIGINAL)
    Events::opt_event_scheduler= Events::EVENTS_OFF;

  Events::set_original_state(Events::opt_event_scheduler);
  if (Events::init((THD*) 0, opt_noacl || opt_bootstrap))
5695 5696
    unireg_abort(1);

5697 5698 5699 5700 5701 5702 5703 5704
  if (WSREP_ON)
  {
    if (opt_bootstrap)
    {
      /*! bootstrap wsrep init was taken care of above */
    }
    else
    {
Brave Galera Crew's avatar
Brave Galera Crew committed
5705 5706
      wsrep_init_globals();
      if (!wsrep_before_SE())
5707 5708 5709 5710 5711 5712
      {
        wsrep_init_startup (false);
      }
      wsrep_create_appliers(wsrep_slave_threads - 1);
    }
  }
5713

5714
  if (opt_bootstrap)
unknown's avatar
unknown committed
5715
  {
5716
    select_thread_in_use= 0;                    // Allow 'kill' to work
Sergey Vojtovich's avatar
Sergey Vojtovich committed
5717
    int bootstrap_error= bootstrap(mysql_stdin);
5718
    if (!abort_loop)
Sergey Vojtovich's avatar
Sergey Vojtovich committed
5719
      unireg_abort(bootstrap_error);
5720 5721 5722 5723 5724
    else
    {
      sleep(2);                                 // Wait for kill
      exit(0);
    }
unknown's avatar
unknown committed
5725
  }
5726

5727
  create_shutdown_event();
5728 5729
  start_handle_manager();

5730 5731 5732
  /* Copy default global rpl_filter to global_rpl_filter */
  copy_filter_setting(global_rpl_filter, get_or_create_rpl_filter("", 0));

5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743
  /*
    init_slave() must be called after the thread keys are created.
    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
    places) assume that active_mi != 0, so let's fail if it's 0 (out of
    memory); a message has already been printed.
  */
  if (init_slave() && !active_mi)
  {
    unireg_abort(1);
  }

5744
  if (opt_init_file && *opt_init_file)
unknown's avatar
unknown committed
5745 5746 5747 5748
  {
    if (read_init_file(opt_init_file))
      unireg_abort(1);
  }
unknown's avatar
unknown committed
5749

5750
  disable_log_notes= 0; /* Startup done, now we can give notes again */
5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770

  if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
    sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname, server_version,
                          ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
                           (char*) "" : mysqld_unix_port),
                          mysqld_port, MYSQL_COMPILATION_COMMENT);
  else
  {
    char real_server_version[2 * SERVER_VERSION_LENGTH + 10];

    set_server_version(real_server_version, sizeof(real_server_version));
    strcat(real_server_version, "' as '");
    strcat(real_server_version, server_version);

    sql_print_information(ER_DEFAULT(ER_STARTUP), my_progname,
                          real_server_version,
                          ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
                           (char*) "" : mysqld_unix_port),
                          mysqld_port, MYSQL_COMPILATION_COMMENT);
  }
5771

5772
#ifndef _WIN32
5773
  // try to keep fd=0 busy
5774
  if (please_close_stdin && !freopen("/dev/null", "r", stdin))
5775 5776 5777 5778
  {
    // fall back on failure
    fclose(stdin);
  }
5779
#endif
5780

5781 5782 5783
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetRunning();
#endif
unknown's avatar
unknown committed
5784

unknown's avatar
unknown committed
5785
  /* Signal threads waiting for server to be started */
Marc Alff's avatar
Marc Alff committed
5786
  mysql_mutex_lock(&LOCK_server_started);
unknown's avatar
unknown committed
5787
  mysqld_server_started= 1;
Marc Alff's avatar
Marc Alff committed
5788 5789
  mysql_cond_signal(&COND_server_started);
  mysql_mutex_unlock(&LOCK_server_started);
unknown's avatar
unknown committed
5790

Sergei Golubchik's avatar
Sergei Golubchik committed
5791 5792
  MYSQL_SET_STAGE(0 ,__FILE__, __LINE__);

5793 5794 5795
  /* Memory used when everything is setup */
  start_memory_used= global_status_var.global_memory_used;

5796
#ifdef _WIN32
5797
  handle_connections_win();
unknown's avatar
unknown committed
5798
#else
5799
  handle_connections_sockets();
5800 5801 5802 5803 5804

  mysql_mutex_lock(&LOCK_start_thread);
  select_thread_in_use=0;
  mysql_cond_broadcast(&COND_start_thread);
  mysql_mutex_unlock(&LOCK_start_thread);
5805
#endif /* _WIN32 */
unknown's avatar
unknown committed
5806

5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826
  /* Shutdown requested */
  char *user= shutdown_user.load(std::memory_order_relaxed);
  sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN), my_progname,
                        user ? user : "unknown");
  if (user)
    my_free(user);

#ifdef WITH_WSREP
  /* Stop wsrep threads in case they are running. */
  if (wsrep_running_threads > 0)
  {
    wsrep_shutdown_replication();
  }
#endif

  close_connections();

  clean_up(1);
  sd_notify(0, "STATUS=MariaDB server is down");

unknown's avatar
unknown committed
5827
  /* (void) pthread_attr_destroy(&connection_attrib); */
5828

unknown's avatar
unknown committed
5829 5830
  DBUG_PRINT("quit",("Exiting main thread"));

5831 5832 5833 5834
  /*
    Disable the main thread instrumentation,
    to avoid recording events during the shutdown.
  */
5835
  PSI_CALL_delete_current_thread();
5836

unknown's avatar
merge  
unknown committed
5837
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
5838
  if (start_mode)
unknown's avatar
merge  
unknown committed
5839 5840 5841
    Service.Stop();
  else
  {
unknown's avatar
unknown committed
5842
    Service.SetShutdownEvent(0);
unknown's avatar
merge  
unknown committed
5843 5844 5845
    if (hEventShutdown)
      CloseHandle(hEventShutdown);
  }
5846
#endif
5847
#if (defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)) && !defined(EMBEDDED_LIBRARY)
5848
  ERR_remove_state(0);
unknown's avatar
unknown committed
5849
#endif
5850
  mysqld_exit(0);
5851
  return 0;
unknown's avatar
unknown committed
5852 5853
}

5854
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
5855

unknown's avatar
SCRUM  
unknown committed
5856

5857 5858 5859 5860 5861
/****************************************************************************
  Main and thread entry function for Win32
  (all this is needed only to run mysqld as a service on WinNT)
****************************************************************************/

unknown's avatar
unknown committed
5862
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
5863
void  mysql_service(void *p)
unknown's avatar
unknown committed
5864
{
5865
  if (my_thread_init())
5866
    abort();
5867
  
5868 5869 5870 5871
  if (use_opt_args)
    win_main(opt_argc, opt_argv);
  else
    win_main(Service.my_argc, Service.my_argv);
5872 5873

  my_thread_end();
unknown's avatar
unknown committed
5874 5875
}

5876 5877 5878 5879 5880 5881 5882 5883

/* Quote string if it contains space, else copy */

static char *add_quoted_string(char *to, const char *from, char *to_end)
{
  uint length= (uint) (to_end-to);

  if (!strchr(from, ' '))
unknown's avatar
unknown committed
5884 5885
    return strmake(to, from, length-1);
  return strxnmov(to, length-1, "\"", from, "\"", NullS);
5886 5887 5888
}


unknown's avatar
unknown committed
5889 5890
/**
  Handle basic handling of services, like installation and removal.
5891

unknown's avatar
unknown committed
5892 5893 5894 5895 5896 5897
  @param argv	   	        Pointer to argument list
  @param servicename		Internal name of service
  @param displayname		Display name of service (in taskbar ?)
  @param file_path		Path to this program
  @param startup_option	Startup option to mysqld

5898 5899
  @retval 0	option handled
  @retval 1	Could not handle option
unknown's avatar
unknown committed
5900
*/
5901

5902 5903 5904 5905 5906
static bool
default_service_handling(char **argv,
			 const char *servicename,
			 const char *displayname,
			 const char *file_path,
unknown's avatar
Merge  
unknown committed
5907 5908
			 const char *extra_opt,
			 const char *account_name)
5909
{
5910
  char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
5911
  const char *opt_delim;
5912
  end= path_and_service + sizeof(path_and_service)-3;
5913 5914 5915

  /* We have to quote filename if it contains spaces */
  pos= add_quoted_string(path_and_service, file_path, end);
5916
  if (extra_opt && *extra_opt)
5917
  {
5918 5919 5920 5921 5922
    /* 
     Add option after file_path. There will be zero or one extra option.  It's 
     assumed to be --defaults-file=file but isn't checked.  The variable (not
     the option name) should be quoted if it contains a string.  
    */
5923
    *pos++= ' ';
5924
    if ((opt_delim= strchr(extra_opt, '=')))
5925 5926
    {
      size_t length= ++opt_delim - extra_opt;
5927
      pos= strnmov(pos, extra_opt, length);
5928 5929 5930 5931 5932
    }
    else
      opt_delim= extra_opt;
    
    pos= add_quoted_string(pos, opt_delim, end);
5933
  }
5934 5935
  /* We must have servicename last */
  *pos++= ' ';
unknown's avatar
unknown committed
5936
  (void) add_quoted_string(pos, servicename, end);
5937

5938 5939
  if (Service.got_service_option(argv, "install"))
  {
unknown's avatar
Merge  
unknown committed
5940 5941
    Service.Install(1, servicename, displayname, path_and_service,
                    account_name);
5942 5943 5944 5945
    return 0;
  }
  if (Service.got_service_option(argv, "install-manual"))
  {
unknown's avatar
Merge  
unknown committed
5946 5947
    Service.Install(0, servicename, displayname, path_and_service,
                    account_name);
5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958
    return 0;
  }
  if (Service.got_service_option(argv, "remove"))
  {
    Service.Remove(servicename);
    return 0;
  }
  return 1;
}


5959
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5960
{
5961 5962
  my_progname= argv[0];

unknown's avatar
unknown committed
5963 5964 5965 5966
  /*
    When several instances are running on the same machine, we
    need to have an  unique  named  hEventShudown  through the
    application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
unknown's avatar
Merge  
unknown committed
5967
  */
5968
  int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
unknown's avatar
Merge  
unknown committed
5969 5970
                                                  "MySQLShutdown"), 10);

5971 5972 5973
  /* Must be initialized early for comparison of service name */
  system_charset_info= &my_charset_utf8_general_ci;

5974 5975 5976 5977 5978 5979
  if (my_init())
  {
    fprintf(stderr, "my_init() failed.");
    return 1;
  }

5980 5981 5982 5983 5984 5985

  char file_path[FN_REFLEN];
  my_path(file_path, argv[0], "");		      /* Find name in path */
  fn_format(file_path,argv[0],file_path,"",   MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);

  if (argc == 2)
unknown's avatar
unknown committed
5986
  {
5987 5988 5989
    if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
      file_path, "", NULL))
      return 0;
unknown's avatar
unknown committed
5990

5991
    if (Service.IsService(argv[1]))        /* Start an optional service */
5992 5993
    {
      /*
5994 5995 5996 5997
      Only add the service name to the groups read from the config file
      if it's not "MySQL". (The default service name should be 'mysqld'
      but we started a bad tradition by calling it MySQL from the start
      and we are now stuck with it.
5998
      */
5999 6000 6001 6002 6003
      if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
        load_default_groups[load_default_groups_sz-2]= argv[1];
      start_mode= 1;
      Service.Init(argv[1], mysql_service);
      return 0;
6004
    }
6005 6006 6007 6008 6009 6010 6011
  }
  else if (argc == 3) /* install or remove any optional service */
  {
    if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
                                  NULL))
      return 0;
    if (Service.IsService(argv[2]))
unknown's avatar
unknown committed
6012
    {
6013 6014 6015 6016 6017 6018 6019
      /*
       mysqld was started as
       mysqld --defaults-file=my_path\my.ini service-name
      */
      use_opt_args=1;
      opt_argc= 2;				// Skip service-name
      opt_argv=argv;
unknown's avatar
unknown committed
6020
      start_mode= 1;
6021 6022 6023
      if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
        load_default_groups[load_default_groups_sz-2]= argv[2];
      Service.Init(argv[2], mysql_service);
unknown's avatar
unknown committed
6024 6025 6026
      return 0;
    }
  }
6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059
  else if (argc == 4 || argc == 5)
  {
    /*
      This may seem strange, because we handle --local-service while
      preserving 4.1's behavior of allowing any one other argument that is
      passed to the service on startup. (The assumption is that this is
      --defaults-file=file, but that was not enforced in 4.1, so we don't
      enforce it here.)
    */
    const char *extra_opt= NullS;
    const char *account_name = NullS;
    int index;
    for (index = 3; index < argc; index++)
    {
      if (!strcmp(argv[index], "--local-service"))
        account_name= "NT AUTHORITY\\LocalService";
      else
        extra_opt= argv[index];
    }

    if (argc == 4 || account_name)
      if (!default_service_handling(argv, argv[2], argv[2], file_path,
                                    extra_opt, account_name))
        return 0;
  }
  else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
  {
    /* start the default service */
    start_mode= 1;
    Service.Init(MYSQL_SERVICENAME, mysql_service);
    return 0;
  }

unknown's avatar
unknown committed
6060
  /* Start as standalone server */
unknown's avatar
unknown committed
6061 6062 6063 6064 6065 6066 6067 6068 6069 6070
  Service.my_argc=argc;
  Service.my_argv=argv;
  mysql_service(NULL);
  return 0;
}
#endif


static bool read_init_file(char *file_name)
{
Marc Alff's avatar
Marc Alff committed
6071
  MYSQL_FILE *file;
unknown's avatar
unknown committed
6072 6073
  DBUG_ENTER("read_init_file");
  DBUG_PRINT("enter",("name: %s",file_name));
Marc Alff's avatar
Marc Alff committed
6074 6075
  if (!(file= mysql_file_fopen(key_file_init, file_name,
                               O_RDONLY, MYF(MY_WME))))
6076
    DBUG_RETURN(TRUE);
unknown's avatar
Merge  
unknown committed
6077
  bootstrap(file);
Marc Alff's avatar
Marc Alff committed
6078
  mysql_file_fclose(file, MYF(MY_WME));
6079
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
6080 6081 6082
}


Mikael Ronström's avatar
Mikael Ronström committed
6083 6084 6085 6086 6087
/**
  Increment number of created threads
*/
void inc_thread_created(void)
{
6088
  statistic_increment(thread_created, &LOCK_status);
Mikael Ronström's avatar
Mikael Ronström committed
6089 6090
}

6091
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
6092 6093 6094 6095 6096 6097 6098 6099

/*
   Simple scheduler that use the main thread to handle the request

   NOTES
     This is only used for debugging, when starting mysqld with
     --thread-handling=no-threads or --one-thread
*/
6100

6101
void handle_connection_in_main_thread(CONNECT *connect)
unknown's avatar
unknown committed
6102
{
6103 6104
  thread_cache_size= 0;			// Safety
  do_handle_one_connection(connect);
unknown's avatar
unknown committed
6105 6106 6107 6108 6109 6110 6111
}


/*
  Scheduler that uses one thread per connection
*/

6112
void create_thread_to_handle_connection(CONNECT *connect)
unknown's avatar
unknown committed
6113
{
6114 6115
  char error_message_buff[MYSQL_ERRMSG_SIZE];
  int error;
Michael Widenius's avatar
Michael Widenius committed
6116 6117 6118
  DBUG_ENTER("create_thread_to_handle_connection");

  /* Check if we can get thread from the cache */
unknown's avatar
unknown committed
6119 6120
  if (cached_thread_count > wake_thread)
  {
Michael Widenius's avatar
Michael Widenius committed
6121 6122 6123
    mysql_mutex_lock(&LOCK_thread_cache);
    /* Recheck condition when we have the lock */
    if (cached_thread_count > wake_thread)
unknown's avatar
unknown committed
6124
    {
Michael Widenius's avatar
Michael Widenius committed
6125
      /* Get thread from cache */
6126
      thread_cache.push_back(connect);
Michael Widenius's avatar
Michael Widenius committed
6127 6128 6129 6130 6131 6132 6133 6134
      wake_thread++;
      mysql_cond_signal(&COND_thread_cache);
      mysql_mutex_unlock(&LOCK_thread_cache);
      DBUG_PRINT("info",("Thread created"));
      DBUG_VOID_RETURN;
    }
    mysql_mutex_unlock(&LOCK_thread_cache);
  }
6135

Michael Widenius's avatar
Michael Widenius committed
6136
  /* Create new thread to handle connection */
6137 6138 6139 6140
  inc_thread_created();
  DBUG_PRINT("info",(("creating thread %lu"), (ulong) connect->thread_id));
  connect->prior_thr_create_utime= microsecond_interval_timer();

Michael Widenius's avatar
Michael Widenius committed
6141
  if ((error= mysql_thread_create(key_thread_one_connection,
6142
                                  &connect->real_id, &connection_attrib,
Sergei Golubchik's avatar
Sergei Golubchik committed
6143
                                  handle_one_connection, (void*) connect)))
Michael Widenius's avatar
Michael Widenius committed
6144 6145
  {
    /* purecov: begin inspected */
Sergei Golubchik's avatar
Sergei Golubchik committed
6146
    DBUG_PRINT("error", ("Can't create thread to handle request (error %d)",
Michael Widenius's avatar
Michael Widenius committed
6147 6148
                error));
    my_snprintf(error_message_buff, sizeof(error_message_buff),
6149
                ER_DEFAULT(ER_CANT_CREATE_THREAD), error);
Sergei Golubchik's avatar
Sergei Golubchik committed
6150
    connect->close_with_error(ER_CANT_CREATE_THREAD, error_message_buff,
6151 6152
                              ER_OUT_OF_RESOURCES);
    DBUG_VOID_RETURN;
Michael Widenius's avatar
Michael Widenius committed
6153
    /* purecov: end */
unknown's avatar
unknown committed
6154 6155
  }
  DBUG_PRINT("info",("Thread created"));
Michael Widenius's avatar
Michael Widenius committed
6156
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
6157 6158 6159
}


unknown's avatar
unknown committed
6160
/**
6161 6162 6163 6164 6165 6166
  Create new thread to handle incoming connection.

    This function will create new thread to handle the incoming
    connection.  If there are idle cached threads one will be used.
    'thd' will be pushed into 'threads'.

unknown's avatar
unknown committed
6167
    In single-threaded mode (\#define ONE_THREAD) connection will be
6168 6169
    handled inside this function.

unknown's avatar
unknown committed
6170
  @param[in,out] thd    Thread handle of future thread.
6171 6172
*/

6173
void create_new_thread(CONNECT *connect)
unknown's avatar
unknown committed
6174 6175 6176
{
  DBUG_ENTER("create_new_thread");

6177 6178 6179 6180 6181
  /*
    Don't allow too many connections. We roughly check here that we allow
    only (max_connections + 1) connections.
  */

Marc Alff's avatar
Marc Alff committed
6182
  mysql_mutex_lock(&LOCK_connection_count);
6183

6184 6185
  if (*connect->scheduler->connection_count >=
      *connect->scheduler->max_connections + 1|| abort_loop)
unknown's avatar
unknown committed
6186
  {
unknown's avatar
unknown committed
6187
    DBUG_PRINT("error",("Too many connections"));
6188 6189

    mysql_mutex_unlock(&LOCK_connection_count);
6190
    statistic_increment(denied_connections, &LOCK_status);
unknown's avatar
unknown committed
6191
    statistic_increment(connection_errors_max_connection, &LOCK_status);
6192
    connect->close_with_error(0, NullS, abort_loop ? ER_SERVER_SHUTDOWN : ER_CON_COUNT_ERROR);
unknown's avatar
unknown committed
6193 6194
    DBUG_VOID_RETURN;
  }
6195

6196
  ++*connect->scheduler->connection_count;
6197

6198 6199
  if (connection_count + extra_connection_count > max_used_connections)
    max_used_connections= connection_count + extra_connection_count;
6200

Marc Alff's avatar
Marc Alff committed
6201
  mysql_mutex_unlock(&LOCK_connection_count);
6202

6203
  connect->thread_count_incremented= 1;
6204

6205 6206 6207 6208 6209
  /*
    The initialization of thread_id is done in create_embedded_thd() for
    the embedded library.
    TODO: refactor this to avoid code duplication there
  */
6210 6211
  connect->thread_id= next_thread_id();
  connect->scheduler->add_connection(connect);
6212

unknown's avatar
unknown committed
6213 6214
  DBUG_VOID_RETURN;
}
6215 6216
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
6217 6218 6219

	/* Handle new connections and spawn new process to handle them */

6220
#ifndef EMBEDDED_LIBRARY
6221

6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312
void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock)
{
  CONNECT *connect;
  bool is_unix_sock;

#ifdef FD_CLOEXEC
  (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC);
#endif

#ifdef HAVE_LIBWRAP
  {
    if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) ||
      mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
    {
      struct request_info req;
      signal(SIGCHLD, SIG_DFL);
      request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE,
        mysql_socket_getfd(new_sock), NULL);
      my_fromhost(&req);
      if (!my_hosts_access(&req))
      {
        /*
          This may be stupid but refuse() includes an exit(0)
          which we surely don't want...
          clean_exit() - same stupid thing ...
        */
        syslog(deny_severity, "refused connect from %s",
          my_eval_client(&req));

        /*
          C++ sucks (the gibberish in front just translates the supplied
          sink function pointer in the req structure from a void (*sink)();
          to a void(*sink)(int) if you omit the cast, the C++ compiler
          will cry...
        */
        if (req.sink)
          ((void(*)(int))req.sink)(req.fd);

        (void)mysql_socket_shutdown(new_sock, SHUT_RDWR);
        (void)mysql_socket_close(new_sock);
        /*
          The connection was refused by TCP wrappers.
          There are no details (by client IP) available to update the
          host_cache.
        */
        statistic_increment(connection_errors_tcpwrap, &LOCK_status);
        return;
      }
    }
  }
#endif /* HAVE_LIBWRAP */

  DBUG_PRINT("info", ("Creating CONNECT for new connection"));

  if ((connect= new CONNECT()))
  {
    is_unix_sock= (mysql_socket_getfd(sock) ==
      mysql_socket_getfd(unix_sock));

    if (!(connect->vio=
      mysql_socket_vio_new(new_sock,
        is_unix_sock ? VIO_TYPE_SOCKET :
        VIO_TYPE_TCPIP,
        is_unix_sock ? VIO_LOCALHOST : 0)))
    {
      delete connect;
      connect= 0;                             // Error handling below
    }
  }

  if (!connect)
  {
    /* Connect failure */
    (void)mysql_socket_close(new_sock);
    statistic_increment(aborted_connects, &LOCK_status);
    statistic_increment(connection_errors_internal, &LOCK_status);
    return;
  }

  if (is_unix_sock)
    connect->host= my_localhost;

  if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
  {
    connect->extra_port= 1;
    connect->scheduler= extra_thread_scheduler;
  }
  create_new_thread(connect);
}

#ifndef _WIN32
6313
void handle_connections_sockets()
unknown's avatar
unknown committed
6314
{
6315 6316
  MYSQL_SOCKET sock= mysql_socket_invalid();
  MYSQL_SOCKET new_sock= mysql_socket_invalid();
unknown's avatar
unknown committed
6317
  uint error_count=0;
6318
  struct sockaddr_storage cAddr;
Michael Widenius's avatar
Michael Widenius committed
6319 6320 6321 6322
  int ip_flags __attribute__((unused))=0;
  int socket_flags __attribute__((unused))= 0;
  int extra_ip_flags __attribute__((unused))=0;
  int flags=0,retval;
6323 6324
#ifdef HAVE_POLL
  int socket_count= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
6325
  struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock
6326
  MYSQL_SOCKET  pfs_fds[3]; // for performance schema
Sergei Golubchik's avatar
Sergei Golubchik committed
6327
#define setup_fds(X)                    \
Sergei Golubchik's avatar
Sergei Golubchik committed
6328
    mysql_socket_set_thread_owner(X);             \
6329 6330
    pfs_fds[socket_count]= (X);                   \
    fds[socket_count].fd= mysql_socket_getfd(X);  \
Sergei Golubchik's avatar
Sergei Golubchik committed
6331 6332
    fds[socket_count].events= POLLIN;   \
    socket_count++
6333
#else
6334
#define setup_fds(X)    FD_SET(mysql_socket_getfd(X),&clientFDs)
6335
  fd_set readFDs,clientFDs;
Sergei Golubchik's avatar
Sergei Golubchik committed
6336
  FD_ZERO(&clientFDs);
6337 6338
#endif

unknown's avatar
unknown committed
6339 6340
  DBUG_ENTER("handle_connections_sockets");

6341
  if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
6342
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6343
    setup_fds(base_ip_sock);
6344
    ip_flags = fcntl(mysql_socket_getfd(base_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6345
  }
6346
  if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
6347
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6348
    setup_fds(extra_ip_sock);
6349
    extra_ip_flags = fcntl(mysql_socket_getfd(extra_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6350 6351
  }
#ifdef HAVE_SYS_UN_H
Sergei Golubchik's avatar
Sergei Golubchik committed
6352
  setup_fds(unix_sock);
6353
  socket_flags=fcntl(mysql_socket_getfd(unix_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6354 6355
#endif

6356
  sd_notify(0, "READY=1\n"
6357
            "STATUS=Taking your SQL requests now...\n");
6358

unknown's avatar
unknown committed
6359 6360 6361
  DBUG_PRINT("general",("Waiting for connections."));
  while (!abort_loop)
  {
6362 6363
#ifdef HAVE_POLL
    retval= poll(fds, socket_count, -1);
unknown's avatar
unknown committed
6364
#else
6365
    readFDs=clientFDs;
6366
    retval= select((int) 0,&readFDs,0,0,0);
6367 6368 6369
#endif

    if (retval < 0)
unknown's avatar
unknown committed
6370
    {
unknown's avatar
unknown committed
6371
      if (socket_errno != SOCKET_EINTR)
unknown's avatar
unknown committed
6372
      {
unknown's avatar
unknown committed
6373 6374 6375 6376 6377 6378
        /*
          select(2)/poll(2) failed on the listening port.
          There is not much details to report about the client,
          increment the server global status variable.
        */
        statistic_increment(connection_errors_accept, &LOCK_status);
unknown's avatar
unknown committed
6379
	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
unknown's avatar
unknown committed
6380
	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
unknown's avatar
unknown committed
6381 6382 6383
      }
      continue;
    }
6384

unknown's avatar
unknown committed
6385 6386 6387
    if (abort_loop)
      break;

6388
    /* Is this a new connection request ? */
6389 6390 6391 6392 6393
#ifdef HAVE_POLL
    for (int i= 0; i < socket_count; ++i) 
    {
      if (fds[i].revents & POLLIN)
      {
6394 6395
        sock= pfs_fds[i];
        flags= fcntl(mysql_socket_getfd(sock), F_GETFL, 0);
6396 6397 6398 6399
        break;
      }
    }
#else  // HAVE_POLL
6400
    if (FD_ISSET(mysql_socket_getfd(base_ip_sock),&readFDs))
unknown's avatar
unknown committed
6401
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6402 6403
      sock=  base_ip_sock;
      flags= ip_flags;
unknown's avatar
unknown committed
6404 6405
    }
    else
6406
    if (FD_ISSET(mysql_socket_getfd(extra_ip_sock),&readFDs))
unknown's avatar
unknown committed
6407
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6408 6409 6410 6411 6412 6413 6414
      sock=  extra_ip_sock;
      flags= extra_ip_flags;
    }
    else
    {
      sock = unix_sock;
      flags= socket_flags;
unknown's avatar
unknown committed
6415
    }
6416
#endif // HAVE_POLL
unknown's avatar
unknown committed
6417 6418 6419 6420 6421

#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
    {
#if defined(O_NONBLOCK)
6422
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NONBLOCK);
unknown's avatar
unknown committed
6423
#elif defined(O_NDELAY)
6424
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NDELAY);
unknown's avatar
unknown committed
6425 6426 6427 6428 6429
#endif
    }
#endif /* NO_FCNTL_NONBLOCK */
    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
    {
6430
      size_socket length= sizeof(struct sockaddr_storage);
6431 6432 6433 6434
      new_sock= mysql_socket_accept(key_socket_client_connection, sock,
                                    (struct sockaddr *)(&cAddr),
                                    &length);
      if (mysql_socket_getfd(new_sock) != INVALID_SOCKET ||
unknown's avatar
unknown committed
6435
	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
unknown's avatar
unknown committed
6436 6437 6438 6439 6440
	break;
#if !defined(NO_FCNTL_NONBLOCK)
      if (!(test_flags & TEST_BLOCKING))
      {
	if (retry == MAX_ACCEPT_RETRY - 1)
6441 6442 6443 6444
        {
          // Try without O_NONBLOCK
	  fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
        }
unknown's avatar
unknown committed
6445 6446 6447
      }
#endif
    }
6448

6449
    if (mysql_socket_getfd(new_sock) == INVALID_SOCKET)
unknown's avatar
unknown committed
6450
    {
unknown's avatar
unknown committed
6451 6452 6453 6454 6455 6456
      /*
        accept(2) failed on the listening port, after many retries.
        There is not much details to report about the client,
        increment the server global status variable.
      */
      statistic_increment(connection_errors_accept, &LOCK_status);
unknown's avatar
unknown committed
6457 6458
      if ((error_count++ & 255) == 0)		// This can happen often
	sql_perror("Error in accept");
unknown's avatar
unknown committed
6459
      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
unknown's avatar
unknown committed
6460 6461 6462
	sleep(1);				// Give other threads some time
      continue;
    }
6463 6464 6465
#if !defined(NO_FCNTL_NONBLOCK)
	if (!(test_flags & TEST_BLOCKING))
		fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
6466
#endif
6467
    handle_accepted_socket(new_sock, sock);
unknown's avatar
unknown committed
6468
  }
6469
  sd_notify(0, "STOPPING=1\n"
6470
            "STATUS=Shutdown in progress\n");
6471 6472 6473
  DBUG_VOID_RETURN;
}

6474
#endif /* _WIN32*/
6475
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
6476

6477 6478 6479

/****************************************************************************
  Handle start options
unknown's avatar
unknown committed
6480 6481
******************************************************************************/

6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526

/**
  Process command line options flagged as 'early'.
  Some components needs to be initialized as early as possible,
  because the rest of the server initialization depends on them.
  Options that needs to be parsed early includes:
  - the performance schema, when compiled in,
  - options related to the help,
  - options related to the bootstrap
  The performance schema needs to be initialized as early as possible,
  before to-be-instrumented objects of the server are initialized.
*/

int handle_early_options()
{
  int ho_error;
  DYNAMIC_ARRAY all_early_options;

  my_getopt_register_get_addr(NULL);
  /* Skip unknown options so that they may be processed later */
  my_getopt_skip_unknown= TRUE;

  /* prepare all_early_options array */
  my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25, MYF(0));
  add_many_options(&all_early_options, pfs_early_options,
                  array_elements(pfs_early_options));
  sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
  add_terminator(&all_early_options);

  ho_error= handle_options(&remaining_argc, &remaining_argv,
                           (my_option*)(all_early_options.buffer),
                           mysqld_get_one_option);
  if (ho_error == 0)
  {
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
  }

  delete_dynamic(&all_early_options);

  return ho_error;
}


6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539
#define MYSQL_COMPATIBILITY_OPTION(option) \
  { option, OPT_MYSQL_COMPATIBILITY, \
   0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }

#define MYSQL_TO_BE_IMPLEMENTED_OPTION(option) \
  { option, OPT_MYSQL_TO_BE_IMPLEMENTED, \
   0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }

#define MYSQL_SUGGEST_ANALOG_OPTION(option, str) \
  { option, OPT_MYSQL_COMPATIBILITY, \
   0, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }


6540 6541 6542 6543 6544
/**
  System variables are automatically command-line options (few
  exceptions are documented in sys_var.h), so don't need
  to be listed here.
*/
6545

Marc Alff's avatar
Marc Alff committed
6546
struct my_option my_long_options[]=
6547
{
unknown's avatar
unknown committed
6548
  {"help", '?', "Display this help and exit.", 
6549
   &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
unknown's avatar
unknown committed
6550
   0, 0},
6551
  {"allow-suspicious-udfs", 0,
unknown's avatar
unknown committed
6552 6553
   "Allows use of UDFs consisting of only one symbol xxx() "
   "without corresponding xxx_init() or xxx_deinit(). That also means "
6554 6555
   "that one can load any function from any library, for example exit() "
   "from libc.so",
6556
   &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
6557
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6558 6559
  {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
   "will also set transaction isolation level 'serializable'.", 0, 0, 0,
unknown's avatar
unknown committed
6560
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6561 6562
  /*
    Because Sys_var_bit does not support command-line options, we need to
6563
    explicitly add one for --autocommit
6564
  */
6565 6566 6567
  {"autocommit", 0, "Set default value for autocommit (0 or 1)",
   &opt_autocommit, &opt_autocommit, 0,
   GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL},
6568
  {"binlog-do-db", OPT_BINLOG_DO_DB,
6569 6570
   "Tells the master it should log updates for the specified database, "
   "and exclude all others not explicitly mentioned.",
6571
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6572
  {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
Staale Smedseng's avatar
Staale Smedseng committed
6573
   "Tells the master that updates to the given database should not be logged to the binary log.",
6574
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6575
  {"binlog-row-event-max-size", 0,
6576 6577 6578
   "The maximum size of a row-based binary log event in bytes. Rows will be "
   "grouped into events smaller than this size if possible. "
   "The value has to be a multiple of 256.",
6579 6580
   &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
   0, GET_ULONG, REQUIRED_ARG,
Monty's avatar
Monty committed
6581
   /* def_value */ 8192, /* min_value */  256, /* max_value */ UINT_MAX32-1,
Nirbhay Choubey's avatar
Nirbhay Choubey committed
6582
   /* sub_size */     0, /* block_size */ 256,
6583 6584
   /* app_type */ 0
  },
6585
#ifndef DISABLE_GRANT_OPTIONS
6586
  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
6587
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6588
#endif
6589
  {"character-set-client-handshake", 0,
unknown's avatar
unknown committed
6590
   "Don't ignore client side character set value sent during handshake.",
6591 6592
   &opt_character_set_client_handshake,
   &opt_character_set_client_handshake,
6593
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
6594
  {"character-set-filesystem", 0,
unknown's avatar
unknown committed
6595
   "Set the filesystem character set.",
6596 6597
   &character_set_filesystem_name,
   &character_set_filesystem_name,
unknown's avatar
unknown committed
6598
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6599
  {"character-set-server", 'C', "Set the default character set.",
6600
   &default_character_set_name, &default_character_set_name,
unknown's avatar
unknown committed
6601
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6602
  {"chroot", 'r', "Chroot mysqld daemon during startup.",
6603
   &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6604
   0, 0, 0, 0, 0, 0},
6605
  {"collation-server", 0, "Set the default collation.",
6606
   &default_collation_name, &default_collation_name,
unknown's avatar
unknown committed
6607
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Staale Smedseng's avatar
Staale Smedseng committed
6608
  {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
6609
   &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
6610
   0, 0, 0},
6611
  {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
6612
   NO_ARG, 0, 0, 0, 0, 0, 0},
Michael Widenius's avatar
Michael Widenius committed
6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653
#ifdef DBUG_OFF
  {"debug", '#', "Built in DBUG debugger. Disabled in this build.",
   &current_dbug_option, &current_dbug_option, 0, GET_STR, OPT_ARG,
   0, 0, 0, 0, 0, 0},
#endif
#ifdef HAVE_REPLICATION
  {"debug-abort-slave-event-count", 0,
   "Option used by mysql-test for debugging and testing of replication.",
   &abort_slave_event_count,  &abort_slave_event_count,
   0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
#ifndef DBUG_OFF
  {"debug-assert-on-error", 0,
   "Do an assert in various functions if we get a fatal error",
   &my_assert_on_error, &my_assert_on_error,
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"debug-assert-if-crashed-table", 0,
   "Do an assert in handler::print_error() if we get a crashed table",
   &debug_assert_if_crashed_table, &debug_assert_if_crashed_table,
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
#ifdef HAVE_REPLICATION
  {"debug-disconnect-slave-event-count", 0,
   "Option used by mysql-test for debugging and testing of replication.",
   &disconnect_slave_event_count, &disconnect_slave_event_count,
   0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
  {"debug-exit-info", 'T', "Used for debugging. Use at your own risk.",
   0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
  {"debug-gdb", 0,
   "Set up signals usable for debugging.",
   &opt_debugging, &opt_debugging,
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_REPLICATION
  {"debug-max-binlog-dump-events", 0,
   "Option used by mysql-test for debugging and testing of replication.",
   &max_binlog_dump_events, &max_binlog_dump_events, 0,
   GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
  {"debug-no-sync", 0,
   "Disables system sync calls. Only for running tests or debugging!",
6654
   &my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
Michael Widenius's avatar
Michael Widenius committed
6655 6656 6657 6658 6659 6660 6661
#ifdef HAVE_REPLICATION
  {"debug-sporadic-binlog-dump-fail", 0,
   "Option used by mysql-test for debugging and testing of replication.",
   &opt_sporadic_binlog_dump_fail,
   &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
   0},
#endif /* HAVE_REPLICATION */
6662 6663 6664 6665 6666 6667 6668
#ifndef DBUG_OFF
  {"debug-assert-on-not-freed-memory", 0,
   "Assert if we found problems with memory allocation",
   &debug_assert_on_not_freed_memory,
   &debug_assert_on_not_freed_memory, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0,
   0},
#endif /* DBUG_OFF */
6669 6670 6671
  /* default-storage-engine should have "MyISAM" as def_value. Instead
     of initializing it here it is done in init_common_variables() due
     to a compiler bug in Sun Studio compiler. */
6672
  {"default-storage-engine", 0, "The default storage engine for new tables",
6673
   &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
6674
   0, 0, 0, 0, 0, 0 },
6675 6676 6677 6678
  {"default-tmp-storage-engine", 0,
    "The default storage engine for user-created temporary tables",
   &default_tmp_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0 },
6679
  {"default-time-zone", 0, "Set the default time zone.",
6680
   &default_tz_name, &default_tz_name,
6681
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Michael Widenius's avatar
Michael Widenius committed
6682 6683 6684 6685 6686 6687 6688 6689
#if defined(ENABLED_DEBUG_SYNC)
  {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
   "Enable the debug sync facility "
   "and optionally specify a default wait timeout in seconds. "
   "A zero value keeps the facility disabled.",
   &opt_debug_sync_timeout, 0,
   0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
#endif /* defined(ENABLED_DEBUG_SYNC) */
unknown's avatar
unknown committed
6690
#ifdef HAVE_OPENSSL
6691
  {"des-key-file", 0,
unknown's avatar
unknown committed
6692
   "Load keys for des_encrypt() and des_encrypt from given file.",
6693
   &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6694 6695
   0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
Michael Widenius's avatar
Michael Widenius committed
6696
#ifdef HAVE_STACKTRACE
Sergei Golubchik's avatar
Sergei Golubchik committed
6697
  {"stack-trace", 0 , "Print a symbolic stack trace on failure",
Michael Widenius's avatar
Michael Widenius committed
6698 6699
   &opt_stack_trace, &opt_stack_trace, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_STACKTRACE */
6700 6701 6702
  {"enforce-storage-engine", 0, "Force the use of a storage engine for new tables",
   &enforced_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0 },
6703 6704 6705 6706
  {"external-locking", 0, "Use system (external) locking (disabled by "
   "default).  With this option enabled you can run myisamchk to test "
   "(not repair) tables while the MySQL server is running. Disable with "
   "--skip-external-locking.", &opt_external_locking, &opt_external_locking,
unknown's avatar
unknown committed
6707
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6708 6709
  /* We must always support the next option to make scripts like mysqltest
     easier to do */
Monty's avatar
Monty committed
6710 6711 6712 6713
  {"flashback", 0,
   "Setup the server to use flashback. This enables binary log in row mode and will enable extra logging for DDL's needed by flashback feature",
   &opt_support_flashback, &opt_support_flashback,
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6714
  {"gdb", 0,
Sergei Golubchik's avatar
Sergei Golubchik committed
6715 6716 6717
   "Set up signals usable for debugging. Deprecated, use --debug-gdb instead.",
   &opt_debugging, &opt_debugging,
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6718 6719 6720 6721 6722 6723 6724 6725
  {"gtid-pos-auto-engines", 0,
   "List of engines for which to automatically create a "
   "mysql.gtid_slave_pos_ENGINE table, if a transaction using that engine "
   "is replicated. This can be used to avoid introducing cross-engine "
   "transactions, if engines are used different from that used by table "
   "mysql.gtid_slave_pos",
   &gtid_pos_auto_engines, 0, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0 },
6726
#ifdef HAVE_LARGE_PAGE_OPTION
6727
  {"super-large-pages", 0, "Enable support for super large pages.",
6728
   &opt_super_large_pages, &opt_super_large_pages, 0,
6729
   GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
unknown's avatar
Merge  
unknown committed
6730
#endif
6731
  {"language", 'L',
6732 6733
   "Client error messages in given language. May be given as a full path. "
   "Deprecated. Use --lc-messages-dir instead.",
6734
   0, 0, 0,
6735
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6736
  {"lc-messages", 0,
6737
   "Set the language used for the error messages.",
6738
   &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
6739
   0, 0, 0, 0, 0, 0 },
6740
  {"lc-time-names", 0,
6741
   "Set the language used for the month names and the days of the week.",
6742
   &lc_time_names_name, &lc_time_names_name,
6743
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6744 6745 6746
  {"log-basename", OPT_LOG_BASENAME,
   "Basename for all log files and the .pid file. This sets all log file "
   "names at once (in 'datadir') and is normally the only option you need "
Sergei Golubchik's avatar
Sergei Golubchik committed
6747
   "for specifying log files. Sets names for --log-bin, --log-bin-index, "
6748
   "--relay-log, --relay-log-index, --general-log-file, "
Sergei Golubchik's avatar
Sergei Golubchik committed
6749
   "--log-slow-query-log-file, --log-error-file, and --pid-file",
6750 6751
   &opt_log_basename, &opt_log_basename, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0},
6752
  {"log-bin", OPT_BIN_LOG,
6753 6754
   "Log update queries in binary format. Optional argument should be name for "
   "binary log. If not given "
6755
   "'datadir'/'log-basename'-bin or 'datadir'/mysql-bin will be used (the later if "
Sergei Golubchik's avatar
Sergei Golubchik committed
6756
   "--log-basename is not specified). We strongly recommend to use either "
6757
   "--log-basename or specify a filename to ensure that replication doesn't "
6758
   "stop if the real hostname of the computer changes.",
6759
   &opt_bin_logname, &opt_bin_logname, 0, GET_STR,
unknown's avatar
unknown committed
6760
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6761
  {"log-bin-index", 0,
6762
   "File that holds the names for last binary log files.",
6763
   &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
6764
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6765 6766 6767 6768 6769
  {"relay-log-index", 0,
   "The location and name to use for the file that keeps a list of the last "
   "relay logs",
   &opt_relaylog_index_name, &opt_relaylog_index_name, 0, GET_STR,
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6770
  {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
6771
   &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
6772
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6773
  {"log-short-format", 0,
unknown's avatar
unknown committed
6774
   "Don't log extra information to update and slow-query logs.",
6775
   &opt_short_log_format, &opt_short_log_format,
unknown's avatar
unknown committed
6776
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6777
  {"log-tc", 0,
unknown's avatar
Merge  
unknown committed
6778
   "Path to transaction coordinator log (used for transactions that affect "
Staale Smedseng's avatar
Staale Smedseng committed
6779
   "more than one storage engine, when binary log is disabled).",
6780
   &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
unknown's avatar
Merge  
unknown committed
6781
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6782
  {"master-info-file", 0,
6783
   "The location and name of the file that remembers the master and where "
6784
   "the I/O replication thread is in the master's binlogs. Defaults to "
Sergei Golubchik's avatar
Sergei Golubchik committed
6785
   "master.info",
6786
   &master_info_file, &master_info_file, 0, GET_STR,
unknown's avatar
unknown committed
6787
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6788
  {"master-retry-count", 0,
6789
   "The number of tries the slave will make to connect to the master before giving up.",
6790
   &master_retry_count, &master_retry_count, 0, GET_ULONG,
6791
   REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6792
#ifdef HAVE_REPLICATION
6793
  {"init-rpl-role", 0, "Set the replication role",
6794
   &rpl_status, &rpl_status, &rpl_role_typelib,
6795
   GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6796
#endif /* HAVE_REPLICATION */
6797
  {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
6798
   &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6799
  {"old-style-user-limits", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6800 6801
   "Enable old-style user limits (before 5.0.3, user resources were counted "
   "per each user+host vs. per account).",
6802
   &opt_old_style_user_limits, &opt_old_style_user_limits,
unknown's avatar
Merge  
unknown committed
6803
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6804
  {"port-open-timeout", 0,
6805
   "Maximum time in seconds to wait for the port to become free. "
6806 6807
   "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6808
  {"replicate-do-db", OPT_REPLICATE_DO_DB,
6809 6810 6811 6812 6813 6814 6815
   "Tells the slave thread to restrict replication to the specified database. "
   "To specify more than one database, use the directive multiple times, "
   "once for each database. Note that this will only work if you do not use "
   "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
   "while having selected a different or no database. If you need cross "
   "database updates to work, make sure you have 3.23.28 or later, and use "
   "replicate-wild-do-table=db_name.%.",
6816
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6817
  {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
6818 6819 6820
   "Tells the slave thread to restrict replication to the specified table. "
   "To specify more than one table, use the directive multiple times, once "
   "for each table. This will work for cross-database updates, in contrast "
6821
   "to replicate-do-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6822
  {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
6823 6824 6825 6826 6827
   "Tells the slave thread to not replicate to the specified database. To "
   "specify more than one database to ignore, use the directive multiple "
   "times, once for each database. This option will not work if you use "
   "cross database updates. If you need cross database updates to work, "
   "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
6828
   "table=db_name.%. ", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6829
  {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
6830 6831 6832
   "Tells the slave thread to not replicate to the specified table. To specify "
   "more than one table to ignore, use the directive multiple times, once for "
   "each table. This will work for cross-database updates, in contrast to "
6833
   "replicate-ignore-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6834
  {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
6835 6836
   "Updates to a database with a different name than the original. Example: "
   "replicate-rewrite-db=master_db_name->slave_db_name.",
6837
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6838
#ifdef HAVE_REPLICATION
6839
  {"replicate-same-server-id", 0,
6840 6841 6842 6843
   "In replication, if set to 1, do not skip events having our server id. "
   "Default value is 0 (to break infinite loops in circular replication). "
   "Can't be set to 1 if --log-slave-updates is used.",
   &replicate_same_server_id, &replicate_same_server_id,
6844
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6845
#endif
unknown's avatar
unknown committed
6846
  {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
6847 6848 6849 6850 6851 6852
   "Tells the slave thread to restrict replication to the tables that match "
   "the specified wildcard pattern. To specify more than one table, use the "
   "directive multiple times, once for each table. This will work for cross-"
   "database updates. Example: replicate-wild-do-table=foo%.bar% will "
   "replicate only updates to tables in all databases that start with foo "
   "and whose table names start with bar.",
6853
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6854
  {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
6855 6856 6857 6858 6859 6860
   "Tells the slave thread to not replicate to the tables that match the "
   "given wildcard pattern. To specify more than one table to ignore, use "
   "the directive multiple times, once for each table. This will work for "
   "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
   "will not do updates to tables in databases that start with foo and whose "
   "table names start with bar.",
6861
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6862
  {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing). Deprecated.",
6863
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6864
  {"safe-user-create", 0,
6865
   "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
6866
   &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
6867
   NO_ARG, 0, 0, 0, 0, 0, 0},
6868
  {"show-slave-auth-info", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6869
   "Show user and password in SHOW SLAVE HOSTS on this master.",
6870
   &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
6871
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6872 6873
  {"silent-startup", OPT_SILENT, "Don't print [Note] to the error log during startup.",
   &opt_silent_startup, &opt_silent_startup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6874
  {"skip-bdb", OPT_DEPRECATED_OPTION,
Otto Kekäläinen's avatar
Otto Kekäläinen committed
6875
   "Deprecated option; Exist only for compatibility with old my.cnf files",
6876
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6877
#ifndef DISABLE_GRANT_OPTIONS
6878
  {"skip-grant-tables", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6879
   "Start without grant tables. This gives all users FULL ACCESS to all tables.",
6880
   &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6881
   0},
6882
#endif
unknown's avatar
unknown committed
6883 6884
  {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6885
  {"skip-slave-start", 0,
6886 6887
   "If set, slave is not autostarted.", &opt_skip_slave_start,
   &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6888 6889 6890
#ifdef HAVE_REPLICATION
  {"slave-parallel-mode", OPT_SLAVE_PARALLEL_MODE,
   "Controls what transactions are applied in parallel when using "
6891 6892 6893 6894 6895 6896 6897
   "--slave-parallel-threads. Possible values: \"optimistic\" tries to "
   "apply most transactional DML in parallel, and handles any conflicts "
   "with rollback and retry. \"conservative\" limits parallelism in an "
   "effort to avoid any conflicts. \"aggressive\" tries to maximise the "
   "parallelism, possibly at the cost of increased conflict rate. "
   "\"minimal\" only parallelizes the commit steps of transactions. "
   "\"none\" disables parallel apply completely.",
6898
   &opt_slave_parallel_mode, &opt_slave_parallel_mode,
6899 6900
   &slave_parallel_mode_typelib, GET_ENUM | GET_ASK_ADDR, REQUIRED_ARG,
   SLAVE_PARALLEL_CONSERVATIVE, 0, 0, 0, 0, 0},
6901
#endif
6902 6903 6904 6905 6906 6907 6908
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  {"slow-start-timeout", 0,
   "Maximum number of milliseconds that the service control manager should wait "
   "before trying to kill the windows service during startup"
   "(Default: 15000).", &slow_start_timeout, &slow_start_timeout, 0,
   GET_ULONG, REQUIRED_ARG, 15000, 0, 0, 0, 0, 0},
#endif
6909
#ifdef HAVE_OPENSSL
6910
  {"ssl", 0,
6911
   "Enable SSL for connection (automatically enabled if an ssl option is used).",
6912
   &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
6913
   0, 0, 0},
6914
#endif
unknown's avatar
unknown committed
6915
#ifdef __WIN__
6916
  {"standalone", 0,
unknown's avatar
unknown committed
6917 6918 6919 6920
  "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
   NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
  {"symbolic-links", 's', "Enable symbolic link support.",
6921
   &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
6922 6923 6924 6925
   /*
     The system call realpath() produces warnings under valgrind and
     purify. These are not suppressed: instead we disable symlinks
     option if compiled with valgrind support.
6926 6927
     Also disable by default on Windows, due to high overhead for checking .sym 
     files.
6928
   */
6929
   IF_VALGRIND(0,IF_WIN(0,1)), 0, 0, 0, 0, 0},
6930
  {"sysdate-is-now", 0,
6931 6932 6933 6934
   "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. "
   "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
   "invocations, even within the same statement.",
   &global_system_variables.sysdate_is_now,
unknown's avatar
unknown committed
6935
   0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
6936
  {"tc-heuristic-recover", 0,
6937 6938
   "Decision to use in heuristic recover process",
   &tc_heuristic_recover, &tc_heuristic_recover,
6939 6940
   &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"temp-pool", 0,
6941
#if (ENABLE_TEMP_POOL)
6942 6943
   "Using this option will cause most temporary files created to use a small "
   "set of names, rather than a unique name for each new file.",
6944 6945 6946
#else
   "This option is ignored on this OS.",
#endif
6947
   &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
unknown's avatar
unknown committed
6948
   0, 0, 0, 0, 0},
6949
  {"transaction-isolation", 0,
6950
   "Default transaction isolation level",
6951 6952
   &global_system_variables.tx_isolation,
   &global_system_variables.tx_isolation, &tx_isolation_typelib,
6953
   GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
6954 6955 6956 6957 6958 6959
  {"transaction-read-only", 0,
   "Default transaction access mode. "
   "True if transactions are read-only.",
   &global_system_variables.tx_read_only,
   &global_system_variables.tx_read_only, 0,
   GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
6960
  {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6961
   0, 0, 0, 0, 0, 0},
Staale Smedseng's avatar
Staale Smedseng committed
6962
  {"verbose", 'v', "Used with --help option for detailed help.",
6963
   &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6964 6965
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_STR,
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6966
  {"plugin-load", OPT_PLUGIN_LOAD,
6967 6968 6969
   "Semicolon-separated list of plugins to load, where each plugin is "
   "specified as ether a plugin_name=library_file pair or only a library_file. "
   "If the latter case, all plugins from a given library_file will be loaded.",
6970
   0, 0, 0,
unknown's avatar
unknown committed
6971
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6972 6973
  {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
   "Optional semicolon-separated list of plugins to load. This option adds "
6974
   "to the list specified by --plugin-load in an incremental way. "
6975 6976 6977
   "It can be specified many times, adding more plugins every time.",
   0, 0, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6978
  {"table_cache", 0, "Deprecated; use --table-open-cache instead.",
6979
   &tc_size, &tc_size, 0, GET_ULONG,
6980
   REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
Monty's avatar
Monty committed
6981 6982 6983 6984 6985 6986 6987
#ifdef WITH_WSREP
  {"wsrep-new-cluster", 0, "Bootstrap a cluster. It works by overriding the "
   "current value of wsrep_cluster_address. It is recommended not to add this "
   "option to the config file as this will trigger bootstrap on every server "
   "start.", &wsrep_new_cluster, &wsrep_new_cluster, 0, GET_BOOL, NO_ARG,
   0, 0, 0, 0, 0, 0},
#endif
6988 6989 6990

  /* The following options exist in 5.6 but not in 10.0 */
  MYSQL_COMPATIBILITY_OPTION("log-raw"),
6991
  MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"),
6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021
  MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"),
  MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"),
  MYSQL_COMPATIBILITY_OPTION("master-info-repository"),
  MYSQL_COMPATIBILITY_OPTION("relay-log-info-repository"),
  MYSQL_SUGGEST_ANALOG_OPTION("binlog-rows-query-log-events", "--binlog-annotate-row-events"),
  MYSQL_COMPATIBILITY_OPTION("binlog-order-commits"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("log-throttle-queries-not-using-indexes"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("end-markers-in-json"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace"),              // OPTIMIZER_TRACE
  MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-features"),     // OPTIMIZER_TRACE
  MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-offset"),       // OPTIMIZER_TRACE
  MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-limit"),        // OPTIMIZER_TRACE
  MYSQL_TO_BE_IMPLEMENTED_OPTION("optimizer-trace-max-mem-size"), // OPTIMIZER_TRACE
  MYSQL_TO_BE_IMPLEMENTED_OPTION("eq-range-index-dive-limit"),
  MYSQL_COMPATIBILITY_OPTION("server-id-bits"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-rows-search-algorithms"), // HAVE_REPLICATION
  MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-allow-batching"),         // HAVE_REPLICATION
  MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-period"),      // HAVE_REPLICATION
  MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-group"),       // HAVE_REPLICATION
  MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"),  // HAVE_REPLICATION
  MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-private-key-path"), // HAVE_OPENSSL && !HAVE_YASSL
  MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-public-key-path"),  // HAVE_OPENSSL && !HAVE_YASSL

  /* The following options exist in 5.5 and 5.6 but not in 10.0 */
  MYSQL_SUGGEST_ANALOG_OPTION("abort-slave-event-count", "--debug-abort-slave-event-count"),
  MYSQL_SUGGEST_ANALOG_OPTION("disconnect-slave-event-count", "--debug-disconnect-slave-event-count"),
  MYSQL_SUGGEST_ANALOG_OPTION("exit-info", "--debug-exit-info"),
  MYSQL_SUGGEST_ANALOG_OPTION("max-binlog-dump-events", "--debug-max-binlog-dump-events"),
  MYSQL_SUGGEST_ANALOG_OPTION("sporadic-binlog-dump-fail", "--debug-sporadic-binlog-dump-fail"),
  MYSQL_COMPATIBILITY_OPTION("new"),
Monty's avatar
Monty committed
7022
  MYSQL_COMPATIBILITY_OPTION("show_compatibility_56"),
7023 7024 7025 7026

  /* The following options were added after 5.6.10 */
  MYSQL_TO_BE_IMPLEMENTED_OPTION("rpl-stop-slave-timeout"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("validate-user-plugins") // NO_EMBEDDED_ACCESS_CHECKS
7027
};
unknown's avatar
unknown committed
7028

7029 7030
static int show_queries(THD *thd, SHOW_VAR *var, char *buff,
                        enum enum_var_type scope)
7031
{
7032
  var->type= SHOW_LONGLONG;
7033
  var->value= &thd->query_id;
7034 7035 7036
  return 0;
}

7037

7038 7039
static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff,
                                enum enum_var_type scope)
7040
{
7041
  var->type= SHOW_MY_BOOL;
7042
  var->value= &thd->net.compress;
7043 7044 7045
  return 0;
}

7046 7047
static int show_starttime(THD *thd, SHOW_VAR *var, char *buff,
                          enum enum_var_type scope)
7048
{
7049
  var->type= SHOW_LONG;
7050
  var->value= buff;
unknown's avatar
unknown committed
7051
  *((long *)buff)= (long) (thd->query_start() - server_start_time);
7052 7053 7054
  return 0;
}

7055
#ifdef ENABLED_PROFILING
7056 7057
static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff,
                                enum enum_var_type scope)
7058 7059 7060 7061 7062 7063
{
  var->type= SHOW_LONG;
  var->value= buff;
  *((long *)buff)= (long) (thd->query_start() - flush_status_time);
  return 0;
}
7064
#endif
7065

7066
#ifdef HAVE_REPLICATION
7067 7068
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff,
                           enum enum_var_type scope)
7069
{
7070
  var->type= SHOW_CHAR;
7071 7072 7073 7074
  var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
  return 0;
}

7075 7076
static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff,
                              enum enum_var_type scope)
7077
{
7078
  Master_info *mi= NULL;
7079
  bool UNINIT_VAR(tmp);
unknown's avatar
unknown committed
7080

7081 7082
  var->type= SHOW_MY_BOOL;
  var->value= buff;
7083 7084 7085

  if ((mi= get_master_info(&thd->variables.default_master_connection,
                           Sql_condition::WARN_LEVEL_NOTE)))
7086
  {
7087 7088 7089
    tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING &&
                    mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN);
    mi->release();
7090
  }
unknown's avatar
unknown committed
7091 7092
  if (mi)
    *((my_bool *)buff)= tmp;
7093
  else
7094
    var->type= SHOW_UNDEF;
7095 7096
  return 0;
}
Andrei Elkin's avatar
Andrei Elkin committed
7097

7098

Monty's avatar
Monty committed
7099 7100 7101 7102 7103 7104 7105
/* How many slaves are connected to this master */

static int show_slaves_connected(THD *thd, SHOW_VAR *var, char *buff)
{

  var->type= SHOW_LONGLONG;
  var->value= buff;
Sergey Vojtovich's avatar
Sergey Vojtovich committed
7106
  *((longlong*) buff)= uint32_t(binlog_dump_thread_count);
Monty's avatar
Monty committed
7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118
  return 0;
}


/* How many masters this slave is connected to */


static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff)
{
  var->type= SHOW_LONGLONG;
  var->value= buff;

7119
  *((longlong *)buff)= any_slave_sql_running(false);
Monty's avatar
Monty committed
7120 7121 7122 7123 7124

  return 0;
}


7125 7126
static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff,
                                          enum enum_var_type scope)
Andrei Elkin's avatar
Andrei Elkin committed
7127
{
7128
  Master_info *mi;
unknown's avatar
unknown committed
7129

7130 7131
  var->type= SHOW_LONGLONG;
  var->value= buff;
7132 7133 7134

  if ((mi= get_master_info(&thd->variables.default_master_connection,
                           Sql_condition::WARN_LEVEL_NOTE)))
7135
  {
7136 7137
    *((longlong *)buff)= mi->received_heartbeats;
    mi->release();
7138
  }
Andrei Elkin's avatar
Andrei Elkin committed
7139 7140 7141 7142 7143
  else
    var->type= SHOW_UNDEF;
  return 0;
}

7144

7145 7146
static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff,
                                 enum enum_var_type scope)
Andrei Elkin's avatar
Andrei Elkin committed
7147
{
Marko Mäkelä's avatar
Marko Mäkelä committed
7148
  Master_info *mi;
unknown's avatar
unknown committed
7149

7150 7151
  var->type= SHOW_CHAR;
  var->value= buff;
7152 7153 7154

  if ((mi= get_master_info(&thd->variables.default_master_connection,
                           Sql_condition::WARN_LEVEL_NOTE)))
7155
  {
7156 7157
    sprintf(buff, "%.3f", mi->heartbeat_period);
    mi->release();
7158
  }
Andrei Elkin's avatar
Andrei Elkin committed
7159 7160 7161 7162 7163 7164
  else
    var->type= SHOW_UNDEF;
  return 0;
}


7165 7166
#endif /* HAVE_REPLICATION */

7167 7168
static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff,
                            enum enum_var_type scope)
7169
{
7170
  var->type= SHOW_LONG;
7171
  var->value= buff;
7172
  *((long *) buff)= (long) tc_records();
7173 7174 7175
  return 0;
}

7176 7177
static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff,
                                    enum enum_var_type scope)
unknown's avatar
unknown committed
7178 7179 7180
{
  var->type= SHOW_LONG;
  var->value= buff;
Marc Alff's avatar
Marc Alff committed
7181
  mysql_mutex_lock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7182
  *((long *)buff)= (long)prepared_stmt_count;
Marc Alff's avatar
Marc Alff committed
7183
  mysql_mutex_unlock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7184 7185 7186
  return 0;
}

7187 7188
static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff,
                                  enum enum_var_type scope)
7189
{
7190
  var->type= SHOW_LONG;
7191
  var->value= buff;
7192
  *((long *) buff)= (long) tdc_records();
7193 7194 7195
  return 0;
}

7196

7197 7198
static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff,
                               enum enum_var_type scope)
7199
{
7200
  var->type= SHOW_LONGLONG;
7201
  var->value= buff;
7202
  *((longlong *) buff)= (longlong)tdc_refresh_version();
7203 7204 7205 7206
  return 0;
}


Konstantin Osipov's avatar
Konstantin Osipov committed
7207
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
7208

7209
/*
7210
   Functions relying on SSL
7211 7212 7213 7214 7215
   Note: In the show_ssl_* functions, we need to check if we have a
         valid vio-object since this isn't always true, specifically
         when session_status or global_status is requested from
         inside an Event.
 */
7216 7217 7218

static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff,
                                enum enum_var_type scope)
7219
{
7220
  var->type= SHOW_CHAR;
7221 7222 7223
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
  else
7224
    var->value= const_cast<char*>("");
7225 7226 7227
  return 0;
}

7228 7229
static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff,
                                        enum enum_var_type scope)
7230
{
7231
  var->type= SHOW_LONG;
7232
  var->value= buff;
7233 7234 7235 7236
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    *((long *)buff)= (long)SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg);
  else
    *((long *)buff)= 0;
7237 7238 7239
  return 0;
}

7240 7241
static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff,
                                    enum enum_var_type scope)
7242
{
7243
  var->type= SHOW_LONG;
7244
  var->value= buff;
7245
#ifndef HAVE_YASSL
7246 7247 7248 7249
  if( thd->net.vio && thd->net.vio->ssl_arg )
    *((long *)buff)= (long)SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg);
  else
    *((long *)buff)= 0;
7250 7251 7252
#else
  *((long *)buff) = 0;
#endif
7253 7254 7255
  return 0;
}

7256 7257
static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff,
                                     enum enum_var_type scope)
7258
{
7259
  var->type= SHOW_LONG;
7260
  var->value= buff;
7261
#ifndef HAVE_YASSL
7262 7263 7264 7265
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    *((long *)buff)= (long)SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg);
  else
    *((long *)buff)= 0;
7266 7267 7268 7269
#else
  *((long *)buff)= 0;
#endif

7270 7271 7272
  return 0;
}

7273 7274
static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff,
                               enum enum_var_type scope)
7275
{
7276
  var->type= SHOW_CHAR;
7277 7278 7279
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
  else
7280
    var->value= const_cast<char*>("");
7281 7282 7283
  return 0;
}

7284 7285
static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff,
                                    enum enum_var_type scope)
7286
{
7287
  var->type= SHOW_CHAR;
7288
  var->value= buff;
7289
  if (thd->vio_ok() && thd->net.vio->ssl_arg)
7290 7291 7292
  {
    int i;
    const char *p;
7293 7294 7295
    char *end= buff + SHOW_VAR_FUNC_BUFF_SIZE;
    for (i=0; (p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i)) &&
               buff < end; i++)
7296
    {
7297
      buff= strnmov(buff, p, end-buff-1);
7298 7299 7300 7301 7302 7303 7304 7305 7306
      *buff++= ':';
    }
    if (i)
      buff--;
  }
  *buff=0;
  return 0;
}

7307 7308 7309 7310 7311 7312
#define SHOW_FNAME(name)                        \
    rpl_semi_sync_master_show_##name

#define DEF_SHOW_FUNC(name, show_type)                                       \
    static  int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR *var, char *buff)   \
    {                                                                        \
7313
      repl_semisync_master.set_export_stats();                                 \
7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327
      var->type= show_type;                                                  \
      var->value= (char *)&rpl_semi_sync_master_##name;                      \
      return 0;                                                              \
    }

DEF_SHOW_FUNC(status, SHOW_BOOL)
DEF_SHOW_FUNC(clients, SHOW_LONG)
DEF_SHOW_FUNC(wait_sessions, SHOW_LONG)
DEF_SHOW_FUNC(trx_wait_time, SHOW_LONGLONG)
DEF_SHOW_FUNC(trx_wait_num, SHOW_LONGLONG)
DEF_SHOW_FUNC(net_wait_time, SHOW_LONGLONG)
DEF_SHOW_FUNC(net_wait_num, SHOW_LONGLONG)
DEF_SHOW_FUNC(avg_net_wait_time, SHOW_LONG)
DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG)
7328 7329 7330 7331

#ifdef HAVE_YASSL

static char *
7332
my_asn1_time_to_string(const ASN1_TIME *time, char *buf, size_t len)
7333 7334 7335 7336 7337 7338 7339
{
  return yaSSL_ASN1_TIME_to_string(time, buf, len);
}

#else /* openssl */

static char *
7340
my_asn1_time_to_string(const ASN1_TIME *time, char *buf, size_t len)
7341 7342 7343 7344 7345 7346 7347 7348
{
  int n_read;
  char *res= NULL;
  BIO *bio= BIO_new(BIO_s_mem());

  if (bio == NULL)
    return NULL;

7349
  if (!ASN1_TIME_print(bio, const_cast<ASN1_TIME*>(time)))
7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379
    goto end;

  n_read= BIO_read(bio, buf, (int) (len - 1));

  if (n_read > 0)
  {
    buf[n_read]= 0;
    res= buf;
  }

end:
  BIO_free(bio);
  return res;
}

#endif


/**
  Handler function for the 'ssl_get_server_not_before' variable

  @param      thd  the mysql thread structure
  @param      var  the data for the variable
  @param[out] buf  the string to put the value of the variable into

  @return          status
  @retval     0    success
*/

static int
7380 7381
show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff,
                               enum enum_var_type scope)
7382 7383 7384 7385 7386 7387
{
  var->type= SHOW_CHAR;
  if(thd->vio_ok() && thd->net.vio->ssl_arg)
  {
    SSL *ssl= (SSL*) thd->net.vio->ssl_arg;
    X509 *cert= SSL_get_certificate(ssl);
7388
    const ASN1_TIME *not_before= X509_get0_notBefore(cert);
7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413

    var->value= my_asn1_time_to_string(not_before, buff,
                                       SHOW_VAR_FUNC_BUFF_SIZE);
    if (!var->value)
      return 1;
    var->value= buff;
  }
  else
    var->value= empty_c_string;
  return 0;
}


/**
  Handler function for the 'ssl_get_server_not_after' variable

  @param      thd  the mysql thread structure
  @param      var  the data for the variable
  @param[out] buf  the string to put the value of the variable into

  @return          status
  @retval     0    success
*/

static int
7414 7415
show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff,
                              enum enum_var_type scope)
7416 7417 7418 7419 7420 7421
{
  var->type= SHOW_CHAR;
  if(thd->vio_ok() && thd->net.vio->ssl_arg)
  {
    SSL *ssl= (SSL*) thd->net.vio->ssl_arg;
    X509 *cert= SSL_get_certificate(ssl);
7422
    const ASN1_TIME *not_after= X509_get0_notAfter(cert);
7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433

    var->value= my_asn1_time_to_string(not_after, buff,
                                       SHOW_VAR_FUNC_BUFF_SIZE);
    if (!var->value)
      return 1;
  }
  else
    var->value= empty_c_string;
  return 0;
}

Konstantin Osipov's avatar
Konstantin Osipov committed
7434
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
7435

7436 7437
static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff,
                                 enum enum_var_type scope)
7438 7439 7440
{
  struct st_data {
    KEY_CACHE_STATISTICS stats;
7441
    SHOW_VAR var[9];
7442 7443 7444 7445 7446 7447 7448
  } *data;
  SHOW_VAR *v;

  data=(st_data *)buff;
  v= data->var;

  var->type= SHOW_ARRAY;
7449
  var->value= v;
7450 7451 7452 7453 7454 7455

  get_key_cache_statistics(dflt_key_cache, 0, &data->stats);

#define set_one_keycache_var(X,Y)       \
  v->name= X;                           \
  v->type= SHOW_LONGLONG;               \
7456
  v->value= &data->stats.Y;      \
7457 7458 7459 7460 7461
  v++;

  set_one_keycache_var("blocks_not_flushed", blocks_changed);
  set_one_keycache_var("blocks_unused",      blocks_unused);
  set_one_keycache_var("blocks_used",        blocks_used);
Sergei Golubchik's avatar
Sergei Golubchik committed
7462
  set_one_keycache_var("blocks_warm",        blocks_warm);
7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476
  set_one_keycache_var("read_requests",      read_requests);
  set_one_keycache_var("reads",              reads);
  set_one_keycache_var("write_requests",     write_requests);
  set_one_keycache_var("writes",             writes);

  v->name= 0;

  DBUG_ASSERT((char*)(v+1) <= buff + SHOW_VAR_FUNC_BUFF_SIZE);

#undef set_one_keycache_var

  return 0;
}

7477 7478

static int show_memory_used(THD *thd, SHOW_VAR *var, char *buff,
7479
                            struct system_status_var *status_var,
7480 7481 7482 7483 7484
                            enum enum_var_type scope)
{
  var->type= SHOW_LONGLONG;
  var->value= buff;
  if (scope == OPT_GLOBAL)
7485 7486
    *(longlong*) buff= (status_var->global_memory_used +
                        status_var->local_memory_used);
7487
  else
7488
    *(longlong*) buff= status_var->local_memory_used;
7489 7490 7491 7492
  return 0;
}


7493
#ifndef DBUG_OFF
7494 7495
static int debug_status_func(THD *thd, SHOW_VAR *var, char *buff,
                             enum enum_var_type scope)
7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510
{
#define add_var(X,Y,Z)                  \
  v->name= X;                           \
  v->value= (char*)Y;                   \
  v->type= Z;                           \
  v++;

  var->type= SHOW_ARRAY;
  var->value= buff;

  SHOW_VAR *v= (SHOW_VAR *)buff;

  if (_db_keyword_(0, "role_merge_stats", 1))
  {
    static SHOW_VAR roles[]= {
7511 7512 7513 7514 7515
      {"global",  &role_global_merges,  SHOW_ULONG},
      {"db",      &role_db_merges,      SHOW_ULONG},
      {"table",   &role_table_merges,   SHOW_ULONG},
      {"column",  &role_column_merges,  SHOW_ULONG},
      {"routine", &role_routine_merges, SHOW_ULONG},
7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529
      {NullS, NullS, SHOW_LONG}
    };

    add_var("role_merges", roles, SHOW_ARRAY);
  }

  v->name= 0;

#undef add_var

  return 0;
}
#endif

7530
#ifdef HAVE_POOL_OF_THREADS
7531 7532
int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff,
                                 enum enum_var_type scope)
7533 7534 7535 7536 7537 7538 7539
{
  var->type= SHOW_INT;
  var->value= buff;
  *(int *)buff= tp_get_idle_thread_count(); 
  return 0;
}
#endif
7540

7541 7542 7543 7544
/*
  Variables shown by SHOW STATUS in alphabetical order
*/

7545
SHOW_VAR status_vars[]= {
7546 7547
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
7548
  {"Acl",                      (char*) acl_statistics,          SHOW_ARRAY},
7549
  {"Access_denied_errors",     (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7550
  {"Binlog_bytes_written",     (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
7551 7552
  {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
  {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
7553 7554
  {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,  SHOW_LONG},
  {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,       SHOW_LONG},
7555
  {"Busy_time",                (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
7556 7557
  {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
  {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
7558 7559
  {"Column_compressions",      (char*) offsetof(STATUS_VAR, column_compressions), SHOW_LONG_STATUS},
  {"Column_decompressions",    (char*) offsetof(STATUS_VAR, column_decompressions), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
7560
  {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
7561
  {"Compression",              (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
7562
  {"Connections",              (char*) &global_thread_id,         SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7563 7564 7565 7566 7567 7568
  {"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG},
  {"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG},
  {"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG},
  {"Connection_errors_peer_address", (char*) &connection_errors_peer_addr, SHOW_LONG},
  {"Connection_errors_select", (char*) &connection_errors_select, SHOW_LONG},
  {"Connection_errors_tcpwrap", (char*) &connection_errors_tcpwrap, SHOW_LONG},
7569
  {"Cpu_time",                 (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7570
  {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables_), SHOW_LONG_STATUS},
7571
  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
Sergei Golubchik's avatar
Sergei Golubchik committed
7572
  {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables_), SHOW_LONG_STATUS},
7573 7574 7575
#ifndef DBUG_OFF
  {"Debug",                    (char*) &debug_status_func,  SHOW_FUNC},
#endif
7576
  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
7577
  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
7578
  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
7579
  {"Delete_scan",	       (char*) offsetof(STATUS_VAR, delete_scan_count), SHOW_LONG_STATUS},
7580
  {"Empty_queries",            (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS},
7581 7582
  {"Executed_events",          (char*) &executed_events, SHOW_LONG_NOFLUSH },
  {"Executed_triggers",        (char*) offsetof(STATUS_VAR, executed_triggers), SHOW_LONG_STATUS},
7583
  {"Feature_check_constraint", (char*) &feature_check_constraint, SHOW_LONG },
7584
  {"Feature_custom_aggregate_functions", (char*) offsetof(STATUS_VAR, feature_custom_aggregate_functions), SHOW_LONG_STATUS},
7585
  {"Feature_delay_key_write",  (char*) &feature_files_opened_with_delayed_keys, SHOW_LONG },
7586 7587 7588
  {"Feature_dynamic_columns",  (char*) offsetof(STATUS_VAR, feature_dynamic_columns), SHOW_LONG_STATUS},
  {"Feature_fulltext",         (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS},
  {"Feature_gis",              (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS},
7589
  {"Feature_invisible_columns",   (char*) offsetof(STATUS_VAR, feature_invisible_columns), SHOW_LONG_STATUS},
7590
  {"Feature_json",             (char*) offsetof(STATUS_VAR, feature_json), SHOW_LONG_STATUS},
7591 7592
  {"Feature_locale",           (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
  {"Feature_subquery",         (char*) offsetof(STATUS_VAR, feature_subquery), SHOW_LONG_STATUS},
7593
  {"Feature_system_versioning",   (char*) offsetof(STATUS_VAR, feature_system_versioning), SHOW_LONG_STATUS},
7594
  {"Feature_timezone",         (char*) offsetof(STATUS_VAR, feature_timezone), SHOW_LONG_STATUS},
7595
  {"Feature_trigger",          (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS},
7596
  {"Feature_window_functions", (char*) offsetof(STATUS_VAR, feature_window_functions), SHOW_LONG_STATUS},
7597
  {"Feature_xml",              (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS},
7598
  {"Flush_commands",           (char*) &show_flush_commands, SHOW_SIMPLE_FUNC},
unknown's avatar
Merge  
unknown committed
7599 7600 7601
  {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
  {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
  {"Handler_discover",         (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
7602
  {"Handler_external_lock",    (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONG_STATUS},
7603
  {"Handler_icp_attempts",     (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
7604 7605
  {"Handler_icp_match",        (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS},
  {"Handler_mrr_init",         (char*) offsetof(STATUS_VAR, ha_mrr_init_count),  SHOW_LONG_STATUS},
7606 7607
  {"Handler_mrr_key_refills",  (char*) offsetof(STATUS_VAR, ha_mrr_key_refills_count), SHOW_LONG_STATUS},
  {"Handler_mrr_rowid_refills",(char*) offsetof(STATUS_VAR, ha_mrr_rowid_refills_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7608 7609 7610
  {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),  SHOW_LONG_STATUS},
  {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
  {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
7611
  {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7612 7613
  {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
  {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
7614
  {"Handler_read_retry",       (char*) offsetof(STATUS_VAR, ha_read_retry_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7615
  {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
7616
  {"Handler_read_rnd_deleted", (char*) offsetof(STATUS_VAR, ha_read_rnd_deleted_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7617 7618 7619 7620
  {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
  {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
  {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
  {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
7621
  {"Handler_tmp_delete",       (char*) offsetof(STATUS_VAR, ha_tmp_delete_count), SHOW_LONG_STATUS},
7622 7623
  {"Handler_tmp_update",       (char*) offsetof(STATUS_VAR, ha_tmp_update_count), SHOW_LONG_STATUS},
  {"Handler_tmp_write",        (char*) offsetof(STATUS_VAR, ha_tmp_write_count), SHOW_LONG_STATUS},
7624 7625
  {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
  {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
7626
  {"Key",                      (char*) &show_default_keycache, SHOW_FUNC},
7627
  {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
7628
  {"Max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS},
7629 7630 7631
  {"Master_gtid_wait_count",   (char*) offsetof(STATUS_VAR, master_gtid_wait_count), SHOW_LONGLONG_STATUS},
  {"Master_gtid_wait_timeouts", (char*) offsetof(STATUS_VAR, master_gtid_wait_timeouts), SHOW_LONGLONG_STATUS},
  {"Master_gtid_wait_time",    (char*) offsetof(STATUS_VAR, master_gtid_wait_time), SHOW_LONGLONG_STATUS},
7632
  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
7633
  {"Memory_used",              (char*) &show_memory_used, SHOW_SIMPLE_FUNC},
7634
  {"Memory_used_initial",      (char*) &start_memory_used, SHOW_LONGLONG},
7635 7636 7637
  {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,    SHOW_LONG_NOFLUSH},
  {"Open_files",               (char*) &my_file_opened,         SHOW_LONG_NOFLUSH},
  {"Open_streams",             (char*) &my_stream_opened,       SHOW_LONG_NOFLUSH},
7638 7639
  {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_SIMPLE_FUNC},
  {"Open_tables",              (char*) &show_open_tables,       SHOW_SIMPLE_FUNC},
7640
  {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
7641
  {"Opened_plugin_libraries",  (char*) &dlopen_count, SHOW_LONG},
7642
  {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7643
  {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
7644
  {"Opened_views",             (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
7645
  {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC},
Sergei Golubchik's avatar
Sergei Golubchik committed
7646
  {"Rows_sent",                (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
7647
  {"Rows_read",                (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
7648
  {"Rows_tmp_read",            (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668
#ifdef HAVE_REPLICATION
  {"Rpl_semi_sync_master_status", (char*) &SHOW_FNAME(status), SHOW_FUNC},
  {"Rpl_semi_sync_master_clients", (char*) &SHOW_FNAME(clients), SHOW_FUNC},
  {"Rpl_semi_sync_master_yes_tx", (char*) &rpl_semi_sync_master_yes_transactions, SHOW_LONG},
  {"Rpl_semi_sync_master_no_tx", (char*) &rpl_semi_sync_master_no_transactions, SHOW_LONG},
  {"Rpl_semi_sync_master_wait_sessions", (char*) &SHOW_FNAME(wait_sessions), SHOW_FUNC},
  {"Rpl_semi_sync_master_no_times", (char*) &rpl_semi_sync_master_off_times, SHOW_LONG},
  {"Rpl_semi_sync_master_timefunc_failures", (char*) &rpl_semi_sync_master_timefunc_fails, SHOW_LONG},
  {"Rpl_semi_sync_master_wait_pos_backtraverse", (char*) &rpl_semi_sync_master_wait_pos_backtraverse, SHOW_LONG},
  {"Rpl_semi_sync_master_tx_wait_time", (char*) &SHOW_FNAME(trx_wait_time), SHOW_FUNC},
  {"Rpl_semi_sync_master_tx_waits", (char*) &SHOW_FNAME(trx_wait_num), SHOW_FUNC},
  {"Rpl_semi_sync_master_tx_avg_wait_time", (char*) &SHOW_FNAME(avg_trx_wait_time), SHOW_FUNC},
  {"Rpl_semi_sync_master_net_wait_time", (char*) &SHOW_FNAME(net_wait_time), SHOW_FUNC},
  {"Rpl_semi_sync_master_net_waits", (char*) &SHOW_FNAME(net_wait_num), SHOW_FUNC},
  {"Rpl_semi_sync_master_net_avg_wait_time", (char*) &SHOW_FNAME(avg_net_wait_time), SHOW_FUNC},
  {"Rpl_semi_sync_master_request_ack", (char*) &rpl_semi_sync_master_request_ack, SHOW_LONGLONG},
  {"Rpl_semi_sync_master_get_ack", (char*)&rpl_semi_sync_master_get_ack, SHOW_LONGLONG},
  {"Rpl_semi_sync_slave_status", (char*) &rpl_semi_sync_slave_status, SHOW_BOOL},
  {"Rpl_semi_sync_slave_send_ack", (char*) &rpl_semi_sync_slave_send_ack, SHOW_LONGLONG},
#endif /* HAVE_REPLICATION */
unknown's avatar
unknown committed
7669
#ifdef HAVE_QUERY_CACHE
7670 7671
  {"Qcache_free_blocks",       (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
  {"Qcache_free_memory",       (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7672
  {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
7673
  {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
7674
  {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
unknown's avatar
unknown committed
7675
  {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
7676 7677
  {"Qcache_queries_in_cache",  (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH},
  {"Qcache_total_blocks",      (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7678
#endif /*HAVE_QUERY_CACHE*/
7679
  {"Queries",                  (char*) &show_queries,            SHOW_SIMPLE_FUNC},
7680
  {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
7681
#ifdef HAVE_REPLICATION
7682
  {"Rpl_status",               (char*) &show_rpl_status,          SHOW_SIMPLE_FUNC},
7683
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
7684 7685 7686 7687 7688
  {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count_), SHOW_LONG_STATUS},
  {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count_), SHOW_LONG_STATUS},
  {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count_), SHOW_LONG_STATUS},
  {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count_), SHOW_LONG_STATUS},
  {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count_), SHOW_LONG_STATUS},
Michael Widenius's avatar
Michael Widenius committed
7689
  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_INT},
7690
#ifdef HAVE_REPLICATION
Monty's avatar
Monty committed
7691 7692 7693
  {"Slaves_connected",        (char*) &show_slaves_connected, SHOW_SIMPLE_FUNC },
  {"Slaves_running",          (char*) &show_slaves_running, SHOW_SIMPLE_FUNC },
  {"Slave_connections",       (char*) offsetof(STATUS_VAR, com_register_slave), SHOW_LONG_STATUS},
7694 7695
  {"Slave_heartbeat_period",   (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC},
  {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC},
Sergei Golubchik's avatar
Sergei Golubchik committed
7696
  {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
7697
  {"Slave_running",            (char*) &show_slave_running,     SHOW_SIMPLE_FUNC},
7698
  {"Slave_skipped_errors",     (char*) &slave_skipped_errors, SHOW_LONGLONG},
7699
#endif
7700
  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
unknown's avatar
Merge  
unknown committed
7701
  {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7702
  {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes_), SHOW_LONG_STATUS},
7703
  {"Sort_priority_queue_sorts",(char*) offsetof(STATUS_VAR, filesort_pq_sorts_), SHOW_LONG_STATUS}, 
Sergei Golubchik's avatar
Sergei Golubchik committed
7704 7705 7706
  {"Sort_range",	       (char*) offsetof(STATUS_VAR, filesort_range_count_), SHOW_LONG_STATUS},
  {"Sort_rows",		       (char*) offsetof(STATUS_VAR, filesort_rows_), SHOW_LONG_STATUS},
  {"Sort_scan",		       (char*) offsetof(STATUS_VAR, filesort_scan_count_), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
7707
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
7708
#ifndef EMBEDDED_LIBRARY
7709 7710 7711
  {"Ssl_accept_renegotiates",  (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_accepts",              (char*) &ssl_acceptor_stats.accept, SHOW_LONG},
  {"Ssl_callback_cache_hits",  (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
7712 7713
  {"Ssl_cipher",               (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC},
  {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC},
7714 7715 7716 7717
  {"Ssl_client_connects",      (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_connect_renegotiates", (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_ctx_verify_depth",     (char*) &ssl_acceptor_stats.verify_depth, SHOW_LONG},
  {"Ssl_ctx_verify_mode",      (char*) &ssl_acceptor_stats.verify_mode, SHOW_LONG},
7718
  {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC},
7719 7720
  {"Ssl_finished_accepts",     (char*) &ssl_acceptor_stats.accept_good, SHOW_LONG},
  {"Ssl_finished_connects",    (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
Sergei Golubchik's avatar
Sergei Golubchik committed
7721 7722
  {"Ssl_server_not_after",     (char*) &show_ssl_get_server_not_after, SHOW_SIMPLE_FUNC},
  {"Ssl_server_not_before",    (char*) &show_ssl_get_server_not_before, SHOW_SIMPLE_FUNC},
7723 7724 7725 7726 7727 7728 7729 7730
  {"Ssl_session_cache_hits",   (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_session_cache_misses", (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_session_cache_mode",   (char*) &ssl_acceptor_stats.session_cache_mode, SHOW_CHAR_PTR},
  {"Ssl_session_cache_overflows", (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_session_cache_size",   (char*) &ssl_acceptor_stats.cache_size, SHOW_LONG},
  {"Ssl_session_cache_timeouts", (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_sessions_reused",      (char*) &ssl_acceptor_stats.zero, SHOW_LONG},
  {"Ssl_used_session_cache_entries",(char*) &ssl_acceptor_stats.zero, SHOW_LONG},
7731 7732 7733
  {"Ssl_verify_depth",         (char*) &show_ssl_get_verify_depth, SHOW_SIMPLE_FUNC},
  {"Ssl_verify_mode",          (char*) &show_ssl_get_verify_mode, SHOW_SIMPLE_FUNC},
  {"Ssl_version",              (char*) &show_ssl_get_version, SHOW_SIMPLE_FUNC},
Konstantin Osipov's avatar
Konstantin Osipov committed
7734
#endif
unknown's avatar
unknown committed
7735
#endif /* HAVE_OPENSSL */
7736
  {"Syncs",                    (char*) &my_sync_count,          SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7737 7738 7739 7740
  /*
    Expression cache used only for caching subqueries now, so its statistic
    variables we call subquery_cache*.
  */
7741 7742
  {"Subquery_cache_hit",       (char*) &subquery_cache_hit,     SHOW_LONG},
  {"Subquery_cache_miss",      (char*) &subquery_cache_miss,    SHOW_LONG},
unknown's avatar
unknown committed
7743 7744
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
7745 7746 7747 7748
  {"Table_open_cache_active_instances", (char*) &tc_active_instances, SHOW_UINT},
  {"Table_open_cache_hits",    (char*) offsetof(STATUS_VAR, table_open_cache_hits), SHOW_LONGLONG_STATUS},
  {"Table_open_cache_misses",  (char*) offsetof(STATUS_VAR, table_open_cache_misses), SHOW_LONGLONG_STATUS},
  {"Table_open_cache_overflows", (char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS},
7749
#ifdef HAVE_MMAP
unknown's avatar
Merge  
unknown committed
7750
  {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
7751
  {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
7752
  {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
7753
#endif
7754
#ifdef HAVE_POOL_OF_THREADS
7755
  {"Threadpool_idle_threads",  (char *) &show_threadpool_idle_threads, SHOW_SIMPLE_FUNC},
7756
  {"Threadpool_threads",       (char *) &tp_stats.num_worker_threads, SHOW_INT},
7757
#endif
7758
  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_NOFLUSH},
Konstantin Osipov's avatar
Konstantin Osipov committed
7759
  {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
7760
  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
7761
  {"Threads_running",          (char*) offsetof(STATUS_VAR, threads_running), SHOW_UINT32_STATUS},
7762 7763 7764
  {"Transactions_multi_engine", (char*) &transactions_multi_engine, SHOW_LONG},
  {"Rpl_transactions_multi_engine", (char*) &rpl_transactions_multi_engine, SHOW_LONG},
  {"Transactions_gtid_foreign_engine", (char*) &transactions_gtid_foreign_engine, SHOW_LONG},
7765
  {"Update_scan",	       (char*) offsetof(STATUS_VAR, update_scan_count), SHOW_LONG_STATUS},
7766
  {"Uptime",                   (char*) &show_starttime,         SHOW_SIMPLE_FUNC},
7767
#ifdef ENABLED_PROFILING
7768
  {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_SIMPLE_FUNC},
7769 7770
#endif
#ifdef WITH_WSREP
Brave Galera Crew's avatar
Brave Galera Crew committed
7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784
  {"wsrep_connected",         (char*) &wsrep_connected,         SHOW_BOOL},
  {"wsrep_ready",             (char*) &wsrep_show_ready,        SHOW_FUNC},
  {"wsrep_cluster_state_uuid",(char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
  {"wsrep_cluster_conf_id",   (char*) &wsrep_cluster_conf_id,   SHOW_LONGLONG},
  {"wsrep_cluster_status",    (char*) &wsrep_cluster_status,    SHOW_CHAR_PTR},
  {"wsrep_cluster_size",      (char*) &wsrep_cluster_size,      SHOW_LONG_NOFLUSH},
  {"wsrep_local_index",       (char*) &wsrep_local_index,       SHOW_LONG_NOFLUSH},
  {"wsrep_local_bf_aborts",   (char*) &wsrep_show_bf_aborts,    SHOW_FUNC},
  {"wsrep_provider_name",     (char*) &wsrep_provider_name,     SHOW_CHAR_PTR},
  {"wsrep_provider_version",  (char*) &wsrep_provider_version,  SHOW_CHAR_PTR},
  {"wsrep_provider_vendor",   (char*) &wsrep_provider_vendor,   SHOW_CHAR_PTR},
  {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
  {"wsrep_thread_count",      (char*) &wsrep_running_threads,   SHOW_LONG_NOFLUSH},
  {"wsrep_cluster_capabilities", (char*) &wsrep_cluster_capabilities, SHOW_CHAR_PTR},
7785
  {"wsrep",                    (char*) &wsrep_show_status,       SHOW_FUNC},
7786
#endif
7787
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
7788 7789
};

7790
static bool add_terminator(DYNAMIC_ARRAY *options)
7791 7792
{
  my_option empty_element= {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0};
Marc Alff's avatar
Marc Alff committed
7793
  return insert_dynamic(options, (uchar *)&empty_element);
7794 7795
}

7796 7797 7798 7799 7800 7801 7802 7803 7804
static bool add_many_options(DYNAMIC_ARRAY *options, my_option *list,
                            size_t elements)
{
  for (my_option *opt= list; opt < list + elements; opt++)
    if (insert_dynamic(options, opt))
      return 1;
  return 0;
}

7805
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
7806 7807
static void print_version(void)
{
7808 7809
  if (IS_SYSVAR_AUTOSIZE(&server_version_ptr))
    set_server_version(server_version, sizeof(server_version));
7810

7811 7812
  printf("%s  Ver %s for %s on %s (%s)\n",my_progname,
	 server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
unknown's avatar
unknown committed
7813 7814
}

7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842
/** Compares two options' names, treats - and _ the same */
static int option_cmp(my_option *a, my_option *b)
{
  const char *sa= a->name;
  const char *sb= b->name;
  for (; *sa || *sb; sa++, sb++)
  {
    if (*sa < *sb)
    {
      if (*sa == '-' && *sb == '_')
        continue;
      else
        return -1;
    }
    if (*sa > *sb)
    {
      if (*sa == '_' && *sb == '-')
        continue;
      else
        return 1;
    }
  }
  return 0;
}

static void print_help()
{
  MEM_ROOT mem_root;
7843
  init_alloc_root(&mem_root, "help", 4096, 4096, MYF(0));
7844 7845

  pop_dynamic(&all_options);
7846 7847
  add_many_options(&all_options, pfs_early_options,
                  array_elements(pfs_early_options));
Marc Alff's avatar
Marc Alff committed
7848
  sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
7849 7850
  add_plugin_options(&all_options, &mem_root);
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
7851
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
Marc Alff's avatar
Marc Alff committed
7852
  add_terminator(&all_options);
7853 7854

  my_print_help((my_option*) all_options.buffer);
7855

7856
  /* Add variables that must be shown but not changed, like version numbers */
7857
  pop_dynamic(&all_options);
7858
  sys_var_add_options(&all_options, sys_var::GETOPT_ONLY_HELP);
7859 7860
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
  add_terminator(&all_options);
7861 7862 7863 7864 7865
  my_print_variables((my_option*) all_options.buffer);

  free_root(&mem_root, MYF(0));
}

unknown's avatar
unknown committed
7866 7867
static void usage(void)
{
7868
  DBUG_ENTER("usage");
7869
  if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
unknown's avatar
unknown committed
7870 7871 7872 7873 7874
					           MY_CS_PRIMARY,
						   MYF(MY_WME))))
    exit(1);
  if (!default_collation_name)
    default_collation_name= (char*) default_charset_info->name;
unknown's avatar
unknown committed
7875
  print_version();
7876
  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
Sergei Golubchik's avatar
Sergei Golubchik committed
7877
  puts("Starts the MariaDB database server.\n");
unknown's avatar
unknown committed
7878
  printf("Usage: %s [OPTIONS]\n", my_progname);
7879
  if (!opt_verbose)
Staale Smedseng's avatar
Staale Smedseng committed
7880
    puts("\nFor more help options (several pages), use mysqld --verbose --help.");
7881 7882
  else
  {
unknown's avatar
unknown committed
7883
#ifdef __WIN__
Sergei Golubchik's avatar
Sergei Golubchik committed
7884 7885 7886 7887 7888 7889 7890 7891 7892
  puts("NT and Win32 specific options:\n"
       "  --install                     Install the default service (NT).\n"
       "  --install-manual              Install the default service started manually (NT).\n"
       "  --install service_name        Install an optional service (NT).\n"
       "  --install-manual service_name Install an optional service started manually (NT).\n"
       "  --remove                      Remove the default service from the service list (NT).\n"
       "  --remove service_name         Remove the service_name from the service list (NT).\n"
       "  --enable-named-pipe           Only to be used for the default server (NT).\n"
       "  --standalone                  Dummy option to start as a standalone server (NT).");
7893
  puts("");
unknown's avatar
unknown committed
7894
#endif
7895
  print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
unknown's avatar
unknown committed
7896 7897
  puts("");
  set_ports();
7898

unknown's avatar
unknown committed
7899
  /* Print out all the options including plugin supplied options */
7900
  print_help();
7901

7902 7903
  if (! plugins_are_initialized)
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
7904 7905
    puts("\nPlugins have parameters that are not reflected in this list"
         "\nbecause execution stopped before plugins were initialized.");
7906 7907
  }

Sergei Golubchik's avatar
Sergei Golubchik committed
7908 7909
  puts("\nTo see what values a running MySQL server is using, type"
       "\n'mysqladmin variables' instead of 'mysqld --verbose --help'.");
7910
  }
7911
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
7912
}
7913
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
7914

unknown's avatar
unknown committed
7915
/**
7916
  Initialize MySQL global variables to default values.
unknown's avatar
unknown committed
7917

unknown's avatar
unknown committed
7918
  @note
unknown's avatar
unknown committed
7919 7920 7921 7922
    The reason to set a lot of global variables to zero is to allow one to
    restart the embedded server with a clean environment
    It's also needed on some exotic platforms where global variables are
    not set to 0 when a program starts.
unknown's avatar
unknown committed
7923

7924
    We don't need to set variables refered to in my_long_options
unknown's avatar
unknown committed
7925 7926
    as these are initialized by my_getopt.
*/
unknown's avatar
unknown committed
7927

7928
static int mysql_init_variables(void)
unknown's avatar
unknown committed
7929 7930 7931 7932
{
  /* Things reset to zero */
  opt_skip_slave_start= opt_reckless_slave = 0;
  mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
7933
#if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH)
7934
  /*  We can only test for sub paths if my_symlink.c is using realpath */
7935
  mysys_test_invalid_symlink= path_starts_from_data_home_dir;
7936
#endif
Monty's avatar
Monty committed
7937
  opt_log= 0;
7938
  opt_bin_log= opt_bin_log_used= 0;
unknown's avatar
unknown committed
7939
  opt_disable_networking= opt_skip_show_db=0;
7940
  opt_skip_name_resolve= 0;
7941
  opt_ignore_builtin_innodb= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
7942
  opt_logname= opt_binlog_index_name= opt_slow_logname= 0;
7943
  opt_log_basename= 0;
unknown's avatar
Merge  
unknown committed
7944
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
7945 7946
  opt_secure_auth= 0;
  opt_bootstrap= opt_myisam_log= 0;
7947
  disable_log_notes= 0;
unknown's avatar
unknown committed
7948 7949 7950
  mqh_used= 0;
  cleanup_done= 0;
  test_flags= select_errors= dropping_tables= ha_open_options=0;
7951
  thread_count= kill_cached_threads= wake_thread= 0;
unknown's avatar
unknown committed
7952 7953 7954
  slave_open_temp_tables= 0;
  cached_thread_count= 0;
  opt_endinfo= using_udf_functions= 0;
7955
  opt_using_transactions= 0;
unknown's avatar
unknown committed
7956
  abort_loop= select_thread_in_use= signal_thread_in_use= 0;
7957
  grant_option= 0;
unknown's avatar
Merge  
unknown committed
7958
  aborted_threads= aborted_connects= 0;
unknown's avatar
unknown committed
7959
  subquery_cache_miss= subquery_cache_hit= 0;
unknown's avatar
unknown committed
7960 7961
  delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
  delayed_insert_errors= thread_created= 0;
unknown's avatar
Merge  
unknown committed
7962
  specialflag= 0;
7963
  binlog_cache_use=  binlog_cache_disk_use= 0;
unknown's avatar
unknown committed
7964 7965
  max_used_connections= slow_launch_threads = 0;
  mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
7966
  prepared_stmt_count= 0;
7967
  mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
7968
  bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
7969 7970 7971
  /* Clear all except global_memory_used */
  bzero((char*) &global_status_var, offsetof(STATUS_VAR,
                                             last_cleared_system_status_var));
7972
  opt_large_pages= 0;
7973
  opt_super_large_pages= 0;
7974 7975 7976
#if defined(ENABLED_DEBUG_SYNC)
  opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
7977
  key_map_full.set_all();
unknown's avatar
unknown committed
7978

7979 7980 7981 7982 7983
  /* Character sets */
  system_charset_info= &my_charset_utf8_general_ci;
  files_charset_info= &my_charset_utf8_general_ci;
  national_charset_info= &my_charset_utf8_general_ci;
  table_alias_charset= &my_charset_bin;
unknown's avatar
unknown committed
7984
  character_set_filesystem= &my_charset_bin;
7985

unknown's avatar
unknown committed
7986
  opt_specialflag= SPECIAL_ENGLISH;
7987
#ifndef EMBEDDED_LIBRARY 
7988
  unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET;
7989
#endif
unknown's avatar
unknown committed
7990 7991 7992
  mysql_home_ptr= mysql_home;
  log_error_file_ptr= log_error_file;
  protocol_version= PROTOCOL_VERSION;
7993
  what_to_log= ~(1UL << COM_TIME);
7994
  denied_connections= 0;
7995
  executed_events= 0;
7996
  global_query_id= 1;
7997
  global_thread_id= 0;
7998
  strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1);
unknown's avatar
unknown committed
7999
  thread_cache.empty();
8000
  key_caches.empty();
unknown's avatar
unknown committed
8001
  if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
8002
                                                default_key_cache_base.length)))
8003 8004 8005 8006
  {
    sql_print_error("Cannot allocate the keycache");
    return 1;
  }
8007

8008 8009
  /* set key_cache_hash.default_value = dflt_key_cache */
  multi_keycache_init();
unknown's avatar
unknown committed
8010 8011

  /* Set directory paths */
8012
  mysql_real_data_home_len=
8013 8014
    (uint)(strmake_buf(mysql_real_data_home,
                get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home);
unknown's avatar
unknown committed
8015 8016
  /* Replication parameters */
  master_info_file= (char*) "master.info",
unknown's avatar
unknown committed
8017
    relay_log_info_file= (char*) "relay-log.info";
unknown's avatar
unknown committed
8018 8019
  report_user= report_password = report_host= 0;	/* TO BE DELETED */
  opt_relay_logname= opt_relaylog_index_name= 0;
8020
  slave_retried_transactions= 0;
8021 8022 8023
  transactions_multi_engine= 0;
  rpl_transactions_multi_engine= 0;
  transactions_gtid_foreign_engine= 0;
8024 8025
  log_bin_basename= NULL;
  log_bin_index= NULL;
unknown's avatar
unknown committed
8026 8027 8028

  /* Variables in libraries */
  charsets_dir= 0;
8029
  default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
8030
  default_collation_name= compiled_default_collation_name;
unknown's avatar
unknown committed
8031
  character_set_filesystem_name= (char*) "binary";
8032
  lc_messages= (char*) "en_US";
8033
  lc_time_names_name= (char*) "en_US";
8034
  
unknown's avatar
unknown committed
8035 8036 8037 8038
  /* Variables that depends on compile options */
#ifndef DBUG_OFF
  default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
			     "d:t:i:o,/tmp/mysqld.trace");
8039
  current_dbug_option= default_dbug_option;
unknown's avatar
unknown committed
8040 8041
#endif
  opt_error_log= IF_WIN(1,0);
8042 8043
#ifdef ENABLED_PROFILING
    have_profiling = SHOW_OPTION_YES;
8044
#else
8045
    have_profiling = SHOW_OPTION_NO;
8046
#endif
8047

unknown's avatar
unknown committed
8048
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8049
  have_ssl=SHOW_OPTION_YES;
8050
#if defined(HAVE_YASSL)
8051
  have_openssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8052
#else
8053 8054 8055 8056
  have_openssl= SHOW_OPTION_YES;
#endif
#else
  have_openssl= have_ssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8057
#endif
unknown's avatar
unknown committed
8058
#ifdef HAVE_BROKEN_REALPATH
unknown's avatar
unknown committed
8059 8060 8061 8062
  have_symlink=SHOW_OPTION_NO;
#else
  have_symlink=SHOW_OPTION_YES;
#endif
8063 8064 8065 8066 8067
#ifdef HAVE_DLOPEN
  have_dlopen=SHOW_OPTION_YES;
#else
  have_dlopen=SHOW_OPTION_NO;
#endif
unknown's avatar
unknown committed
8068 8069 8070 8071 8072
#ifdef HAVE_QUERY_CACHE
  have_query_cache=SHOW_OPTION_YES;
#else
  have_query_cache=SHOW_OPTION_NO;
#endif
8073 8074 8075 8076 8077 8078 8079 8080 8081 8082
#ifdef HAVE_SPATIAL
  have_geometry=SHOW_OPTION_YES;
#else
  have_geometry=SHOW_OPTION_NO;
#endif
#ifdef HAVE_RTREE_KEYS
  have_rtree_keys=SHOW_OPTION_YES;
#else
  have_rtree_keys=SHOW_OPTION_NO;
#endif
unknown's avatar
unknown committed
8083 8084 8085 8086 8087 8088
#ifdef HAVE_CRYPT
  have_crypt=SHOW_OPTION_YES;
#else
  have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
8089
  have_compress= SHOW_OPTION_YES;
unknown's avatar
unknown committed
8090
#else
8091
  have_compress= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8092 8093 8094 8095 8096 8097
#endif
#ifdef HAVE_LIBWRAP
  libwrapName= NullS;
#endif
#ifdef HAVE_OPENSSL
  des_key_file = 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8098
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
8099
  ssl_acceptor_fd= 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8100 8101
#endif /* ! EMBEDDED_LIBRARY */
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
8102

8103 8104
#if defined(__WIN__)
  /* Allow Win32 users to move MySQL anywhere */
unknown's avatar
unknown committed
8105 8106
  {
    char prg_dev[LIBLEN];
8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117
    char executing_path_name[LIBLEN];
    if (!test_if_hard_path(my_progname))
    {
      // we don't want to use GetModuleFileName inside of my_path since
      // my_path is a generic path dereferencing function and here we care
      // only about the executing binary.
      GetModuleFileName(NULL, executing_path_name, sizeof(executing_path_name));
      my_path(prg_dev, executing_path_name, NULL);
    }
    else
      my_path(prg_dev, my_progname, "mysql/bin");
unknown's avatar
unknown committed
8118 8119 8120 8121 8122
    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
    cleanup_dirname(mysql_home,prg_dev);
  }
#else
  const char *tmpenv;
unknown's avatar
unknown committed
8123
  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
unknown's avatar
unknown committed
8124
    tmpenv = DEFAULT_MYSQL_HOME;
8125
  strmake_buf(mysql_home, tmpenv);
8126
  set_sys_var_value_origin(&mysql_home_ptr, sys_var::ENV);
8127
#endif
8128

Sergei Golubchik's avatar
Sergei Golubchik committed
8129
  if (wsrep_init_vars())
8130
    return 1;
8131

8132
  return 0;
unknown's avatar
unknown committed
8133 8134
}

8135
my_bool
8136
mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
unknown's avatar
unknown committed
8137
{
8138 8139 8140
  if (opt->app_type)
  {
    sys_var *var= (sys_var*) opt->app_type;
8141 8142 8143 8144 8145
    if (argument == autoset_my_option)
    {
      var->value_origin= sys_var::AUTO;
      return 0;
    }
8146 8147 8148
    var->value_origin= sys_var::CONFIG;
  }

8149 8150
  switch(optid) {
  case '#':
8151
#ifndef DBUG_OFF
8152 8153 8154
    if (!argument)
      argument= (char*) default_dbug_option;
    if (argument[0] == '0' && !argument[1])
unknown's avatar
unknown committed
8155 8156 8157 8158
    {
      DEBUGGER_OFF;
      break;
    }
8159
    DEBUGGER_ON;
8160
    if (argument[0] == '1' && !argument[1])
unknown's avatar
unknown committed
8161
      break;
8162
    DBUG_SET_INITIAL(argument);
8163
    current_dbug_option= argument;
8164
    opt_endinfo=1;				/* unireg: memory allocation */
8165 8166
#else
    sql_print_warning("'%s' is disabled in this build", opt->name);
8167
#endif
8168
    break;
8169
  case OPT_DEPRECATED_OPTION:
Sergei Golubchik's avatar
Sergei Golubchik committed
8170
    sql_print_warning("'%s' is deprecated. It does nothing and exists only "
Otto Kekäläinen's avatar
Otto Kekäläinen committed
8171
                      "for compatibility with old my.cnf files.",
8172 8173
                      opt->name);
    break;
8174
  case OPT_MYSQL_COMPATIBILITY:
Monty's avatar
Monty committed
8175 8176
    sql_print_warning("'%s' is MySQL 5.6 / 5.7 compatible option. Not used or "
                      "needed in MariaDB.", opt->name);
8177 8178
    break;
  case OPT_MYSQL_TO_BE_IMPLEMENTED:
Monty's avatar
Monty committed
8179 8180
    sql_print_warning("'%s' is MySQL 5.6 / 5.7 compatible option. To be "
                      "implemented in later versions.", opt->name);
8181
    break;
8182
  case 'a':
Sergei Golubchik's avatar
Sergei Golubchik committed
8183 8184
    SYSVAR_AUTOSIZE(global_system_variables.sql_mode, MODE_ANSI);
    SYSVAR_AUTOSIZE(global_system_variables.tx_isolation, ISO_SERIALIZABLE);
8185 8186
    break;
  case 'b':
8187
    strmake_buf(mysql_home, argument);
8188
    break;
8189
  case 'C':
8190 8191
    if (default_collation_name == compiled_default_collation_name)
      default_collation_name= 0;
8192
    break;
8193
  case 'h':
8194
    strmake_buf(mysql_real_data_home, argument);
8195
    /* Correct pointer set by my_getopt (for embedded library) */
8196
    mysql_real_data_home_ptr= mysql_real_data_home;
8197
    break;
8198
  case 'u':
8199
    if (!mysqld_user || !strcmp(mysqld_user, argument))
unknown's avatar
unknown committed
8200
      mysqld_user= argument;
8201
    else
8202
      sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
8203
    break;
8204
  case 'L':
8205
    strmake_buf(lc_messages_dir, argument);
8206
    break;
8207 8208
  case OPT_BINLOG_FORMAT:
    binlog_format_used= true;
8209
    break;
8210
#include <sslopt-case.h>
8211
  case 'V':
8212 8213 8214 8215
    if (argument)
    {
      strmake(server_version, argument, sizeof(server_version) - 1);
      set_sys_var_value_origin(&server_version_ptr, sys_var::CONFIG);
8216
      using_custom_server_version= true;
8217
    }
8218
#ifndef EMBEDDED_LIBRARY
8219 8220 8221 8222 8223
    else
    {
      print_version();
      opt_abort= 1;                    // Abort after parsing all options
    }
8224
#endif /*EMBEDDED_LIBRARY*/
8225
    break;
8226 8227 8228 8229 8230 8231 8232 8233
  case 'W':
    if (!argument)
      global_system_variables.log_warnings++;
    else if (argument == disabled_my_option)
      global_system_variables.log_warnings= 0L;
    else
      global_system_variables.log_warnings= atoi(argument);
    break;
8234 8235 8236 8237
  case 'T':
    test_flags= argument ? (uint) atoi(argument) : 0;
    opt_endinfo=1;
    break;
8238 8239 8240
  case OPT_THREAD_CONCURRENCY:
    WARN_DEPRECATED_NO_REPLACEMENT(NULL, "THREAD_CONCURRENCY");
    break;
8241 8242 8243 8244
  case (int) OPT_ISAM_LOG:
    opt_myisam_log=1;
    break;
  case (int) OPT_BIN_LOG:
8245
    opt_bin_log= MY_TEST(argument != disabled_my_option);
8246
    opt_bin_log_used= 1;
8247
    break;
8248 8249 8250
  case (int) OPT_LOG_BASENAME:
  {
    if (opt_log_basename[0] == 0 || strchr(opt_log_basename, FN_EXTCHAR) ||
8251 8252
        strchr(opt_log_basename,FN_LIBCHAR) ||
        !is_filename_allowed(opt_log_basename, strlen(opt_log_basename), FALSE))
8253
    {
8254
      sql_print_error("Wrong argument for --log-basename. It can't be empty or contain '.' or '" FN_DIRSEP "'. It must be valid filename.");
8255 8256
      return 1;
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
8257
    if (log_error_file_ptr != disabled_my_option)
Sergei Golubchik's avatar
Sergei Golubchik committed
8258
      SYSVAR_AUTOSIZE(log_error_file_ptr, opt_log_basename);
8259

8260
    /* General log file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8261
    make_default_log_name(&opt_logname, ".log", false);
8262
    /* Slow query log file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8263
    make_default_log_name(&opt_slow_logname, "-slow.log", false);
8264
    /* Binary log file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8265
    make_default_log_name(&opt_bin_logname, "-bin", true);
8266
    /* Binary log index file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8267
    make_default_log_name(&opt_binlog_index_name, "-bin.index", true);
8268 8269
    set_sys_var_value_origin(&opt_logname, sys_var::AUTO);
    set_sys_var_value_origin(&opt_slow_logname, sys_var::AUTO);
Sergei Golubchik's avatar
Sergei Golubchik committed
8270 8271 8272 8273 8274
    if (!opt_logname || !opt_slow_logname || !opt_bin_logname ||
        !opt_binlog_index_name)
      return 1;

#ifdef HAVE_REPLICATION
8275
    /* Relay log file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8276
    make_default_log_name(&opt_relay_logname, "-relay-bin", true);
8277
    /* Relay log index file */
Sergei Golubchik's avatar
Sergei Golubchik committed
8278
    make_default_log_name(&opt_relaylog_index_name, "-relay-bin.index", true);
8279
    set_sys_var_value_origin(&opt_relay_logname, sys_var::AUTO);
Sergei Golubchik's avatar
Sergei Golubchik committed
8280 8281 8282
    if (!opt_relay_logname || !opt_relaylog_index_name)
      return 1;
#endif
8283

Sergei Golubchik's avatar
Sergei Golubchik committed
8284
    SYSVAR_AUTOSIZE(pidfile_name_ptr, pidfile_name);
8285
    /* PID file */
8286 8287 8288 8289
    strmake(pidfile_name, argument, sizeof(pidfile_name)-5);
    strmov(fn_ext(pidfile_name),".pid");

    /* check for errors */
Sergei Golubchik's avatar
Sergei Golubchik committed
8290
    if (!pidfile_name_ptr)
8291 8292 8293
      return 1;                                 // out of memory error
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8294
#ifdef HAVE_REPLICATION
8295
  case (int)OPT_REPLICATE_IGNORE_DB:
8296
  {
8297
    cur_rpl_filter->add_ignore_db(argument);
8298 8299 8300 8301
    break;
  }
  case (int)OPT_REPLICATE_DO_DB:
  {
8302
    cur_rpl_filter->add_do_db(argument);
8303 8304 8305 8306
    break;
  }
  case (int)OPT_REPLICATE_REWRITE_DB:
  {
8307
    /* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */
8308
    char* key = argument,*p, *val;
8309

8310
    if (!(p= strstr(argument, "->")))
8311
    {
Monty's avatar
Monty committed
8312
      sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!");
8313
      return 1;
8314
    }
8315
    val= p--;
unknown's avatar
unknown committed
8316
    while (my_isspace(mysqld_charset, *p) && p > argument)
8317 8318
      *p-- = 0;
    if (p == argument)
8319
    {
Monty's avatar
Monty committed
8320
      sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!");
8321
      return 1;
8322
    }
8323 8324
    *val= 0;
    val+= 2;
unknown's avatar
unknown committed
8325
    while (*val && my_isspace(mysqld_charset, *val))
8326
      val++;
8327
    if (!*val)
8328
    {
Monty's avatar
Monty committed
8329
      sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!");
8330
      return 1;
8331 8332
    }

8333
    cur_rpl_filter->add_db_rewrite(key, val);
8334 8335
    break;
  }
8336 8337 8338
  case (int)OPT_SLAVE_PARALLEL_MODE:
  {
    /* Store latest mode for Master::Info */
8339 8340
    cur_rpl_filter->set_parallel_mode
      ((enum_slave_parallel_mode)opt_slave_parallel_mode);
8341 8342
    break;
  }
8343

8344
  case (int)OPT_BINLOG_IGNORE_DB:
8345
  {
8346
    binlog_filter->add_ignore_db(argument);
8347 8348
    break;
  }
8349
  case (int)OPT_BINLOG_DO_DB:
8350
  {
8351
    binlog_filter->add_do_db(argument);
8352 8353
    break;
  }
8354
  case (int)OPT_REPLICATE_DO_TABLE:
8355
  {
8356
    if (cur_rpl_filter->add_do_table(argument))
8357
    {
Monty's avatar
Monty committed
8358
      sql_print_error("Could not add do table rule '%s'!", argument);
8359
      return 1;
8360
    }
8361 8362
    break;
  }
8363
  case (int)OPT_REPLICATE_WILD_DO_TABLE:
8364
  {
8365
    if (cur_rpl_filter->add_wild_do_table(argument))
8366
    {
Monty's avatar
Monty committed
8367
      sql_print_error("Could not add do table rule '%s'!", argument);
8368
      return 1;
8369
    }
8370 8371
    break;
  }
8372
  case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
8373
  {
8374
    if (cur_rpl_filter->add_wild_ignore_table(argument))
8375
    {
Monty's avatar
Monty committed
8376
      sql_print_error("Could not add ignore table rule '%s'!", argument);
8377
      return 1;
8378
    }
8379 8380
    break;
  }
8381
  case (int)OPT_REPLICATE_IGNORE_TABLE:
8382
  {
8383
    if (cur_rpl_filter->add_ignore_table(argument))
8384
    {
Monty's avatar
Monty committed
8385
      sql_print_error("Could not add ignore table rule '%s'!", argument);
8386
      return 1;
8387
    }
8388 8389
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8390
#endif /* HAVE_REPLICATION */
8391
  case (int) OPT_SAFE:
8392
    opt_specialflag|= SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC;
Sergei Golubchik's avatar
Sergei Golubchik committed
8393 8394
    SYSVAR_AUTOSIZE(delay_key_write_options, (uint) DELAY_KEY_WRITE_NONE);
    SYSVAR_AUTOSIZE(myisam_recover_options, HA_RECOVER_DEFAULT);
8395
    ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
unknown's avatar
unknown committed
8396
#ifdef HAVE_QUERY_CACHE
Sergei Golubchik's avatar
Sergei Golubchik committed
8397
    SYSVAR_AUTOSIZE(query_cache_size, 0);
8398
#endif
8399 8400
    sql_print_warning("The syntax '--safe-mode' is deprecated and will be "
                      "removed in a future release.");
8401 8402 8403 8404 8405
    break;
  case (int) OPT_SKIP_HOST_CACHE:
    opt_specialflag|= SPECIAL_NO_HOST_CACHE;
    break;
  case (int) OPT_SKIP_RESOLVE:
8406
    opt_skip_name_resolve= 1;
8407 8408 8409 8410 8411
    opt_specialflag|=SPECIAL_NO_RESOLVE;
    break;
  case (int) OPT_WANT_CORE:
    test_flags |= TEST_CORE_ON_SIGNAL;
    break;
8412 8413 8414 8415
  case OPT_CONSOLE:
    if (opt_console)
      opt_error_log= 0;			// Force logs to stdout
    break;
8416 8417 8418 8419
  case OPT_BOOTSTRAP:
    opt_noacl=opt_bootstrap=1;
    break;
  case OPT_SERVER_ID:
8420
    ::server_id= global_system_variables.server_id;
8421
    break;
unknown's avatar
unknown committed
8422
  case OPT_LOWER_CASE_TABLE_NAMES:
8423
    lower_case_table_names_used= 1;
unknown's avatar
unknown committed
8424
    break;
8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440
#if defined(ENABLED_DEBUG_SYNC)
  case OPT_DEBUG_SYNC_TIMEOUT:
    /*
      Debug Sync Facility. See debug_sync.cc.
      Default timeout for WAIT_FOR action.
      Default value is zero (facility disabled).
      If option is given without an argument, supply a non-zero value.
    */
    if (!argument)
    {
      /* purecov: begin tested */
      opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
      /* purecov: end */
    }
    break;
#endif /* defined(ENABLED_DEBUG_SYNC) */
8441 8442 8443 8444 8445 8446 8447 8448
  case OPT_LOG_ERROR:
    /*
      "No --log-error" == "write errors to stderr",
      "--log-error without argument" == "write errors to a file".
    */
    if (argument == NULL) /* no argument */
      log_error_file_ptr= const_cast<char*>("");
    break;
8449
  case OPT_IGNORE_DB_DIRECTORY:
8450
    opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions
8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463
    if (*argument == 0)
      ignore_db_dirs_reset();
    else
    {
      if (push_ignored_db_dir(argument))
      {
        sql_print_error("Can't start server: "
                        "cannot process --ignore-db-dir=%.*s", 
                        FN_REFLEN, argument);
        return 1;
      }
    }
    break;
8464 8465 8466 8467 8468 8469
  case OPT_PLUGIN_LOAD:
    free_list(opt_plugin_load_list_ptr);
    /* fall through */
  case OPT_PLUGIN_LOAD_ADD:
    opt_plugin_load_list_ptr->push_back(new i_string(argument));
    break;
8470 8471 8472
  case OPT_MAX_LONG_DATA_SIZE:
    max_long_data_size_used= true;
    break;
8473
  case OPT_PFS_INSTRUMENT:
8474
  {
8475
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
8476
#ifndef EMBEDDED_LIBRARY
8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539
    /* Parse instrument name and value from argument string */
    char* name = argument,*p, *val;

    /* Assignment required */
    if (!(p= strchr(argument, '=')))
    {
       my_getopt_error_reporter(WARNING_LEVEL,
                             "Missing value for performance_schema_instrument "
                             "'%s'", argument);
      return 0;
    }

    /* Option value */
    val= p + 1;
    if (!*val)
    {
       my_getopt_error_reporter(WARNING_LEVEL,
                             "Missing value for performance_schema_instrument "
                             "'%s'", argument);
      return 0;
    }

    /* Trim leading spaces from instrument name */
    while (*name && my_isspace(mysqld_charset, *name))
      name++;

    /* Trim trailing spaces and slashes from instrument name */
    while (p > argument && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '/'))
      p--;
    *p= 0;

    if (!*name)
    {
       my_getopt_error_reporter(WARNING_LEVEL,
                             "Invalid instrument name for "
                             "performance_schema_instrument '%s'", argument);
      return 0;
    }

    /* Trim leading spaces from option value */
    while (*val && my_isspace(mysqld_charset, *val))
      val++;

    /* Trim trailing spaces from option value */
    if ((p= my_strchr(mysqld_charset, val, val+strlen(val), ' ')) != NULL)
      *p= 0;

    if (!*val)
    {
       my_getopt_error_reporter(WARNING_LEVEL,
                             "Invalid value for performance_schema_instrument "
                             "'%s'", argument);
      return 0;
    }

    /* Add instrument name and value to array of configuration options */
    if (add_pfs_instr_to_array(name, val))
    {
       my_getopt_error_reporter(WARNING_LEVEL,
                             "Invalid value for performance_schema_instrument "
                             "'%s'", argument);
      return 0;
    }
8540
#endif /* EMBEDDED_LIBRARY */
8541 8542
#endif
    break;
unknown's avatar
unknown committed
8543
  }
8544 8545
#ifdef WITH_WSREP
  case OPT_WSREP_CAUSAL_READS:
8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566
  {
    if (global_system_variables.wsrep_causal_reads)
    {
      WSREP_WARN("option --wsrep-causal-reads is deprecated");
      if (!(global_system_variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ))
      {
        WSREP_WARN("--wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=%u. "
                     "WSREP_SYNC_WAIT_BEFORE_READ is on",
                     global_system_variables.wsrep_sync_wait);
        global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
      }
    }
    else
    {
      if (global_system_variables.wsrep_sync_wait & WSREP_SYNC_WAIT_BEFORE_READ) {
          WSREP_WARN("--wsrep-sync-wait=%u takes precedence over --wsrep-causal-reads=OFF. "
                     "WSREP_SYNC_WAIT_BEFORE_READ is on",
                     global_system_variables.wsrep_sync_wait);
          global_system_variables.wsrep_causal_reads = 1;
      }
    }
8567
    break;
8568
  }
8569 8570 8571 8572 8573 8574
  case OPT_WSREP_SYNC_WAIT:
    global_system_variables.wsrep_causal_reads=
      MY_TEST(global_system_variables.wsrep_sync_wait &
              WSREP_SYNC_WAIT_BEFORE_READ);
    break;
#endif /* WITH_WSREP */
8575
  }
8576 8577
  return 0;
}
8578

8579

unknown's avatar
unknown committed
8580
/** Handle arguments for multiple key caches. */
8581

8582
C_MODE_START
8583

8584
static void*
8585
mysql_getopt_value(const char *name, uint length,
8586
		   const struct my_option *option, int *error)
8587
{
8588 8589
  if (error)
    *error= 0;
8590 8591
  switch (option->id) {
  case OPT_KEY_BUFFER_SIZE:
unknown's avatar
unknown committed
8592
  case OPT_KEY_CACHE_BLOCK_SIZE:
8593 8594
  case OPT_KEY_CACHE_DIVISION_LIMIT:
  case OPT_KEY_CACHE_AGE_THRESHOLD:
8595
  case OPT_KEY_CACHE_PARTITIONS:
8596
  case OPT_KEY_CACHE_CHANGED_BLOCKS_HASH_SIZE:
8597
  {
unknown's avatar
unknown committed
8598
    KEY_CACHE *key_cache;
8599
    if (unlikely(!(key_cache= get_or_create_key_cache(name, length))))
8600 8601 8602 8603 8604
    {
      if (error)
        *error= EXIT_OUT_OF_MEMORY;
      return 0;
    }
8605 8606
    switch (option->id) {
    case OPT_KEY_BUFFER_SIZE:
8607
      return &key_cache->param_buff_size;
8608
    case OPT_KEY_CACHE_BLOCK_SIZE:
8609
      return &key_cache->param_block_size;
8610
    case OPT_KEY_CACHE_DIVISION_LIMIT:
8611
      return &key_cache->param_division_limit;
8612
    case OPT_KEY_CACHE_AGE_THRESHOLD:
8613
      return &key_cache->param_age_threshold;
8614 8615
    case OPT_KEY_CACHE_PARTITIONS:
      return (uchar**) &key_cache->param_partitions;
8616 8617
    case OPT_KEY_CACHE_CHANGED_BLOCKS_HASH_SIZE:
      return (uchar**) &key_cache->changed_blocks_hash_size;
8618
    }
8619
  }
8620 8621
  /* We return in all cases above. Let us silence -Wimplicit-fallthrough */
  DBUG_ASSERT(0);
8622
#ifdef HAVE_REPLICATION
8623
  /* fall through */
8624 8625 8626 8627 8628 8629 8630
  case OPT_REPLICATE_DO_DB:
  case OPT_REPLICATE_DO_TABLE:
  case OPT_REPLICATE_IGNORE_DB:
  case OPT_REPLICATE_IGNORE_TABLE:
  case OPT_REPLICATE_WILD_DO_TABLE:
  case OPT_REPLICATE_WILD_IGNORE_TABLE:
  case OPT_REPLICATE_REWRITE_DB:
8631
  case OPT_SLAVE_PARALLEL_MODE:
8632 8633 8634 8635 8636 8637 8638
  {
    /* Store current filter for mysqld_get_one_option() */
    if (!(cur_rpl_filter= get_or_create_rpl_filter(name, length)))
    {
      if (error)
        *error= EXIT_OUT_OF_MEMORY;
    }
8639
    if (option->id == OPT_SLAVE_PARALLEL_MODE)
8640
    {
8641 8642 8643 8644 8645
      /*
        Ensure parallel_mode variable is shown in --help. The other
        variables are not easily printable here.
       */
      return (char**) &opt_slave_parallel_mode;
8646
    }
8647
    return 0;
8648 8649
  }
#endif
8650
  }
8651
  return option->value;
8652 8653
}

8654
static void option_error_reporter(enum loglevel level, const char *format, ...)
unknown's avatar
unknown committed
8655
{
8656
  va_list args;
unknown's avatar
unknown committed
8657
  va_start(args, format);
8658 8659 8660 8661 8662 8663 8664

  /* Don't print warnings for --loose options during bootstrap */
  if (level == ERROR_LEVEL || !opt_bootstrap ||
      global_system_variables.log_warnings)
  {
    vprint_msg_to_log(level, format, args);
  }
unknown's avatar
unknown committed
8665
  va_end(args);
unknown's avatar
unknown committed
8666
}
8667

8668
C_MODE_END
unknown's avatar
unknown committed
8669

unknown's avatar
unknown committed
8670
/**
Marc Alff's avatar
Marc Alff committed
8671 8672 8673 8674 8675 8676
  Get server options from the command line,
  and perform related server initializations.
  @param [in, out] argc_ptr       command line options (count)
  @param [in, out] argv_ptr       command line options (values)
  @return 0 on success

unknown's avatar
unknown committed
8677 8678 8679
  @todo
  - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
*/
Marc Alff's avatar
Marc Alff committed
8680
static int get_options(int *argc_ptr, char ***argv_ptr)
8681 8682 8683
{
  int ho_error;

8684
  my_getopt_register_get_addr(mysql_getopt_value);
8685
  my_getopt_error_reporter= option_error_reporter;
unknown's avatar
unknown committed
8686

Marc Alff's avatar
Marc Alff committed
8687 8688
  /* prepare all_options array */
  my_init_dynamic_array(&all_options, sizeof(my_option),
Monty's avatar
Monty committed
8689 8690
                        array_elements(my_long_options) +
                        sys_var_elements(),
8691
                        array_elements(my_long_options)/4, MYF(0));
8692
  add_many_options(&all_options, my_long_options, array_elements(my_long_options));
8693
  sys_var_add_options(&all_options, 0);
Marc Alff's avatar
Marc Alff committed
8694
  add_terminator(&all_options);
8695

unknown's avatar
unknown committed
8696 8697 8698
  /* Skip unknown options so that they may be processed later by plugins */
  my_getopt_skip_unknown= TRUE;

Marc Alff's avatar
Marc Alff committed
8699
  if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer),
8700
                                mysqld_get_one_option)))
8701
    return ho_error;
8702 8703 8704

  if (!opt_help)
    delete_dynamic(&all_options);
8705 8706
  else
    opt_abort= 1;
8707

Marc Alff's avatar
Marc Alff committed
8708 8709 8710
  /* Add back the program name handle_options removes */
  (*argc_ptr)++;
  (*argv_ptr)--;
8711

8712 8713
  disable_log_notes= opt_silent_startup;

8714 8715 8716 8717 8718 8719
  /*
    Options have been parsed. Now some of them need additional special
    handling, like custom value checking, checking of incompatibilites
    between options, setting of multiple variables, etc.
    Do them here.
  */
8720 8721 8722 8723 8724 8725 8726 8727
  if (global_system_variables.net_buffer_length > 
      global_system_variables.max_allowed_packet)
  {
    sql_print_warning("net_buffer_length (%lu) is set to be larger "
                      "than max_allowed_packet (%lu). Please rectify.",
                      global_system_variables.net_buffer_length, 
                      global_system_variables.max_allowed_packet);
  }
8728

8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741
  if (log_error_file_ptr != disabled_my_option)
    opt_error_log= 1;
  else
    log_error_file_ptr= const_cast<char*>("");

  opt_init_connect.length=strlen(opt_init_connect.str);
  opt_init_slave.length=strlen(opt_init_slave.str);

  if (global_system_variables.low_priority_updates)
    thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;

  if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax))
  {
Monty's avatar
Monty committed
8742
    sql_print_error("Invalid ft-boolean-syntax string: %s",
8743 8744 8745 8746 8747
                    ft_boolean_syntax);
    return 1;
  }

  if (opt_disable_networking)
Sergei Golubchik's avatar
Sergei Golubchik committed
8748
    mysqld_port= mysqld_extra_port= 0;
8749

8750 8751 8752 8753 8754 8755 8756
  if (opt_skip_show_db)
    opt_specialflag|= SPECIAL_SKIP_SHOW_DB;

  if (myisam_flush)
    flush_time= 0;

#ifdef HAVE_REPLICATION
8757 8758 8759 8760
  if (init_slave_skip_errors(opt_slave_skip_errors))
    return 1;
  if (init_slave_transaction_retry_errors(opt_slave_transaction_retry_errors))
    return 1;
8761 8762 8763 8764 8765 8766 8767
#endif

  if (global_system_variables.max_join_size == HA_POS_ERROR)
    global_system_variables.option_bits|= OPTION_BIG_SELECTS;
  else
    global_system_variables.option_bits&= ~OPTION_BIG_SELECTS;

Monty's avatar
Monty committed
8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779
  if (opt_support_flashback)
  {
    /* Force binary logging */
    if (!opt_bin_logname)
      opt_bin_logname= (char*) "";                  // Use default name
    opt_bin_log= opt_bin_log_used= 1;

    /* Force format to row */
    binlog_format_used= 1;
    global_system_variables.binlog_format= BINLOG_FORMAT_ROW;
  }

8780
  if (!opt_bootstrap && WSREP_PROVIDER_EXISTS &&
8781 8782
      global_system_variables.binlog_format != BINLOG_FORMAT_ROW)
  {
8783 8784 8785 8786 8787 8788 8789

    WSREP_ERROR ("Only binlog_format = 'ROW' is currently supported. "
                 "Configured value: '%s'. Please adjust your configuration.",
                 binlog_format_names[global_system_variables.binlog_format]);
    return 1;
  }

8790 8791 8792 8793 8794 8795
  // Synchronize @@global.autocommit on --autocommit
  const ulonglong turn_bit_on= opt_autocommit ?
    OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
  global_system_variables.option_bits=
    (global_system_variables.option_bits &
     ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) | turn_bit_on;
8796 8797 8798

  global_system_variables.sql_mode=
    expand_sql_mode(global_system_variables.sql_mode);
Sergei Golubchik's avatar
Sergei Golubchik committed
8799
#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH)
8800 8801 8802 8803 8804 8805 8806 8807 8808 8809
  my_use_symdir=0;
  my_disable_symlinks=1;
  have_symlink=SHOW_OPTION_NO;
#else
  if (!my_use_symdir)
  {
    my_disable_symlinks=1;
    have_symlink=SHOW_OPTION_DISABLED;
  }
#endif
8810 8811 8812
  if (opt_debugging)
  {
    /* Allow break with SIGINT, no core or stack trace */
Michael Widenius's avatar
Michael Widenius committed
8813 8814
    test_flags|= TEST_SIGINT;
    opt_stack_trace= 1;
8815 8816
    test_flags&= ~TEST_CORE_ON_SIGNAL;
  }
8817
  /* Set global MyISAM variables from delay_key_write_options */
8818
  fix_delay_key_write(0, 0, OPT_GLOBAL);
8819

8820
#ifndef EMBEDDED_LIBRARY
8821 8822
  if (mysqld_chroot)
    set_root(mysqld_chroot);
8823
#else
Sergei Golubchik's avatar
Sergei Golubchik committed
8824
  SYSVAR_AUTOSIZE(thread_handling, SCHEDULER_NO_THREADS);
8825 8826
  max_allowed_packet= global_system_variables.max_allowed_packet;
  net_buffer_length= global_system_variables.net_buffer_length;
8827
#endif
8828 8829
  if (fix_paths())
    return 1;
unknown's avatar
unknown committed
8830

unknown's avatar
unknown committed
8831 8832 8833 8834
  /*
    Set some global variables from the global_system_variables
    In most cases the global variables will not be used
  */
8835
  my_disable_locking= myisam_single_user= MY_TEST(opt_external_locking == 0);
unknown's avatar
unknown committed
8836
  my_default_record_cache_size=global_system_variables.read_buff_size;
unknown's avatar
unknown committed
8837

8838
  /*
8839 8840 8841
    Log mysys errors when we don't have a thd or thd->log_all_errors is set
    (recovery) to the log.  This is mainly useful for debugging strange system
    errors.
8842 8843
  */
  if (global_system_variables.log_warnings >= 10)
8844
    my_global_flags= MY_WME | ME_NOTE;
8845 8846
  /* Log all errors not handled by thd->handle_error() to my_message_sql() */
  if (global_system_variables.log_warnings >= 11)
8847
    my_global_flags|= ME_ERROR_LOG;
8848 8849
  if (my_assert_on_error)
    debug_assert_if_crashed_table= 1;
8850

8851
  global_system_variables.long_query_time= (ulonglong)
Monty's avatar
Monty committed
8852 8853 8854
    (global_system_variables.long_query_time_double * 1e6 + 0.1);
  global_system_variables.max_statement_time= (ulonglong)
    (global_system_variables.max_statement_time_double * 1e6 + 0.1);
8855

8856 8857
  if (opt_short_log_format)
    opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
8858

8859
  if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
8860
                                  &global_date_format) ||
8861
      init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
8862
                                  &global_time_format) ||
8863
      init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
8864
                                  &global_datetime_format))
8865
    return 1;
8866

unknown's avatar
unknown committed
8867
#ifdef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
8868 8869
  one_thread_scheduler(thread_scheduler);
  one_thread_scheduler(extra_thread_scheduler);
unknown's avatar
unknown committed
8870
#else
8871

8872
  if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
Sergei Golubchik's avatar
Sergei Golubchik committed
8873
    one_thread_per_connection_scheduler(thread_scheduler, &max_connections,
8874
                                        &connection_count);
8875
  else if (thread_handling == SCHEDULER_NO_THREADS)
Sergei Golubchik's avatar
Sergei Golubchik committed
8876
    one_thread_scheduler(thread_scheduler);
unknown's avatar
unknown committed
8877
  else
8878 8879 8880
    pool_of_threads_scheduler(thread_scheduler,  &max_connections,
                                        &connection_count); 

Sergei Golubchik's avatar
Sergei Golubchik committed
8881
  one_thread_per_connection_scheduler(extra_thread_scheduler,
8882 8883
                                      &extra_max_connections,
                                      &extra_connection_count);
unknown's avatar
unknown committed
8884
#endif
8885

8886 8887
  opt_readonly= read_only;

8888 8889 8890 8891 8892
  /*
    If max_long_data_size is not specified explicitly use
    value of max_allowed_packet.
  */
  if (!max_long_data_size_used)
Sergei Golubchik's avatar
Sergei Golubchik committed
8893 8894
    SYSVAR_AUTOSIZE(max_long_data_size,
                    global_system_variables.max_allowed_packet);
8895

8896
  /* Remember if max_user_connections was 0 at startup */
Sergei Golubchik's avatar
Sergei Golubchik committed
8897
  max_user_connections_checking= global_system_variables.max_user_connections != 0;
8898

Sergei Golubchik's avatar
Sergei Golubchik committed
8899
#ifdef HAVE_REPLICATION
8900 8901 8902 8903
  {
    sys_var *max_relay_log_size_var, *max_binlog_size_var;
    /* If max_relay_log_size is 0, then set it to max_binlog_size */
    if (!global_system_variables.max_relay_log_size)
Sergei Golubchik's avatar
Sergei Golubchik committed
8904 8905
      SYSVAR_AUTOSIZE(global_system_variables.max_relay_log_size,
                      max_binlog_size);
8906 8907 8908 8909 8910 8911

    /*
      Fix so that DEFAULT and limit checking works with max_relay_log_size
      (Yes, this is a hack, but it's required as the definition of
      max_relay_log_size allows it to be set to 0).
    */
Sergei Golubchik's avatar
Sergei Golubchik committed
8912 8913
    max_relay_log_size_var= intern_find_sys_var(STRING_WITH_LEN("max_relay_log_size"));
    max_binlog_size_var= intern_find_sys_var(STRING_WITH_LEN("max_binlog_size"));
Sergei Golubchik's avatar
Sergei Golubchik committed
8914 8915 8916 8917 8918 8919 8920
    if (max_binlog_size_var && max_relay_log_size_var)
    {
      max_relay_log_size_var->option.min_value=
        max_binlog_size_var->option.min_value; 
      max_relay_log_size_var->option.def_value=
        max_binlog_size_var->option.def_value;
    }
8921
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
8922
#endif
8923 8924 8925

  /* Ensure that some variables are not set higher than needed */
  if (thread_cache_size > max_connections)
Sergei Golubchik's avatar
Sergei Golubchik committed
8926
    SYSVAR_AUTOSIZE(thread_cache_size, max_connections);
8927

8928
  return 0;
unknown's avatar
unknown committed
8929 8930 8931
}


8932 8933 8934 8935 8936 8937 8938
/*
  Create version name for running mysqld version
  We automaticly add suffixes -debug, -embedded and -log to the version
  name to make the version more descriptive.
  (MYSQL_SERVER_SUFFIX is set by the compilation environment)
*/

8939
void set_server_version(char *buf, size_t size)
8940
{
8941 8942 8943 8944 8945 8946 8947 8948 8949
  bool is_log= opt_log || global_system_variables.sql_log_slow || opt_bin_log;
  bool is_debug= IF_DBUG(!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"), 0);
  strxnmov(buf, size - 1,
           MYSQL_SERVER_VERSION,
           MYSQL_SERVER_SUFFIX_STR,
           IF_EMBEDDED("-embedded", ""),
           is_debug ? "-debug" : "",
           is_log ? "-log" : "",
           NullS);
8950 8951 8952
}


unknown's avatar
unknown committed
8953 8954 8955
static char *get_relative_path(const char *path)
{
  if (test_if_hard_path(path) &&
8956
      is_prefix(path,DEFAULT_MYSQL_HOME) &&
unknown's avatar
unknown committed
8957 8958
      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
  {
unknown's avatar
unknown committed
8959
    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
8960
    while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
unknown's avatar
unknown committed
8961 8962 8963 8964 8965 8966
      path++;
  }
  return (char*) path;
}


unknown's avatar
unknown committed
8967
/**
8968 8969
  Fix filename and replace extension where 'dir' is relative to
  mysql_real_data_home.
unknown's avatar
unknown committed
8970 8971
  @return
    1 if len(path) > FN_REFLEN
8972 8973 8974
*/

bool
8975
fn_format_relative_to_data_home(char * to, const char *name,
8976 8977 8978 8979 8980 8981 8982 8983 8984 8985
				const char *dir, const char *extension)
{
  char tmp_path[FN_REFLEN];
  if (!test_if_hard_path(dir))
  {
    strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
	     dir, NullS);
    dir=tmp_path;
  }
  return !fn_format(to, name, dir, extension,
8986
		    MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
8987 8988 8989
}


8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003
/**
  Test a file path to determine if the path is compatible with the secure file
  path restriction.
 
  @param path null terminated character string

  @return
    @retval TRUE The path is secure
    @retval FALSE The path isn't secure
*/

bool is_secure_file_path(char *path)
{
  char buff1[FN_REFLEN], buff2[FN_REFLEN];
9004
  size_t opt_secure_file_priv_len;
9005 9006 9007 9008 9009 9010
  /*
    All paths are secure if opt_secure_file_path is 0
  */
  if (!opt_secure_file_priv)
    return TRUE;

9011 9012
  opt_secure_file_priv_len= strlen(opt_secure_file_priv);

Georgi Kodinov's avatar
Georgi Kodinov committed
9013 9014 9015
  if (strlen(path) >= FN_REFLEN)
    return FALSE;

9016 9017 9018 9019 9020
  if (my_realpath(buff1, path, 0))
  {
    /*
      The supplied file path might have been a file and not a directory.
    */
Michael Widenius's avatar
Michael Widenius committed
9021
    size_t length= dirname_length(path);        // Guaranteed to be < FN_REFLEN
9022 9023 9024 9025 9026 9027
    memcpy(buff2, path, length);
    buff2[length]= '\0';
    if (length == 0 || my_realpath(buff1, buff2, 0))
      return FALSE;
  }
  convert_dirname(buff2, buff1, NullS);
9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041
  if (!lower_case_file_system)
  {
    if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
      return FALSE;
  }
  else
  {
    if (files_charset_info->coll->strnncoll(files_charset_info,
                                            (uchar *) buff2, strlen(buff2),
                                            (uchar *) opt_secure_file_priv,
                                            opt_secure_file_priv_len,
                                            TRUE))
      return FALSE;
  }
9042 9043 9044
  return TRUE;
}

Michael Widenius's avatar
Michael Widenius committed
9045

9046
static int fix_paths(void)
unknown's avatar
unknown committed
9047
{
9048
  char buff[FN_REFLEN],*pos;
9049 9050
  DBUG_ENTER("fix_paths");

9051
  convert_dirname(mysql_home,mysql_home,NullS);
9052
  /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
9053
  my_realpath(mysql_home,mysql_home,MYF(0));
9054 9055 9056 9057 9058 9059 9060
  /* Ensure that mysql_home ends in FN_LIBCHAR */
  pos=strend(mysql_home);
  if (pos[-1] != FN_LIBCHAR)
  {
    pos[0]= FN_LIBCHAR;
    pos[1]= 0;
  }
9061
  convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
9062
  convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
unknown's avatar
unknown committed
9063 9064
  (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
  (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
9065
  (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
Marc Alff's avatar
Marc Alff committed
9066

Sergei Golubchik's avatar
Sergei Golubchik committed
9067 9068 9069
  convert_dirname(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : 
                                  get_relative_path(PLUGINDIR), NullS);
  (void) my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
9070
  opt_plugin_dir_ptr= opt_plugin_dir;
Sergei Golubchik's avatar
Sergei Golubchik committed
9071
  pidfile_name_ptr= pidfile_name;
unknown's avatar
unknown committed
9072

9073 9074
  my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
  mysql_unpacked_real_data_home_len= 
9075
  strlen(mysql_unpacked_real_data_home);
9076 9077 9078
  if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
    --mysql_unpacked_real_data_home_len;

unknown's avatar
unknown committed
9079
  char *sharedir=get_relative_path(SHAREDIR);
unknown's avatar
unknown committed
9080
  if (test_if_hard_path(sharedir))
9081
    strmake_buf(buff, sharedir);		/* purecov: tested */
unknown's avatar
unknown committed
9082
  else
unknown's avatar
unknown committed
9083
    strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
9084
  convert_dirname(buff,buff,NullS);
9085
  (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
unknown's avatar
unknown committed
9086 9087

  /* If --character-sets-dir isn't given, use shared library dir */
9088
  if (charsets_dir)
Sergei Golubchik's avatar
Sergei Golubchik committed
9089
  {
9090
    strmake_buf(mysql_charsets_dir, charsets_dir);
Sergei Golubchik's avatar
Sergei Golubchik committed
9091 9092
    charsets_dir= mysql_charsets_dir;
  }
9093
  else
Sergei Golubchik's avatar
Sergei Golubchik committed
9094
  {
unknown's avatar
unknown committed
9095 9096
    strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
	     CHARSET_DIR, NullS);
Sergei Golubchik's avatar
Sergei Golubchik committed
9097 9098
    SYSVAR_AUTOSIZE(charsets_dir, mysql_charsets_dir);
  }
unknown's avatar
unknown committed
9099
  (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
9100
  convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
unknown's avatar
unknown committed
9101

unknown's avatar
unknown committed
9102
  if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
9103
    DBUG_RETURN(1);
9104 9105
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir= mysql_tmpdir;
unknown's avatar
SCRUM  
unknown committed
9106
#ifdef HAVE_REPLICATION
9107
  if (!slave_load_tmpdir)
Sergei Golubchik's avatar
Sergei Golubchik committed
9108
    SYSVAR_AUTOSIZE(slave_load_tmpdir, mysql_tmpdir);
9109
#endif /* HAVE_REPLICATION */
9110 9111 9112
  /*
    Convert the secure-file-priv option to system format, allowing
    a quick strcmp to check if read or write is in an allowed dir
Michael Widenius's avatar
Michael Widenius committed
9113
  */
9114 9115
  if (opt_secure_file_priv)
  {
9116 9117
    if (*opt_secure_file_priv == 0)
    {
9118
      my_free(opt_secure_file_priv);
9119 9120 9121 9122
      opt_secure_file_priv= 0;
    }
    else
    {
9123 9124
      if (strlen(opt_secure_file_priv) >= FN_REFLEN)
        opt_secure_file_priv[FN_REFLEN-1]= '\0';
9125
      if (my_realpath(buff, opt_secure_file_priv, 0))
9126 9127
      {
        sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
9128
        DBUG_RETURN(1);
9129
      }
9130
      char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
9131
      convert_dirname(secure_file_real_path, buff, NullS);
9132
      my_free(opt_secure_file_priv);
9133 9134
      opt_secure_file_priv= secure_file_real_path;
    }
9135
  }
9136
  DBUG_RETURN(0);
unknown's avatar
unknown committed
9137 9138
}

unknown's avatar
unknown committed
9139 9140
/**
  Check if file system used for databases is case insensitive.
9141

unknown's avatar
unknown committed
9142
  @param dir_name			Directory to test
9143

9144 9145 9146
  @retval -1  Don't know (Test failed)
  @retval  0   File system is case sensitive
  @retval  1   File system is case insensitive
9147 9148 9149 9150 9151 9152 9153 9154
*/

static int test_if_case_insensitive(const char *dir_name)
{
  int result= 0;
  File file;
  char buff[FN_REFLEN], buff2[FN_REFLEN];
  MY_STAT stat_info;
9155
  DBUG_ENTER("test_if_case_insensitive");
9156

9157
  fn_format(buff, opt_log_basename, dir_name, ".lower-test",
9158
	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
9159
  fn_format(buff2, opt_log_basename, dir_name, ".LOWER-TEST",
9160
	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
Marc Alff's avatar
Marc Alff committed
9161 9162 9163
  mysql_file_delete(key_file_casetest, buff2, MYF(0));
  if ((file= mysql_file_create(key_file_casetest,
                               buff, 0666, O_RDWR, MYF(0))) < 0)
9164
  {
9165
    if (!opt_abort)
9166
      sql_print_warning("Can't create test file %s", buff);
9167
    DBUG_RETURN(-1);
9168
  }
Marc Alff's avatar
Marc Alff committed
9169 9170
  mysql_file_close(file, MYF(0));
  if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
9171
    result= 1;					// Can access file
Marc Alff's avatar
Marc Alff committed
9172
  mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
9173 9174
  DBUG_PRINT("exit", ("result: %d", result));
  DBUG_RETURN(result);
9175 9176 9177
}


9178 9179
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
9180 9181 9182
/**
  Create file to store pid number.
*/
9183 9184 9185
static void create_pid_file()
{
  File file;
Marc Alff's avatar
Marc Alff committed
9186 9187
  if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
                               O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
9188
  {
9189
    char buff[MAX_BIGINT_WIDTH + 1], *end;
9190
    end= int10_to_str((long) getpid(), buff, 10);
unknown's avatar
unknown committed
9191
    *end++= '\n';
Marc Alff's avatar
Marc Alff committed
9192 9193
    if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
                          MYF(MY_WME | MY_NABP)))
9194
    {
Marc Alff's avatar
Marc Alff committed
9195
      mysql_file_close(file, MYF(0));
9196
      pid_file_created= true;
9197 9198
      return;
    }
Marc Alff's avatar
Marc Alff committed
9199
    mysql_file_close(file, MYF(0));
9200
  }
9201
  sql_perror("Can't start server: can't create PID file");
unknown's avatar
foo1  
unknown committed
9202
  exit(1);
9203
}
9204
#endif /* EMBEDDED_LIBRARY */
9205

Marc Alff's avatar
Marc Alff committed
9206

9207 9208 9209 9210 9211
/**
  Remove the process' pid file.
  
  @param  flags  file operation flags
*/
Marc Alff's avatar
Marc Alff committed
9212

9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223
static void delete_pid_file(myf flags)
{
#ifndef EMBEDDED_LIBRARY
  if (pid_file_created)
  {
    mysql_file_delete(key_file_pid, pidfile_name, flags);
    pid_file_created= false;
  }
#endif /* EMBEDDED_LIBRARY */
  return;
}
Marc Alff's avatar
Marc Alff committed
9224 9225


unknown's avatar
unknown committed
9226
/** Clear most status variables. */
9227 9228
void refresh_status(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
9229
  mysql_mutex_lock(&LOCK_status);
9230

9231
  /* Add thread's status variabes to global status */
9232
  add_to_status(&global_status_var, &thd->status_var);
9233 9234

  /* Reset thread's status variables */
9235
  thd->set_status_var_init();
9236
  thd->status_var.global_memory_used= 0;
9237 9238
  bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); 
  thd->start_bytes_received= 0;
9239

9240
  /* Reset some global variables */
unknown's avatar
unknown committed
9241
  reset_status_vars();
9242 9243
#ifdef WITH_WSREP
  if (WSREP_ON)
Brave Galera Crew's avatar
Brave Galera Crew committed
9244 9245 9246
  {
    Wsrep_server_state::instance().provider().reset_status();
  }
9247
#endif /* WITH_WSREP */
9248

9249
  /* Reset the counters of all key caches (default and named). */
9250
  process_key_caches(reset_key_cache_counters, 0);
9251
  flush_status_time= time((time_t*) 0);
Marc Alff's avatar
Marc Alff committed
9252
  mysql_mutex_unlock(&LOCK_status);
9253 9254 9255

  /*
    Set max_used_connections to the number of currently open
Michael Widenius's avatar
Michael Widenius committed
9256
    connections.  This is not perfect, but status data is not exact anyway.
9257
  */
9258
  max_used_connections= connection_count + extra_connection_count;
9259 9260
}

Sergei Golubchik's avatar
Sergei Golubchik committed
9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293
#ifdef HAVE_PSI_INTERFACE
static PSI_file_info all_server_files[]=
{
#ifdef HAVE_MMAP
  { &key_file_map, "map", 0},
#endif /* HAVE_MMAP */
  { &key_file_binlog, "binlog", 0},
  { &key_file_binlog_index, "binlog_index", 0},
  { &key_file_relaylog, "relaylog", 0},
  { &key_file_relaylog_index, "relaylog_index", 0},
  { &key_file_casetest, "casetest", 0},
  { &key_file_dbopt, "dbopt", 0},
  { &key_file_des_key_file, "des_key_file", 0},
  { &key_file_ERRMSG, "ERRMSG", 0},
  { &key_select_to_file, "select_to_file", 0},
  { &key_file_fileparser, "file_parser", 0},
  { &key_file_frm, "FRM", 0},
  { &key_file_global_ddl_log, "global_ddl_log", 0},
  { &key_file_load, "load", 0},
  { &key_file_loadfile, "LOAD_FILE", 0},
  { &key_file_log_event_data, "log_event_data", 0},
  { &key_file_log_event_info, "log_event_info", 0},
  { &key_file_master_info, "master_info", 0},
  { &key_file_misc, "misc", 0},
  { &key_file_partition, "partition", 0},
  { &key_file_pid, "pid", 0},
  { &key_file_query_log, "query_log", 0},
  { &key_file_relay_log_info, "relay_log_info", 0},
  { &key_file_send_file, "send_file", 0},
  { &key_file_slow_log, "slow_log", 0},
  { &key_file_tclog, "tclog", 0},
  { &key_file_trg, "trigger_name", 0},
  { &key_file_trn, "trigger", 0},
unknown's avatar
unknown committed
9294 9295
  { &key_file_init, "init", 0},
  { &key_file_binlog_state, "binlog_state", 0}
Sergei Golubchik's avatar
Sergei Golubchik committed
9296 9297 9298
};
#endif /* HAVE_PSI_INTERFACE */

9299
PSI_stage_info stage_after_apply_event= { 0, "After apply log event", 0};
9300
PSI_stage_info stage_after_create= { 0, "After create", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9301 9302
PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0};
PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0};
9303 9304 9305 9306 9307
PSI_stage_info stage_allocating_local_table= { 0, "Allocating local table", 0};
PSI_stage_info stage_alter_inplace_prepare= { 0, "Preparing for alter table", 0};
PSI_stage_info stage_alter_inplace= { 0, "Altering table", 0};
PSI_stage_info stage_alter_inplace_commit= { 0, "Committing alter table to storage engine", 0};
PSI_stage_info stage_apply_event= { 0, "Apply log event", 0};
9308 9309
PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
9310 9311 9312 9313 9314
PSI_stage_info stage_checking_permissions= { 0, "Checking permissions", 0};
PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "Checking privileges on cached query", 0};
PSI_stage_info stage_checking_query_cache_for_query= { 0, "Checking query cache for query", 0};
PSI_stage_info stage_cleaning_up= { 0, "Reset for next command", 0};
PSI_stage_info stage_closing_tables= { 0, "Closing tables", 0};
9315
PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0};
9316
PSI_stage_info stage_converting_heap_to_myisam= { 0, "Converting HEAP to " TMP_ENGINE_NAME, 0};
9317 9318
PSI_stage_info stage_copying_to_group_table= { 0, "Copying to group table", 0};
PSI_stage_info stage_copying_to_tmp_table= { 0, "Copying to tmp table", 0};
9319
PSI_stage_info stage_copy_to_tmp_table= { 0, "Copy to tmp table", 0};
9320 9321
PSI_stage_info stage_creating_delayed_handler= { 0, "Creating delayed handler", 0};
PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0};
9322
PSI_stage_info stage_creating_table= { 0, "Creating table", 0};
9323
PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0};
9324 9325 9326 9327 9328 9329
PSI_stage_info stage_deleting_from_main_table= { 0, "Deleting from main table", 0};
PSI_stage_info stage_deleting_from_reference_tables= { 0, "Deleting from reference tables", 0};
PSI_stage_info stage_discard_or_import_tablespace= { 0, "Discard_or_import_tablespace", 0};
PSI_stage_info stage_enabling_keys= { 0, "Enabling keys", 0};
PSI_stage_info stage_end= { 0, "End of update loop", 0};
PSI_stage_info stage_executing= { 0, "Executing", 0};
9330
PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0};
9331
PSI_stage_info stage_explaining= { 0, "Explaining", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9332
PSI_stage_info stage_finding_key_cache= { 0, "Finding key cache", 0};
9333 9334 9335
PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0};
PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0};
PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0};
9336 9337 9338 9339 9340 9341 9342 9343 9344
PSI_stage_info stage_freeing_items= { 0, "Freeing items", 0};
PSI_stage_info stage_fulltext_initialization= { 0, "Fulltext initialization", 0};
PSI_stage_info stage_got_handler_lock= { 0, "Got handler lock", 0};
PSI_stage_info stage_got_old_table= { 0, "Got old table", 0};
PSI_stage_info stage_init= { 0, "Init", 0};
PSI_stage_info stage_init_update= { 0, "Init for update", 0};
PSI_stage_info stage_insert= { 0, "Insert", 0};
PSI_stage_info stage_invalidating_query_cache_entries_table= { 0, "Invalidating query cache entries (table)", 0};
PSI_stage_info stage_invalidating_query_cache_entries_table_list= { 0, "Invalidating query cache entries (table list)", 0};
9345
PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0};
9346
PSI_stage_info stage_logging_slow_query= { 0, "Logging slow query", 0};
9347 9348
PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE.", 0};
PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE.", 0};
9349
PSI_stage_info stage_manage_keys= { 0, "Manage keys", 0};
9350 9351
PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for binlog to be updated", 0};
PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0};
9352 9353
PSI_stage_info stage_optimizing= { 0, "Optimizing", 0};
PSI_stage_info stage_preparing= { 0, "Preparing", 0};
9354
PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0};
9355 9356 9357 9358 9359 9360
PSI_stage_info stage_query_end= { 0, "Query end", 0};
PSI_stage_info stage_starting_cleanup= { 0, "Starting cleanup", 0};
PSI_stage_info stage_rollback= { 0, "Rollback", 0};
PSI_stage_info stage_rollback_implicit= { 0, "Rollback_implicit", 0};
PSI_stage_info stage_commit= { 0, "Commit", 0};
PSI_stage_info stage_commit_implicit= { 0, "Commit_implicit", 0};
9361 9362
PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0};
PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0};
9363
PSI_stage_info stage_recreating_table= { 0, "Recreating table", 0};
9364 9365
PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0};
PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0};
9366 9367 9368
PSI_stage_info stage_removing_tmp_table= { 0, "Removing tmp table", 0};
PSI_stage_info stage_rename= { 0, "Rename", 0};
PSI_stage_info stage_rename_result_table= { 0, "Rename result table", 0};
9369
PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0};
9370
PSI_stage_info stage_reschedule= { 0, "Reschedule", 0};
9371 9372
PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0};
PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0};
9373
PSI_stage_info stage_sending_cached_result_to_client= { 0, "Sending cached result to client", 0};
9374
PSI_stage_info stage_sending_data= { 0, "Sending data", 0};
9375 9376
PSI_stage_info stage_setup= { 0, "Setup", 0};
PSI_stage_info stage_show_explain= { 0, "Show explain", 0};
9377
PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for the slave I/O thread to update it", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9378
PSI_stage_info stage_sorting= { 0, "Sorting", 0};
9379 9380 9381
PSI_stage_info stage_sorting_for_group= { 0, "Sorting for group", 0};
PSI_stage_info stage_sorting_for_order= { 0, "Sorting for order", 0};
PSI_stage_info stage_sorting_result= { 0, "Sorting result", 0};
9382
PSI_stage_info stage_statistics= { 0, "Statistics", 0};
9383
PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0 };
9384 9385
PSI_stage_info stage_storing_result_in_query_cache= { 0, "Storing result in query cache", 0};
PSI_stage_info stage_storing_row_into_queue= { 0, "Storing row into queue", 0};
9386
PSI_stage_info stage_system_lock= { 0, "System lock", 0};
9387
PSI_stage_info stage_unlocking_tables= { 0, "Unlocking tables", 0};
9388 9389
PSI_stage_info stage_table_lock= { 0, "Table lock", 0};
PSI_stage_info stage_filling_schema_table= { 0, "Filling schema table", 0};
9390 9391 9392 9393 9394
PSI_stage_info stage_update= { 0, "Update", 0};
PSI_stage_info stage_updating= { 0, "Updating", 0};
PSI_stage_info stage_updating_main_table= { 0, "Updating main table", 0};
PSI_stage_info stage_updating_reference_tables= { 0, "Updating reference tables", 0};
PSI_stage_info stage_upgrading_lock= { 0, "Upgrading lock", 0};
9395 9396
PSI_stage_info stage_user_lock= { 0, "User lock", 0};
PSI_stage_info stage_user_sleep= { 0, "User sleep", 0};
9397 9398 9399 9400 9401 9402
PSI_stage_info stage_verifying_table= { 0, "Verifying table", 0};
PSI_stage_info stage_waiting_for_delay_list= { 0, "Waiting for delay_list", 0};
PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log= { 0, "Waiting for GTID to be written to binary log", 0};
PSI_stage_info stage_waiting_for_handler_insert= { 0, "Waiting for handler insert", 0};
PSI_stage_info stage_waiting_for_handler_lock= { 0, "Waiting for handler lock", 0};
PSI_stage_info stage_waiting_for_handler_open= { 0, "Waiting for handler open", 0};
9403 9404 9405 9406
PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0};
PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0};
PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0};
PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0};
9407 9408
PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave=
{ 0, "Waiting for semi-sync ACK from slave", 0};
9409 9410
PSI_stage_info stage_waiting_for_semi_sync_slave={ 0, "Waiting for semi-sync slave connection", 0};
PSI_stage_info stage_reading_semi_sync_ack={ 0, "Reading semi-sync ACK from slave", 0};
9411 9412 9413 9414 9415 9416 9417 9418
PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0};
PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0};
PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0};
PSI_stage_info stage_waiting_for_query_cache_lock= { 0, "Waiting for query cache lock", 0};
PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0};
PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0};
PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0};
PSI_stage_info stage_waiting_to_get_readlock= { 0, "Waiting to get readlock", 0};
9419
PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0};
9420
PSI_stage_info stage_binlog_write= { 0, "Writing to binlog", 0};
9421 9422
PSI_stage_info stage_binlog_processing_checkpoint_notify= { 0, "Processing binlog checkpoint notification", 0};
PSI_stage_info stage_binlog_stopping_background_thread= { 0, "Stopping binlog background thread", 0};
9423
PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0};
9424 9425
PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to commit", 0};
PSI_stage_info stage_waiting_for_prior_transaction_to_start_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9426
PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0};
9427
PSI_stage_info stage_waiting_for_workers_idle= { 0, "Waiting for worker threads to be idle", 0};
9428 9429 9430
PSI_stage_info stage_waiting_for_ftwrl= { 0, "Waiting due to global read lock", 0};
PSI_stage_info stage_waiting_for_ftwrl_threads_to_pause= { 0, "Waiting for worker threads to pause for global read lock", 0};
PSI_stage_info stage_waiting_for_rpl_thread_pool= { 0, "Waiting while replication worker thread pool is busy", 0};
unknown's avatar
unknown committed
9431 9432
PSI_stage_info stage_master_gtid_wait_primary= { 0, "Waiting in MASTER_GTID_WAIT() (primary waiter)", 0};
PSI_stage_info stage_master_gtid_wait= { 0, "Waiting in MASTER_GTID_WAIT()", 0};
9433
PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process GTID received on multiple master connections", 0};
9434 9435 9436
PSI_stage_info stage_slave_background_process_request= { 0, "Processing requests", 0};
PSI_stage_info stage_slave_background_wait_request= { 0, "Waiting for requests", 0};
PSI_stage_info stage_waiting_for_deadlock_kill= { 0, "Waiting for parallel replication deadlock handling to complete", 0};
9437

9438
#ifdef HAVE_PSI_INTERFACE
9439

9440 9441
PSI_stage_info *all_server_stages[]=
{
9442
  & stage_after_apply_event,
9443
  & stage_after_create,
Sergei Golubchik's avatar
Sergei Golubchik committed
9444 9445
  & stage_after_opening_tables,
  & stage_after_table_lock,
9446
  & stage_allocating_local_table,
Sergei Golubchik's avatar
Sergei Golubchik committed
9447 9448 9449
  & stage_alter_inplace,
  & stage_alter_inplace_commit,
  & stage_alter_inplace_prepare,
9450
  & stage_apply_event,
9451
  & stage_binlog_write,
Sergei Golubchik's avatar
Sergei Golubchik committed
9452 9453 9454
  & stage_binlog_processing_checkpoint_notify,
  & stage_binlog_stopping_background_thread,
  & stage_binlog_waiting_background_tasks,
9455 9456 9457 9458 9459 9460 9461
  & stage_changing_master,
  & stage_checking_master_version,
  & stage_checking_permissions,
  & stage_checking_privileges_on_cached_query,
  & stage_checking_query_cache_for_query,
  & stage_cleaning_up,
  & stage_closing_tables,
9462 9463
  & stage_commit,
  & stage_commit_implicit,
9464 9465
  & stage_connecting_to_master,
  & stage_converting_heap_to_myisam,
Sergei Golubchik's avatar
Sergei Golubchik committed
9466
  & stage_copy_to_tmp_table,
9467 9468 9469 9470 9471 9472 9473 9474 9475
  & stage_copying_to_group_table,
  & stage_copying_to_tmp_table,
  & stage_creating_delayed_handler,
  & stage_creating_sort_index,
  & stage_creating_table,
  & stage_creating_tmp_table,
  & stage_deleting_from_main_table,
  & stage_deleting_from_reference_tables,
  & stage_discard_or_import_tablespace,
Sergei Golubchik's avatar
Sergei Golubchik committed
9476
  & stage_enabling_keys,
9477 9478 9479 9480
  & stage_end,
  & stage_executing,
  & stage_execution_of_init_command,
  & stage_explaining,
Sergei Golubchik's avatar
Sergei Golubchik committed
9481
  & stage_finding_key_cache,
9482 9483 9484 9485 9486 9487 9488 9489
  & stage_finished_reading_one_binlog_switching_to_next_binlog,
  & stage_flushing_relay_log_and_master_info_repository,
  & stage_flushing_relay_log_info_file,
  & stage_freeing_items,
  & stage_fulltext_initialization,
  & stage_got_handler_lock,
  & stage_got_old_table,
  & stage_init,
9490
  & stage_init_update,
9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503
  & stage_insert,
  & stage_invalidating_query_cache_entries_table,
  & stage_invalidating_query_cache_entries_table_list,
  & stage_killing_slave,
  & stage_logging_slow_query,
  & stage_making_temp_file_append_before_load_data,
  & stage_making_temp_file_create_before_load_data,
  & stage_manage_keys,
  & stage_master_has_sent_all_binlog_to_slave,
  & stage_opening_tables,
  & stage_optimizing,
  & stage_preparing,
  & stage_purging_old_relay_logs,
9504
  & stage_starting_cleanup,
9505 9506 9507
  & stage_query_end,
  & stage_queueing_master_event_to_the_relay_log,
  & stage_reading_event_from_the_relay_log,
Sergei Golubchik's avatar
Sergei Golubchik committed
9508
  & stage_recreating_table,
9509 9510 9511 9512 9513 9514 9515
  & stage_registering_slave_on_master,
  & stage_removing_duplicates,
  & stage_removing_tmp_table,
  & stage_rename,
  & stage_rename_result_table,
  & stage_requesting_binlog_dump,
  & stage_reschedule,
9516 9517
  & stage_rollback,
  & stage_rollback_implicit,
9518 9519 9520 9521 9522
  & stage_searching_rows_for_update,
  & stage_sending_binlog_event_to_slave,
  & stage_sending_cached_result_to_client,
  & stage_sending_data,
  & stage_setup,
Sergei Golubchik's avatar
Sergei Golubchik committed
9523
  & stage_show_explain,
Sergei Golubchik's avatar
Sergei Golubchik committed
9524
  & stage_slave_has_read_all_relay_log,
Sergei Golubchik's avatar
Sergei Golubchik committed
9525
  & stage_sorting,
9526 9527 9528 9529 9530 9531 9532 9533
  & stage_sorting_for_group,
  & stage_sorting_for_order,
  & stage_sorting_result,
  & stage_sql_thd_waiting_until_delay,
  & stage_statistics,
  & stage_storing_result_in_query_cache,
  & stage_storing_row_into_queue,
  & stage_system_lock,
9534
  & stage_unlocking_tables,
9535 9536
  & stage_table_lock,
  & stage_filling_schema_table,
9537 9538 9539 9540 9541 9542 9543 9544 9545
  & stage_update,
  & stage_updating,
  & stage_updating_main_table,
  & stage_updating_reference_tables,
  & stage_upgrading_lock,
  & stage_user_lock,
  & stage_user_sleep,
  & stage_verifying_table,
  & stage_waiting_for_delay_list,
Sergei Golubchik's avatar
Sergei Golubchik committed
9546
  & stage_waiting_for_gtid_to_be_written_to_binary_log,
9547 9548 9549 9550 9551 9552
  & stage_waiting_for_handler_insert,
  & stage_waiting_for_handler_lock,
  & stage_waiting_for_handler_open,
  & stage_waiting_for_insert,
  & stage_waiting_for_master_to_send_event,
  & stage_waiting_for_master_update,
Sergei Golubchik's avatar
Sergei Golubchik committed
9553
  & stage_waiting_for_prior_transaction_to_commit,
9554
  & stage_waiting_for_prior_transaction_to_start_commit,
Sergei Golubchik's avatar
Sergei Golubchik committed
9555 9556 9557
  & stage_waiting_for_query_cache_lock,
  & stage_waiting_for_relay_log_space,
  & stage_waiting_for_room_in_worker_thread,
9558 9559 9560 9561 9562
  & stage_waiting_for_slave_mutex_on_exit,
  & stage_waiting_for_slave_thread_to_start,
  & stage_waiting_for_table_flush,
  & stage_waiting_for_the_next_event_in_relay_log,
  & stage_waiting_for_the_slave_thread_to_advance_position,
Sergei Golubchik's avatar
Sergei Golubchik committed
9563
  & stage_waiting_for_work_from_sql_thread,
9564
  & stage_waiting_to_finalize_termination,
unknown's avatar
unknown committed
9565 9566
  & stage_waiting_to_get_readlock,
  & stage_master_gtid_wait_primary,
9567
  & stage_master_gtid_wait,
9568 9569
  & stage_gtid_wait_other_connection,
  & stage_slave_background_process_request,
9570
  & stage_slave_background_wait_request,
9571 9572 9573
  & stage_waiting_for_semi_sync_ack_from_slave,
  & stage_waiting_for_semi_sync_slave,
  & stage_reading_semi_sync_ack,
9574
  & stage_waiting_for_deadlock_kill
9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593
};

PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;

static PSI_socket_info all_server_sockets[]=
{
  { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_GLOBAL},
  { &key_socket_unix, "server_unix_socket", PSI_FLAG_GLOBAL},
  { &key_socket_client_connection, "client_connection", 0}
};

/**
  Initialise all the performance schema instrumentation points
  used by the server.
*/
void init_server_psi_keys(void)
{
  const char* category= "sql";
  int count;
unknown's avatar
unknown committed
9594

9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622
  count= array_elements(all_server_mutexes);
  mysql_mutex_register(category, all_server_mutexes, count);

  count= array_elements(all_server_rwlocks);
  mysql_rwlock_register(category, all_server_rwlocks, count);

  count= array_elements(all_server_conds);
  mysql_cond_register(category, all_server_conds, count);

  count= array_elements(all_server_threads);
  mysql_thread_register(category, all_server_threads, count);

  count= array_elements(all_server_files);
  mysql_file_register(category, all_server_files, count);

  count= array_elements(all_server_stages);
  mysql_stage_register(category, all_server_stages, count);

  count= array_elements(all_server_sockets);
  mysql_socket_register(category, all_server_sockets, count);

#ifdef HAVE_PSI_STATEMENT_INTERFACE
  init_sql_statement_info();
  count= array_elements(sql_statement_info);
  mysql_statement_register(category, sql_statement_info, count);

  category= "com";
  init_com_statement_info();
Sergei Golubchik's avatar
Sergei Golubchik committed
9623 9624 9625 9626 9627

  /*
    Register [0 .. COM_QUERY - 1] as "statement/com/..."
  */
  count= (int) COM_QUERY;
9628 9629
  mysql_statement_register(category, com_statement_info, count);

Sergei Golubchik's avatar
Sergei Golubchik committed
9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641
  /*
    Register [COM_QUERY + 1 .. COM_END] as "statement/com/..."
  */
  count= (int) COM_END - (int) COM_QUERY;
  mysql_statement_register(category, & com_statement_info[(int) COM_QUERY + 1], count);

  category= "abstract";
  /*
    Register [COM_QUERY] as "statement/abstract/com_query"
  */
  mysql_statement_register(category, & com_statement_info[(int) COM_QUERY], 1);

9642 9643
  /*
    When a new packet is received,
Sergei Golubchik's avatar
Sergei Golubchik committed
9644
    it is instrumented as "statement/abstract/new_packet".
9645 9646
    Based on the packet type found, it later mutates to the
    proper narrow type, for example
Sergei Golubchik's avatar
Sergei Golubchik committed
9647 9648
    "statement/abstract/query" or "statement/com/ping".
    In cases of "statement/abstract/query", SQL queries are given to
9649 9650 9651 9652
    the parser, which mutates the statement type to an even more
    narrow classification, for example "statement/sql/select".
  */
  stmt_info_new_packet.m_key= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
9653
  stmt_info_new_packet.m_name= "new_packet";
9654
  stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE;
Sergei Golubchik's avatar
Sergei Golubchik committed
9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665
  mysql_statement_register(category, &stmt_info_new_packet, 1);

  /*
    Statements processed from the relay log are initially instrumented as
    "statement/abstract/relay_log". The parser will mutate the statement type to
    a more specific classification, for example "statement/sql/insert".
  */
  stmt_info_rpl.m_key= 0;
  stmt_info_rpl.m_name= "relay_log";
  stmt_info_rpl.m_flags= PSI_FLAG_MUTABLE;
  mysql_statement_register(category, &stmt_info_rpl, 1);
unknown's avatar
unknown committed
9666
#endif
9667
}
Marc Alff's avatar
Marc Alff committed
9668

9669
#endif /* HAVE_PSI_INTERFACE */
9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705


/*
  Connection ID allocation.

  We need to maintain thread_ids in the 32bit range,
  because this is how it is passed to the client in the protocol.

  The idea is to maintain a id range, initially set to
 (0,UINT32_MAX). Whenever new id is needed, we increment the
  lower limit and return its new value.

  On "overflow", if id can not be generated anymore(i.e lower == upper -1),
  we recalculate the range boundaries.
  To do that, we first collect thread ids that are in use, by traversing
  THD list, and find largest region within (0,UINT32_MAX), that is still free.

*/

static my_thread_id thread_id_max= UINT_MAX32;

#include <vector>
#include <algorithm>

/*
  Find largest unused thread_id range.

  i.e for every number N within the returned range,
  there is no existing connection with thread_id equal to N.

  The range is exclusive, lower bound is always >=0 and
  upper bound <=MAX_UINT32.

  @param[out] low  - lower bound for the range
  @param[out] high - upper bound for the range
*/
9706 9707 9708 9709 9710 9711 9712 9713

static my_bool recalculate_callback(THD *thd, std::vector<my_thread_id> *ids)
{
  ids->push_back(thd->thread_id);
  return 0;
}


9714 9715 9716 9717 9718 9719 9720
static void recalculate_thread_id_range(my_thread_id *low, my_thread_id *high)
{
  std::vector<my_thread_id> ids;

  // Add sentinels
  ids.push_back(0);
  ids.push_back(UINT_MAX32);
9721
  server_threads.iterate(recalculate_callback, &ids);
9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762

  std::sort(ids.begin(), ids.end());
  my_thread_id max_gap= 0;
  for (size_t i= 0; i < ids.size() - 1; i++)
  {
    my_thread_id gap= ids[i+1] - ids[i];
    if (gap > max_gap)
    {
      *low= ids[i];
      *high= ids[i+1];
      max_gap= gap;
    }
  }

  if (max_gap < 2)
  {
    /* Can't find free id. This is not really possible,
      we'd need 2^32 connections for this to happen.*/
    sql_print_error("Cannot find free connection id.");
    abort();
  }
}


my_thread_id next_thread_id(void)
{
  my_thread_id retval;
  DBUG_EXECUTE_IF("thread_id_overflow", global_thread_id= thread_id_max-2;);

  mysql_mutex_lock(&LOCK_thread_id);

  if (unlikely(global_thread_id == thread_id_max - 1))
  {
    recalculate_thread_id_range(&global_thread_id, &thread_id_max);
  }

  retval= ++global_thread_id;

  mysql_mutex_unlock(&LOCK_thread_id);
  return retval;
}