mysqld.cc 334 KB
Newer Older
1
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Sergei Golubchik's avatar
Sergei Golubchik committed
2
   Copyright (c) 2008, 2014, SkySQL Ab.
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"
18 19 20 21 22 23 24 25 26 27 28 29 30
#include "sql_priv.h"
#include "unireg.h"
#include <signal.h>
#ifndef __WIN__
#include <netdb.h>        // getservbyname, servent
#endif
#include "sql_parse.h"    // test_if_data_home_dir
#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 51
#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 "derror.h"       // init_errmessage
#include "des_key_file.h" // load_des_key_file
#include "sql_manager.h"  // stop_handle_manager, start_handle_manager
52
#include "sql_expression_cache.h" // subquery_cache_miss, subquery_cache_hit
53
#include "sys_vars_shared.h"
Sergei Golubchik's avatar
Sergei Golubchik committed
54

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

79
#include "sql_callback.h"
80
#include "threadpool.h"
81

Marc Alff's avatar
Marc Alff committed
82 83 84
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
#include "../storage/perfschema/pfs_server.h"
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
85 86 87 88
#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
89

90
#include "keycaches.h"
91
#include "../storage/myisam/ha_myisam.h"
92
#include "set_var.h"
93

94 95
#include "rpl_injector.h"

He Zhenxing's avatar
He Zhenxing committed
96 97
#include "rpl_handler.h"

98 99
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
100 101
#endif

unknown's avatar
unknown committed
102 103
#include <thr_alarm.h>
#include <ft_global.h>
104
#include <errmsg.h>
unknown's avatar
Merge  
unknown committed
105 106
#include "sp_rcontext.h"
#include "sp_cache.h"
107
#include "sql_reload.h"  // reload_acl_and_cache
unknown's avatar
unknown committed
108

109 110
#ifdef HAVE_POLL_H
#include <poll.h>
111 112
#endif

unknown's avatar
unknown committed
113
#define mysqld_charset &my_charset_latin1
114

115
/* We have HAVE_valgrind below as this speeds up the shutdown of MySQL */
116

117
#if defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_valgrind) && defined(__linux__)
unknown's avatar
unknown committed
118
#define HAVE_CLOSE_SERVER_SOCK 1
119
#endif
unknown's avatar
unknown committed
120

unknown's avatar
unknown committed
121 122 123 124
extern "C" {					// Because of SCO 3.2V4.2
#include <errno.h>
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
125
#define __GNU_LIBRARY__				// Skip warnings in getopt.h
unknown's avatar
unknown committed
126
#endif
127
#include <my_getopt.h>
unknown's avatar
unknown committed
128 129 130 131 132 133 134 135 136
#ifdef HAVE_SYSENT_H
#include <sysent.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>				// For getpwent
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
unknown's avatar
Merge  
unknown committed
137
#include <my_net.h>
unknown's avatar
unknown committed
138

139
#if !defined(__WIN__)
unknown's avatar
unknown committed
140 141
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
142
#include <sys/un.h>
unknown's avatar
unknown committed
143 144
#endif
#ifdef HAVE_SELECT_H
145
#include <select.h>
unknown's avatar
unknown committed
146 147 148 149 150
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/utsname.h>
unknown's avatar
unknown committed
151
#endif /* __WIN__ */
unknown's avatar
unknown committed
152

153
#include <my_libwrap.h>
unknown's avatar
unknown committed
154

155 156 157 158
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

159 160 161 162
#ifdef __WIN__ 
#include <crtdbg.h>
#endif

163 164 165 166 167 168 169 170 171 172
#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
173
#ifdef _AIX41
unknown's avatar
unknown committed
174
int initgroups(const char *,unsigned int);
unknown's avatar
unknown committed
175 176
#endif

177
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
unknown's avatar
unknown committed
178 179 180 181
#include <ieeefp.h>
#ifdef HAVE_FP_EXCEPT				// Fix type conflict
typedef fp_except fp_except_t;
#endif
182
#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
183 184 185 186
#ifdef HAVE_SYS_FPU_H
/* for IRIX to use set_fpc_csr() */
#include <sys/fpu.h>
#endif
187 188 189
#ifdef HAVE_FPU_CONTROL_H
#include <fpu_control.h>
#endif
190 191 192 193
#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
# define fpu_control_t unsigned int
# define _FPU_EXTENDED 0x300
# define _FPU_DOUBLE 0x200
194
# if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
195 196
#  define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
#  define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
197 198 199 200 201
# else
#  define _FPU_GETCW(cw) (cw= 0)
#  define _FPU_SETCW(cw)
# endif
#endif
unknown's avatar
unknown committed
202

Sergei Golubchik's avatar
Sergei Golubchik committed
203 204 205 206
#ifndef HAVE_FCNTL
#define fcntl(X,Y,Z) 0
#endif

207 208 209
extern "C" my_bool reopen_fstreams(const char *filename,
                                   FILE *outstream, FILE *errstream);

210
inline void setup_fpu()
unknown's avatar
unknown committed
211
{
212
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
unknown's avatar
unknown committed
213
  /* We can't handle floating point exceptions with threads, so disable
unknown's avatar
unknown committed
214
     this on freebsd
215 216
     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
217
  */
218
#if defined(FP_X_DNML)
unknown's avatar
unknown committed
219 220
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
	      FP_X_IMP));
unknown's avatar
unknown committed
221
#else
222 223
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
224 225 226 227 228 229
#endif /* FP_X_DNML */
#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */

#ifdef HAVE_FEDISABLEEXCEPT
  fedisableexcept(FE_ALL_EXCEPT);
#endif
230

231 232 233 234
#ifdef HAVE_FESETROUND
    /* Set FPU rounding mode to "round-to-nearest" */
  fesetround(FE_TONEAREST);
#endif /* HAVE_FESETROUND */
235 236

  /*
237 238 239 240
    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.
241
  */
242
#if defined(__i386__) && !defined(__SSE2_MATH__)
243 244 245 246 247 248 249 250 251 252 253 254
#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__ */

255
#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
256
  /* Enable denormalized DOUBLE values support for IRIX */
257 258 259 260 261
  union fpc_csr n;
  n.fc_word = get_fpc_csr();
  n.fc_struct.flush = 0;
  set_fpc_csr(n.fc_word);
#endif
262
}
unknown's avatar
unknown committed
263

unknown's avatar
unknown committed
264 265
} /* cplusplus */

unknown's avatar
unknown committed
266
#define MYSQL_KILL_SIGNAL SIGTERM
unknown's avatar
unknown committed
267 268 269 270 271 272 273

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

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

274
extern "C" sig_handler handle_fatal_signal(int sig);
275

276 277 278
#if defined(__linux__)
#define ENABLE_TEMP_POOL 1
#else
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
279
#define ENABLE_TEMP_POOL 0
280 281
#endif

unknown's avatar
unknown committed
282
/* Constants */
283

284 285
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE

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

unknown's avatar
unknown committed
288 289 290 291 292 293 294 295 296
static const char *tc_heuristic_recover_names[]=
{
  "COMMIT", "ROLLBACK", NullS
};
static TYPELIB tc_heuristic_recover_typelib=
{
  array_elements(tc_heuristic_recover_names)-1,"",
  tc_heuristic_recover_names, NULL
};
unknown's avatar
unknown committed
297

unknown's avatar
unknown committed
298
const char *first_keyword= "first", *binary_keyword= "BINARY";
unknown's avatar
unknown committed
299
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
300

unknown's avatar
unknown committed
301
bool opt_large_files= sizeof(my_off_t) > 4;
302
static my_bool opt_autocommit; ///< for --autocommit command-line option
303 304 305 306

/*
  Used with --help for detailed option
*/
307
static my_bool opt_verbose= 0;
308

309
arg_cmp_func Arg_comparator::comparator_matrix[6][2] =
310 311 312
{{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
 {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
 {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
unknown's avatar
Merge  
unknown committed
313
 {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
314 315
 {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal},
 {&Arg_comparator::compare_datetime,   &Arg_comparator::compare_e_datetime}};
unknown's avatar
unknown committed
316

unknown's avatar
unknown committed
317 318
/* static variables */

Marc Alff's avatar
Marc Alff committed
319 320 321
#ifdef HAVE_PSI_INTERFACE
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
static PSI_thread_key key_thread_handle_con_namedpipes;
Marc Alff's avatar
Marc Alff committed
322
static PSI_cond_key key_COND_handler_count;
Marc Alff's avatar
Marc Alff committed
323 324 325 326 327 328 329 330 331 332 333 334 335
#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */

#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
static PSI_thread_key key_thread_handle_con_sharedmem;
#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */

#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
static PSI_thread_key key_thread_handle_con_sockets;
#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */

#ifdef __WIN__
static PSI_thread_key key_thread_handle_shutdown;
#endif /* __WIN__ */
336 337 338 339

#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
static PSI_rwlock_key key_rwlock_openssl;
#endif
Marc Alff's avatar
Marc Alff committed
340 341
#endif /* HAVE_PSI_INTERFACE */

342 343 344 345
#ifdef HAVE_NPTL
volatile sig_atomic_t ld_assume_kernel_is_set= 0;
#endif

Sergei Golubchik's avatar
Sergei Golubchik committed
346 347 348 349 350 351 352
/**
  Statement instrumentation key for replication.
*/
#ifdef HAVE_PSI_STATEMENT_INTERFACE
PSI_statement_info stmt_info_rpl;
#endif

353
/* the default log output is log tables */
unknown's avatar
unknown committed
354
static bool lower_case_table_names_used= 0;
355
static bool max_long_data_size_used= false;
unknown's avatar
unknown committed
356
static bool volatile select_thread_in_use, signal_thread_in_use;
357
static volatile bool ready_to_exit;
unknown's avatar
unknown committed
358 359
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
360 361
uint kill_cached_threads;
static uint wake_thread;
Michael Widenius's avatar
Michael Widenius committed
362
ulong max_used_connections;
unknown's avatar
unknown committed
363
static volatile ulong cached_thread_count= 0;
364
static char *mysqld_user, *mysqld_chroot;
unknown's avatar
unknown committed
365
static char *default_character_set_name;
unknown's avatar
unknown committed
366
static char *character_set_filesystem_name;
367
static char *lc_messages;
368
static char *lc_time_names_name;
369
char *my_bind_addr_str;
370
static char *default_collation_name;
371
char *default_storage_engine, *default_tmp_storage_engine;
372
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
unknown's avatar
unknown committed
373
static I_List<THD> thread_cache;
374 375
static bool binlog_format_used= false;
LEX_STRING opt_init_connect, opt_init_slave;
376 377
mysql_cond_t COND_thread_cache;
static mysql_cond_t COND_flush_thread_cache;
378
static DYNAMIC_ARRAY all_options;
unknown's avatar
unknown committed
379

unknown's avatar
unknown committed
380
/* Global variables */
unknown's avatar
unknown committed
381

382
bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0;
Monty's avatar
Monty committed
383
my_bool opt_log, debug_assert_if_crashed_table= 0, opt_help= 0;
384
static my_bool opt_abort;
385
ulonglong log_output_options;
Sergei Golubchik's avatar
Sergei Golubchik committed
386
my_bool opt_userstat_running;
387
my_bool opt_log_queries_not_using_indexes= 0;
388
bool opt_error_log= IF_WIN(1,0);
unknown's avatar
unknown committed
389
bool opt_disable_networking=0, opt_skip_show_db=0;
390
bool opt_skip_name_resolve=0;
391
my_bool opt_character_set_client_handshake= 1;
unknown's avatar
unknown committed
392
bool server_id_supplied = 0;
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;
397
bool volatile shutdown_in_progress;
Sergei Golubchik's avatar
Sergei Golubchik committed
398
uint volatile global_disable_checkpoint;
399 400 401
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
ulong slow_start_timeout;
#endif
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
/*
  True if the bootstrap thread is running. Protected by LOCK_thread_count,
  just like thread_count.
  Used in bootstrap() function to determine if the bootstrap thread
  has completed. Note, that we can't use 'thread_count' instead,
  since in 5.1, in presence of the Event Scheduler, there may be
  event threads running in parallel, so it's impossible to know
  what value of 'thread_count' is a sign of completion of the
  bootstrap thread.

  At the same time, we can't start the event scheduler after
  bootstrap either, since we want to be able to process event-related
  SQL commands in the init file and in --bootstrap mode.
*/
bool in_bootstrap= FALSE;
417 418 419 420
/**
   @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.
421
   @note This flag is dropped in 5.1
422 423 424
   @see grant_init()
 */
bool volatile grant_option;
unknown's avatar
unknown committed
425

unknown's avatar
unknown committed
426
my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
unknown's avatar
unknown committed
427
my_bool opt_reckless_slave = 0;
unknown's avatar
unknown committed
428 429
my_bool opt_enable_named_pipe= 0;
my_bool opt_local_infile, opt_slave_compressed_protocol;
430 431
my_bool opt_safe_user_create = 0;
my_bool opt_show_slave_auth_info;
432
my_bool opt_log_slave_updates= 0;
433
my_bool opt_replicate_annotate_row_events= 0;
434 435
char *opt_slave_skip_errors;

436 437 438 439 440
/*
  Legacy global handlerton. These will be removed (please do not add more).
*/
handlerton *heap_hton;
handlerton *myisam_hton;
441
handlerton *partition_hton;
442

443 444
my_bool read_only= 0, opt_readonly= 0;
my_bool use_temp_pool, relay_log_purge;
445
my_bool relay_log_recovery;
unknown's avatar
unknown committed
446
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
447
my_bool opt_secure_auth= 0;
448
char* opt_secure_file_priv;
449
my_bool opt_log_slow_admin_statements= 0;
450
my_bool opt_log_slow_slave_statements= 0;
unknown's avatar
unknown committed
451
my_bool lower_case_file_system= 0;
452
my_bool opt_large_pages= 0;
453
my_bool opt_super_large_pages= 0;
unknown's avatar
unknown committed
454
my_bool opt_myisam_use_mmap= 0;
455
uint   opt_large_page_size= 0;
456
#if defined(ENABLED_DEBUG_SYNC)
457
MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
458
#endif /* defined(ENABLED_DEBUG_SYNC) */
459
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
460
ulong opt_replicate_events_marked_for_skip;
461

unknown's avatar
Merge  
unknown committed
462 463 464 465 466
/*
  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
467
volatile bool mqh_used = 0;
468
my_bool opt_noacl;
unknown's avatar
Merge  
unknown committed
469
my_bool sp_automatic_privileges= 1;
470

471
ulong opt_binlog_rows_event_max_size;
472 473
my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1;
unknown's avatar
unknown committed
474
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
475
#ifdef HAVE_INITGROUPS
476
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
477
#endif
478
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
479
uint mysqld_extra_port;
480
uint mysqld_port_timeout;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
481
ulong delay_key_write_options;
482
uint protocol_version;
unknown's avatar
unknown committed
483
uint lower_case_table_names;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
484
ulong tc_heuristic_recover= 0;
Michael Widenius's avatar
Michael Widenius committed
485
int32 thread_count;
486
int32 thread_running;
Michael Widenius's avatar
Michael Widenius committed
487
int32 slave_open_temp_tables;
488
ulong thread_created;
489
ulong back_log, connect_timeout, concurrency, server_id;
490
ulong what_to_log;
Michael Widenius's avatar
Michael Widenius committed
491
ulong slow_launch_time;
492
ulong open_files_limit, max_binlog_size;
493 494
ulong slave_trans_retries;
uint  slave_net_timeout;
495
ulong slave_exec_mode_options;
496
ulong slave_run_triggers_for_rbr= 0;
497
ulong slave_ddl_exec_mode_options= SLAVE_EXEC_MODE_IDEMPOTENT;
unknown's avatar
unknown committed
498
ulonglong slave_type_conversions_options;
499
ulong thread_cache_size=0;
500 501
ulonglong binlog_cache_size=0;
ulonglong max_binlog_cache_size=0;
502
ulong slave_max_allowed_packet= 0;
503 504 505
ulonglong binlog_stmt_cache_size=0;
ulonglong  max_binlog_stmt_cache_size=0;
ulonglong query_cache_size=0;
506
ulong query_cache_limit=0;
507
ulong executed_events=0;
508
query_id_t global_query_id;
509
my_atomic_rwlock_t global_query_id_lock;
510
my_atomic_rwlock_t thread_running_lock;
Michael Widenius's avatar
Michael Widenius committed
511
my_atomic_rwlock_t thread_count_lock;
512
my_atomic_rwlock_t statistics_lock;
513
my_atomic_rwlock_t slave_executed_entries_lock;
unknown's avatar
unknown committed
514
ulong aborted_threads, aborted_connects;
unknown's avatar
unknown committed
515 516
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
517
ulong delayed_insert_errors,flush_time;
unknown's avatar
Merge  
unknown committed
518
ulong specialflag=0;
519
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
520
ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
unknown's avatar
unknown committed
521
ulong max_connections, max_connect_errors;
522
ulong extra_max_connections;
523
ulong slave_retried_transactions;
524
ulonglong denied_connections;
Sergei Golubchik's avatar
Sergei Golubchik committed
525
my_decimal decimal_zero;
Sergei Golubchik's avatar
Sergei Golubchik committed
526

527 528 529 530 531
/*
  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
532

533 534 535 536
/* Limits for internal temporary tables (MyISAM or Aria) */
uint internal_tmp_table_max_key_length;
uint internal_tmp_table_max_key_segments;

537
bool max_user_connections_checking=0;
unknown's avatar
unknown committed
538
/**
539 540 541 542
  Limit of the total number of prepared statements in the server.
  Is necessary to protect the server against out-of-memory attacks.
*/
ulong max_prepared_stmt_count;
unknown's avatar
unknown committed
543
/**
544 545 546 547 548 549 550 551 552 553
  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.
*/
ulong prepared_stmt_count=0;
unknown's avatar
unknown committed
554
ulong thread_id=1L,current_pid;
555
ulong slow_launch_threads = 0;
556 557
uint sync_binlog_period= 0, sync_relaylog_period= 0,
     sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
unknown's avatar
unknown committed
558
ulong expire_logs_days = 0;
unknown's avatar
unknown committed
559
ulong rpl_recovery_rank=0;
560 561 562 563 564
/**
  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
565

566
ulong opt_slave_parallel_threads= 0;
unknown's avatar
unknown committed
567
ulong opt_slave_domain_parallel_threads= 0;
568 569
ulong opt_binlog_commit_wait_count= 0;
ulong opt_binlog_commit_wait_usec= 0;
unknown's avatar
unknown committed
570
ulong opt_slave_parallel_max_queued= 131072;
571
my_bool opt_gtid_ignore_duplicates= FALSE;
572

573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
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
606

607
time_t server_start_time, flush_status_time;
608

609 610
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
char *default_tz_name;
611
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN], *opt_log_basename;
unknown's avatar
unknown committed
612
char mysql_real_data_home[FN_REFLEN],
613 614
     lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
     mysql_charsets_dir[FN_REFLEN],
615
     *opt_init_file, *opt_tc_log_file;
616
char *lc_messages_dir_ptr= lc_messages_dir, *log_error_file_ptr;
617
char mysql_unpacked_real_data_home[FN_REFLEN];
618
int mysql_unpacked_real_data_home_len;
619
uint mysql_real_data_home_len, mysql_data_home_len= 1;
620
uint reg_ext_length;
621 622 623
const key_map key_map_empty(0);
key_map key_map_full(0);                        // Will be initialized later

624 625
DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
Time_zone *default_tz;
626

627
const char *mysql_real_data_home_ptr= mysql_real_data_home;
628
char server_version[SERVER_VERSION_LENGTH];
629
char *mysqld_unix_port, *opt_mysql_tmpdir;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
630
ulong thread_handling;
631

632
/** name of reference on left expression in rewritten IN subquery */
633
const char *in_left_expr_name= "<left expr>";
unknown's avatar
unknown committed
634
/** name of additional condition */
635
const char *in_additional_cond= "<IN COND>";
636 637
const char *in_having_cond= "<IN HAVING>";

unknown's avatar
unknown committed
638 639 640 641 642 643 644 645 646 647 648 649 650
/** 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
651 652 653 654 655 656 657 658
/* 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;

Marc Alff's avatar
Marc Alff committed
659
MYSQL_FILE *bootstrap_file;
unknown's avatar
Merge  
unknown committed
660
int bootstrap_error;
unknown's avatar
unknown committed
661

unknown's avatar
unknown committed
662
I_List<THD> threads;
663 664
Rpl_filter* cur_rpl_filter;
Rpl_filter* global_rpl_filter;
unknown's avatar
unknown committed
665
Rpl_filter* binlog_filter;
unknown's avatar
unknown committed
666

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
THD *first_global_thread()
{
  if (threads.is_empty())
    return NULL;
  return threads.head();
}

THD *next_global_thread(THD *thd)
{
  if (threads.is_last(thd))
    return NULL;
  struct ilink *next= thd->next;
  return static_cast<THD*>(next);
}

unknown's avatar
unknown committed
682 683
struct system_variables global_system_variables;
struct system_variables max_system_variables;
unknown's avatar
Merge  
unknown committed
684
struct system_status_var global_status_var;
unknown's avatar
unknown committed
685

unknown's avatar
unknown committed
686
MY_TMPDIR mysql_tmpdir_list;
687
MY_BITMAP temp_pool;
unknown's avatar
unknown committed
688

689 690
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
unknown's avatar
unknown committed
691
CHARSET_INFO *character_set_filesystem;
Marc Alff's avatar
Marc Alff committed
692
CHARSET_INFO *error_message_charset_info;
693

694
MY_LOCALE *my_default_lc_messages;
695 696
MY_LOCALE *my_default_lc_time_names;

697
SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
698
SHOW_COMP_OPTION have_geometry, have_rtree_keys;
unknown's avatar
unknown committed
699
SHOW_COMP_OPTION have_crypt, have_compress;
700
SHOW_COMP_OPTION have_profiling;
701
SHOW_COMP_OPTION have_openssl;
unknown's avatar
unknown committed
702 703

/* Thread specific variables */
704

unknown's avatar
unknown committed
705
pthread_key(MEM_ROOT**,THR_MALLOC);
unknown's avatar
unknown committed
706
pthread_key(THD*, THR_THD);
Michael Widenius's avatar
Michael Widenius committed
707
mysql_mutex_t LOCK_thread_count, LOCK_thread_cache;
708
mysql_mutex_t
Sergei Golubchik's avatar
Sergei Golubchik committed
709
  LOCK_status, LOCK_error_log, LOCK_short_uuid_generator,
Marc Alff's avatar
Marc Alff committed
710 711 712 713 714
  LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
  LOCK_crypt,
  LOCK_global_system_variables,
  LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
  LOCK_connection_count, LOCK_error_messages;
Sergei Golubchik's avatar
Sergei Golubchik committed
715 716 717

mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats,
              LOCK_global_table_stats, LOCK_global_index_stats;
718

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 731
mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
mysql_rwlock_t LOCK_system_variables_hash;
Marc Alff's avatar
Marc Alff committed
732
mysql_cond_t COND_thread_count;
unknown's avatar
unknown committed
733 734
pthread_t signal_thread;
pthread_attr_t connection_attrib;
Marc Alff's avatar
Marc Alff committed
735 736
mysql_mutex_t LOCK_server_started;
mysql_cond_t COND_server_started;
unknown's avatar
unknown committed
737

738
int mysqld_server_started=0, mysqld_server_initialized= 0;
739 740
File_parser_dummy_hook file_parser_dummy_hook;

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

/* Static variables */

751
static volatile sig_atomic_t kill_in_progress;
Michael Widenius's avatar
Michael Widenius committed
752
my_bool opt_stack_trace;
753 754
my_bool opt_expect_abort= 0, opt_bootstrap= 0;
static my_bool opt_myisam_log;
unknown's avatar
unknown committed
755
static int cleanup_done;
756
static ulong opt_specialflag;
Sergei Golubchik's avatar
Sergei Golubchik committed
757
static char *opt_binlog_index_name;
758
char *mysql_home_ptr, *pidfile_name_ptr;
Marc Alff's avatar
Marc Alff committed
759
/** Initial command line arguments (count), after load_defaults().*/
unknown's avatar
unknown committed
760
static int defaults_argc;
Marc Alff's avatar
Marc Alff committed
761 762 763 764 765 766 767 768
/**
  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
769
static char **defaults_argv;
Marc Alff's avatar
Marc Alff committed
770 771 772 773
/** 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
774

775 776 777
int orig_argc;
char **orig_argv;

778
static struct my_option pfs_early_options[]=
779
{
780
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
781 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,
    GET_BOOL, OPT_ARG, TRUE, 0, 0, 0, 0, 0}
845
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
846 847
};

848 849
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
850 851
PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool,
  key_LOCK_pending_checkpoint;
852 853 854 855 856 857
#endif /* HAVE_MMAP */

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

858
PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
859
  key_BINLOG_LOCK_binlog_background_thread,
860 861 862 863 864 865 866
  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,
  key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status,
867
  key_LOCK_system_variables_hash, key_LOCK_thd_data,
868 869
  key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log,
  key_master_info_data_lock, key_master_info_run_lock,
Sergei Golubchik's avatar
Sergei Golubchik committed
870
  key_master_info_sleep_lock,
871
  key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
Michael Widenius's avatar
Michael Widenius committed
872
  key_rpl_group_info_sleep_lock,
873
  key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
874
  key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
Michael Widenius's avatar
Michael Widenius committed
875 876
  key_LOCK_error_messages, key_LOG_INFO_lock,
  key_LOCK_thread_count, key_LOCK_thread_cache,
877 878
  key_PARTITION_LOCK_auto_inc;
PSI_mutex_key key_RELAYLOG_LOCK_index;
879
PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
880
  key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry;
881 882 883

PSI_mutex_key key_LOCK_stats,
  key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
Sergei Golubchik's avatar
Sergei Golubchik committed
884
  key_LOCK_global_index_stats,
885
  key_LOCK_wakeup_ready, key_LOCK_wait_commit;
886
PSI_mutex_key key_LOCK_gtid_waiting;
Sergei Golubchik's avatar
Sergei Golubchik committed
887 888

PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
Sergei Golubchik's avatar
Sergei Golubchik committed
889
PSI_mutex_key key_TABLE_SHARE_LOCK_share;
890 891 892 893 894 895 896 897

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},
898
  { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pending_checkpoint", 0},
899 900 901 902 903 904 905
#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},
906
  { &key_BINLOG_LOCK_xid_list, "MYSQL_BIN_LOG::LOCK_xid_list", 0},
907
  { &key_BINLOG_LOCK_binlog_background_thread, "MYSQL_BIN_LOG::LOCK_binlog_background_thread", 0},
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
  { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
  { &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},
  { &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
930
  { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
931
  { &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0},
932
  { &key_LOCK_gtid_waiting, "gtid_waiting::LOCK_gtid_waiting", 0},
933 934
  { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
  { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
935
  { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
936 937 938
  { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
  { &key_master_info_data_lock, "Master_info::data_lock", 0},
  { &key_master_info_run_lock, "Master_info::run_lock", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
939
  { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
940 941 942 943
  { &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
944
  { &key_rpl_group_info_sleep_lock, "Rpl_group_info::sleep_lock", 0},
945 946
  { &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
947
  { &key_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0},
948
  { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
949 950
  { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL},
  { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
951 952
  { &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
  { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
Michael Widenius's avatar
Michael Widenius committed
953
  { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL},
954
  { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0},
unknown's avatar
unknown committed
955
  { &key_LOCK_slave_state, "LOCK_slave_state", 0},
956 957
  { &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
  { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
958 959
  { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
  { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0}
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
};

PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
  key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
  key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;

static PSI_rwlock_info all_server_rwlocks[]=
{
#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
  { &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},
  { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
  { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}
};

#ifdef HAVE_MMAP
980
PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
981 982
#endif /* HAVE_MMAP */

983
PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
984 985
  key_BINLOG_COND_binlog_background_thread,
  key_BINLOG_COND_binlog_background_thread_end,
986 987 988 989 990
  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
991
  key_master_info_sleep_cond,
992 993
  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
994
  key_rpl_group_info_sleep_cond,
995
  key_TABLE_SHARE_cond, key_user_level_lock_cond,
996 997
  key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache,
  key_BINLOG_COND_queue_busy;
998 999
PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready,
  key_COND_wait_commit;
1000 1001
PSI_cond_key key_RELAYLOG_COND_queue_busy;
PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
unknown's avatar
unknown committed
1002 1003 1004 1005
PSI_cond_key key_COND_rpl_thread_queue, key_COND_rpl_thread,
  key_COND_rpl_thread_pool,
  key_COND_parallel_entry, key_COND_group_commit_orderer,
  key_COND_prepare_ordered;
1006
PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates;
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016

static PSI_cond_info all_server_conds[]=
{
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
  { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL},
#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
#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},
1017
  { &key_TC_LOG_MMAP_COND_queue_busy, "TC_LOG_MMAP::COND_queue_busy", 0},
1018
#endif /* HAVE_MMAP */
1019
  { &key_BINLOG_COND_xid_list, "MYSQL_BIN_LOG::COND_xid_list", 0},
1020
  { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
1021 1022
  { &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},
1023
  { &key_BINLOG_COND_queue_busy, "MYSQL_BIN_LOG::COND_queue_busy", 0},
1024
  { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
1025
  { &key_RELAYLOG_COND_queue_busy, "MYSQL_RELAY_LOG::COND_queue_busy", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
1026
  { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 0},
1027
  { &key_COND_wait_commit, "wait_for_commit::COND_wait_commit", 0},
1028 1029 1030 1031 1032 1033 1034 1035 1036
  { &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
1037
  { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
1038 1039 1040 1041
  { &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
1042
  { &key_rpl_group_info_sleep_cond, "Rpl_group_info::sleep_cond", 0},
1043 1044 1045 1046
  { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
  { &key_user_level_lock_cond, "User_level_lock::cond", 0},
  { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL},
  { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL},
1047 1048
  { &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
1049
  { &key_COND_rpl_thread_queue, "COND_rpl_thread_queue", 0},
1050
  { &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0},
1051
  { &key_COND_parallel_entry, "COND_parallel_entry", 0},
unknown's avatar
unknown committed
1052
  { &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0},
1053
  { &key_COND_prepare_ordered, "COND_prepare_ordered", 0},
1054 1055
  { &key_COND_wait_gtid, "COND_wait_gtid", 0},
  { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0}
1056 1057 1058 1059
};

PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
  key_thread_handle_manager, key_thread_main,
1060
  key_thread_one_connection, key_thread_signal_hand,
1061
  key_thread_slave_init, key_rpl_parallel_thread;
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085

static PSI_thread_info all_server_threads[]=
{
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
  { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL},
#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */

#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
  { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL},
#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */

#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
  { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL},
#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */

#ifdef __WIN__
  { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL},
#endif /* __WIN__ */

  { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL},
  { &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},
1086
  { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL},
1087 1088
  { &key_thread_slave_init, "slave_init", PSI_FLAG_GLOBAL},
  { &key_rpl_parallel_thread, "rpl_parallel_thread", 0}
1089 1090
};

1091 1092 1093 1094
#ifdef HAVE_MMAP
PSI_file_key key_file_map;
#endif /* HAVE_MMAP */

1095 1096 1097 1098 1099 1100 1101 1102 1103
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;
1104
PSI_file_key key_file_binlog_state;
1105

1106
#endif /* HAVE_PSI_INTERFACE */
1107

1108 1109 1110 1111 1112 1113
#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 */)
1114
{
1115 1116 1117
  THD *thd;
  thd= static_cast<THD*> (user_data);
  DBUG_ASSERT(thd != NULL);
1118

1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
  if (thd->m_server_idle)
  {
    /*
      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);
  }
}
1132

1133 1134 1135 1136 1137
void net_after_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */, my_bool rc)
{
  THD *thd;
  thd= static_cast<THD*> (user_data);
  DBUG_ASSERT(thd != NULL);
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
  if (thd->m_server_idle)
  {
    /*
      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);
1153

1154 1155 1156 1157
    if (! rc)
    {
      thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
                                                  stmt_info_new_packet.m_key,
1158 1159
                                                  thd->db, thd->db_length,
                                                  thd->charset());
1160

1161 1162
      THD_STAGE_INFO(thd, stage_init);
    }
1163

1164 1165 1166 1167 1168 1169
    /*
      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);
  }
1170 1171
}

1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
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;
  thd->m_server_idle= false;
  /* 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;
}
#endif /* EMBEDDED_LIBRARY */
1186

Marc Alff's avatar
Marc Alff committed
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
/**
  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:
    sql_print_error("Buffered error: %s\n", m_message.c_ptr_safe());
    break;
  case WARNING_LEVEL:
    sql_print_warning("Buffered warning: %s\n", m_message.c_ptr_safe());
    break;
  case INFORMATION_LEVEL:
1239 1240 1241 1242 1243 1244 1245 1246 1247
    /*
      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
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
    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()
{
1283
  init_alloc_root(&m_root, 1024, 0, MYF(0));
Marc Alff's avatar
Marc Alff committed
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 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
}

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;

1322 1323 1324
static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()

1325
#ifndef EMBEDDED_LIBRARY
Marc Alff's avatar
Marc Alff committed
1326 1327 1328 1329 1330
/**
  Error reporter that buffer log messages.
  @param level          log message level
  @param format         log message format string
*/
1331
C_MODE_START
1332 1333
static void buffered_option_error_reporter(enum loglevel level,
                                           const char *format, ...)
Marc Alff's avatar
Marc Alff committed
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
{
  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);
}

1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370

/**
  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
1371 1372 1373 1374
struct passwd *user_info;
static pthread_t select_thread;
#endif

unknown's avatar
unknown committed
1375 1376
/* OS specific variables */

unknown's avatar
unknown committed
1377 1378 1379
#ifdef __WIN__
#undef	 getpid
#include <process.h>
unknown's avatar
unknown committed
1380

Marc Alff's avatar
Marc Alff committed
1381
static mysql_cond_t COND_handler_count;
unknown's avatar
unknown committed
1382 1383 1384 1385 1386
static uint handler_count;
static bool start_mode=0, use_opt_args;
static int opt_argc;
static char **opt_argv;

unknown's avatar
unknown committed
1387
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
1388
static HANDLE hEventShutdown;
1389
static char shutdown_event_name[40];
unknown's avatar
unknown committed
1390
#include "nt_servc.h"
unknown's avatar
unknown committed
1391
static	 NTService  Service;	      ///< Service object for WinNT
unknown's avatar
unknown committed
1392 1393 1394
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */

Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1395
#ifdef _WIN32
1396
static char pipe_name[512];
unknown's avatar
unknown committed
1397 1398 1399
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
unknown's avatar
unknown committed
1400
#endif
unknown's avatar
unknown committed
1401

unknown's avatar
unknown committed
1402
#ifndef EMBEDDED_LIBRARY
1403
bool mysqld_embedded=0;
unknown's avatar
unknown committed
1404
#else
1405
bool mysqld_embedded=1;
unknown's avatar
unknown committed
1406 1407
#endif

1408
my_bool plugins_are_initialized= FALSE;
1409

unknown's avatar
unknown committed
1410
#ifndef DBUG_OFF
1411
static const char* default_dbug_option;
unknown's avatar
unknown committed
1412
#endif
1413
static const char *current_dbug_option="disabled";
unknown's avatar
unknown committed
1414
#ifdef HAVE_LIBWRAP
1415
const char *libwrapName= NULL;
1416 1417
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
unknown's avatar
unknown committed
1418 1419 1420 1421 1422 1423 1424
#endif
#ifdef HAVE_QUERY_CACHE
ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
Query_cache query_cache;
#endif
#ifdef HAVE_SMEM
char *shared_memory_base_name= default_shared_memory_base_name;
1425
my_bool opt_enable_shared_memory;
1426
HANDLE smem_event_connect_request= 0;
unknown's avatar
unknown committed
1427 1428
#endif

1429 1430
my_bool opt_use_ssl  = 0;
char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
1431 1432 1433
  *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL,
  *opt_ssl_crlpath= NULL;

1434

Sergei Golubchik's avatar
Sergei Golubchik committed
1435 1436 1437
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
1438

unknown's avatar
unknown committed
1439
#ifdef HAVE_OPENSSL
1440
#include <openssl/crypto.h>
unknown's avatar
unknown committed
1441
#ifndef HAVE_YASSL
1442 1443
typedef struct CRYPTO_dynlock_value
{
Marc Alff's avatar
Marc Alff committed
1444
  mysql_rwlock_t lock;
1445 1446 1447 1448 1449 1450 1451 1452
} 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);
static unsigned long openssl_id_function();
unknown's avatar
unknown committed
1453
#endif
unknown's avatar
unknown committed
1454
char *des_key_file;
Konstantin Osipov's avatar
Konstantin Osipov committed
1455
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1456
struct st_VioSSLFd *ssl_acceptor_fd;
Konstantin Osipov's avatar
Konstantin Osipov committed
1457
#endif
unknown's avatar
unknown committed
1458 1459
#endif /* HAVE_OPENSSL */

1460 1461 1462 1463
/**
  Number of currently active user connections. The variable is protected by
  LOCK_connection_count.
*/
1464
uint connection_count= 0, extra_connection_count= 0;
unknown's avatar
unknown committed
1465

1466
my_bool opt_gtid_strict_mode= FALSE;
1467 1468


unknown's avatar
unknown committed
1469 1470
/* Function declarations */

1471
pthread_handler_t signal_hand(void *arg);
1472
static int mysql_init_variables(void);
Marc Alff's avatar
Marc Alff committed
1473 1474
static int get_options(int *argc_ptr, char ***argv_ptr);
static bool add_terminator(DYNAMIC_ARRAY *options);
1475
static bool add_many_options(DYNAMIC_ARRAY *, my_option *, size_t);
1476
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
1477
static int init_thread_environment();
unknown's avatar
unknown committed
1478
static char *get_relative_path(const char *path);
1479
static int fix_paths(void);
1480 1481 1482 1483
void handle_connections_sockets();
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg);
#endif
1484
pthread_handler_t kill_server_thread(void *arg);
Marc Alff's avatar
Marc Alff committed
1485
static void bootstrap(MYSQL_FILE *file);
unknown's avatar
unknown committed
1486
static bool read_init_file(char *file_name);
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1487
#ifdef _WIN32
1488
pthread_handler_t handle_connections_namedpipes(void *arg);
unknown's avatar
unknown committed
1489
#endif
1490
#ifdef HAVE_SMEM
1491
pthread_handler_t handle_connections_shared_memory(void *arg);
1492
#endif
1493
pthread_handler_t handle_slave(void *arg);
unknown's avatar
unknown committed
1494
static void clean_up(bool print_message);
1495 1496 1497
static int test_if_case_insensitive(const char *dir_name);

#ifndef EMBEDDED_LIBRARY
1498
static bool pid_file_created= false;
1499
static void usage(void);
1500 1501
static void start_signal_handler(void);
static void close_server_sock();
unknown's avatar
unknown committed
1502
static void clean_up_mutexes(void);
1503
static void wait_for_signal_thread_to_end(void);
1504
static void create_pid_file();
1505
static void mysqld_exit(int exit_code) __attribute__((noreturn));
1506
#endif
1507
static void delete_pid_file(myf flags);
Konstantin Osipov's avatar
Konstantin Osipov committed
1508
static void end_ssl();
1509

1510 1511

#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
/****************************************************************************
** Code to end mysqld
****************************************************************************/

static void close_connections(void)
{
#ifdef EXTRA_DEBUG
  int count=0;
#endif
  DBUG_ENTER("close_connections");

  /* Clear thread cache */
  kill_cached_threads++;
  flush_thread_cache();

  /* kill connection thread */
1528
#if !defined(__WIN__)
unknown's avatar
unknown committed
1529 1530
  DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
                      (ulong) select_thread));
Marc Alff's avatar
Marc Alff committed
1531
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
1532 1533 1534 1535 1536 1537

  while (select_thread_in_use)
  {
    struct timespec abstime;
    int error;
    LINT_INIT(error);
unknown's avatar
unknown committed
1538
    DBUG_PRINT("info",("Waiting for select thread"));
1539

unknown's avatar
unknown committed
1540
#ifndef DONT_USE_THR_ALARM
1541
    if (pthread_kill(select_thread, thr_client_alarm))
unknown's avatar
unknown committed
1542 1543
      break;					// allready dead
#endif
1544
    set_timespec(abstime, 2);
1545
    for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
unknown's avatar
unknown committed
1546
    {
Marc Alff's avatar
Marc Alff committed
1547 1548
      error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
                                  &abstime);
unknown's avatar
unknown committed
1549 1550 1551 1552
      if (error != EINTR)
	break;
    }
#ifdef EXTRA_DEBUG
1553
    if (error != 0 && error != ETIMEDOUT && !count++)
Marc Alff's avatar
Marc Alff committed
1554
      sql_print_error("Got error %d from mysql_cond_timedwait", error);
unknown's avatar
unknown committed
1555
#endif
unknown's avatar
unknown committed
1556
    close_server_sock();
unknown's avatar
unknown committed
1557
  }
Marc Alff's avatar
Marc Alff committed
1558
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1559 1560 1561 1562 1563
#endif /* __WIN__ */


  /* Abort listening to new connections */
  DBUG_PRINT("quit",("Closing sockets"));
unknown's avatar
Merge  
unknown committed
1564
  if (!opt_disable_networking )
unknown's avatar
unknown committed
1565
  {
1566
    if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1567
    {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1568
      (void) mysql_socket_shutdown(base_ip_sock, SHUT_RDWR);
1569 1570
      (void) mysql_socket_close(base_ip_sock);
      base_ip_sock= MYSQL_INVALID_SOCKET;
1571
    }
1572
    if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1573
    {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1574
      (void) mysql_socket_shutdown(extra_ip_sock, SHUT_RDWR);
1575 1576
      (void) mysql_socket_close(extra_ip_sock);
      extra_ip_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1577 1578
    }
  }
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1579
#ifdef _WIN32
unknown's avatar
unknown committed
1580
  if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
unknown's avatar
unknown committed
1581
  {
unknown's avatar
merge  
unknown committed
1582
    HANDLE temp;
unknown's avatar
Merge  
unknown committed
1583
    DBUG_PRINT("quit", ("Closing named pipes") );
1584

unknown's avatar
merge  
unknown committed
1585
    /* Create connection to the handle named pipe handler to break the loop */
1586
    if ((temp = CreateFile(pipe_name,
unknown's avatar
merge  
unknown committed
1587 1588 1589 1590 1591 1592 1593
			   GENERIC_READ | GENERIC_WRITE,
			   0,
			   NULL,
			   OPEN_EXISTING,
			   0,
			   NULL )) != INVALID_HANDLE_VALUE)
    {
1594
      WaitNamedPipe(pipe_name, 1000);
unknown's avatar
merge  
unknown committed
1595 1596 1597 1598 1599 1600
      DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
      SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
      CancelIo(temp);
      DisconnectNamedPipe(temp);
      CloseHandle(temp);
    }
unknown's avatar
unknown committed
1601 1602 1603
  }
#endif
#ifdef HAVE_SYS_UN_H
1604
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1605
  {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1606
    (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR);
1607
    (void) mysql_socket_close(unix_sock);
1608
    (void) unlink(mysqld_unix_port);
1609
    unix_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1610 1611
  }
#endif
1612
  end_thr_alarm(0);			 // Abort old alarms.
unknown's avatar
unknown committed
1613

1614 1615 1616 1617 1618
  /*
    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.
  */
unknown's avatar
unknown committed
1619 1620

  THD *tmp;
Marc Alff's avatar
Marc Alff committed
1621
  mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1622 1623 1624 1625 1626 1627

  I_List_iterator<THD> it(threads);
  while ((tmp=it++))
  {
    DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
		       tmp->thread_id));
1628
    /* We skip slave threads & scheduler on this first loop through. */
1629
    if (tmp->slave_thread)
1630
      continue;
1631

1632 1633 1634 1635 1636
#ifdef WITH_WSREP
    /* skip wsrep system threads as well */
    if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier))
      continue;
#endif
1637
    tmp->killed= KILL_SERVER_HARD;
Sergei Golubchik's avatar
Sergei Golubchik committed
1638
    MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1639
    mysql_mutex_lock(&tmp->LOCK_thd_data);
unknown's avatar
unknown committed
1640 1641 1642
    if (tmp->mysys_var)
    {
      tmp->mysys_var->abort=1;
Marc Alff's avatar
Marc Alff committed
1643
      mysql_mutex_lock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1644
      if (tmp->mysys_var->current_cond)
unknown's avatar
unknown committed
1645
      {
1646 1647 1648
        uint i;
        for (i=0; i < 2; i++)
        {
Sergei Golubchik's avatar
Sergei Golubchik committed
1649 1650
          int ret= mysql_mutex_trylock(tmp->mysys_var->current_mutex);
          mysql_cond_broadcast(tmp->mysys_var->current_cond);
1651 1652 1653
          if (!ret)
          {
            /* Thread has surely got the signal, unlock and abort */
Sergei Golubchik's avatar
Sergei Golubchik committed
1654
            mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1655 1656 1657 1658
            break;
          }
          sleep(1);
        }
unknown's avatar
unknown committed
1659
      }
Marc Alff's avatar
Marc Alff committed
1660
      mysql_mutex_unlock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1661
    }
1662
    mysql_mutex_unlock(&tmp->LOCK_thd_data);
unknown's avatar
unknown committed
1663
  }
Marc Alff's avatar
Marc Alff committed
1664
  mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1665

1666
  Events::deinit();
1667 1668
  end_slave();

1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
  /*
    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.
  */
  for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++)
1684
    my_sleep(20000);
unknown's avatar
unknown committed
1685

1686 1687 1688 1689 1690
  /*
    Force remaining threads to die by closing the connection to the client
    This will ensure that threads that are waiting for a command from the
    client on a blocking read call are aborted.
  */
unknown's avatar
unknown committed
1691 1692 1693 1694

  for (;;)
  {
    DBUG_PRINT("quit",("Locking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1695
    mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1696 1697 1698
    if (!(tmp=threads.get()))
    {
      DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1699
      mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1700 1701 1702
      break;
    }
#ifndef __bsdi__				// Bug in BSDI kernel
1703
    if (tmp->vio_ok())
unknown's avatar
unknown committed
1704
    {
1705
      if (global_system_variables.log_warnings)
1706
        sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1707
                          tmp->thread_id,
1708 1709
                          (tmp->main_security_ctx.user ?
                           tmp->main_security_ctx.user : ""));
Sergei Golubchik's avatar
Sergei Golubchik committed
1710
      close_connection(tmp,ER_SERVER_SHUTDOWN);
unknown's avatar
unknown committed
1711
    }
1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
#endif
#ifdef WITH_WSREP
    /*
     * WSREP_TODO:
     *       this code block may turn out redundant. wsrep->disconnect()
     *       should terminate slave threads gracefully, and we don't need
     *       to signal them here. 
     *       The code here makes sure mysqld will not hang during shutdown
     *       even if wsrep provider has problems in shutting down.
     */
    if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV)
    {
      sql_print_information("closing wsrep system thread");
      tmp->killed= KILL_CONNECTION;
      MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
      if (tmp->mysys_var)
      {
        tmp->mysys_var->abort=1;
        mysql_mutex_lock(&tmp->mysys_var->mutex);
        if (tmp->mysys_var->current_cond)
        {
          mysql_mutex_lock(tmp->mysys_var->current_mutex);
          mysql_cond_broadcast(tmp->mysys_var->current_cond);
          mysql_mutex_unlock(tmp->mysys_var->current_mutex);
        }
        mysql_mutex_unlock(&tmp->mysys_var->mutex);
      }
    }
unknown's avatar
unknown committed
1740 1741
#endif
    DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1742
    mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1743 1744 1745
  }
  /* All threads has now been aborted */
  DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
Marc Alff's avatar
Marc Alff committed
1746
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
1747 1748
  while (thread_count)
  {
Marc Alff's avatar
Marc Alff committed
1749
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
unknown's avatar
unknown committed
1750 1751
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
1752
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1753 1754 1755 1756 1757

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

1758

1759
#ifdef HAVE_CLOSE_SERVER_SOCK
1760
static void close_socket(MYSQL_SOCKET sock, const char *info)
unknown's avatar
unknown committed
1761
{
1762 1763
  DBUG_ENTER("close_socket");

1764
  if (mysql_socket_getfd(sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1765
  {
1766
    DBUG_PRINT("info", ("calling shutdown on %s socket", info));
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1767
    (void) mysql_socket_shutdown(sock, SHUT_RDWR);
unknown's avatar
unknown committed
1768
  }
1769 1770
  DBUG_VOID_RETURN;
}
1771
#endif
1772 1773


1774
static void close_server_sock()
unknown's avatar
unknown committed
1775
{
1776
#ifdef HAVE_CLOSE_SERVER_SOCK
unknown's avatar
unknown committed
1777
  DBUG_ENTER("close_server_sock");
1778 1779 1780 1781 1782

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

1783
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
Konstantin Osipov's avatar
Konstantin Osipov committed
1784
    (void) unlink(mysqld_unix_port);
1785
  base_ip_sock= extra_ip_sock= unix_sock= MYSQL_INVALID_SOCKET;
Sergei Golubchik's avatar
Sergei Golubchik committed
1786

unknown's avatar
unknown committed
1787 1788
  DBUG_VOID_RETURN;
#endif
1789
}
unknown's avatar
unknown committed
1790

1791 1792
#endif /*EMBEDDED_LIBRARY*/

1793

unknown's avatar
unknown committed
1794 1795 1796 1797
void kill_mysql(void)
{
  DBUG_ENTER("kill_mysql");

1798
#if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
1799 1800
  abort_loop=1;					// Break connection loops
  close_server_sock();				// Force accept to wake up
1801
#endif
unknown's avatar
unknown committed
1802

unknown's avatar
unknown committed
1803
#if defined(__WIN__)
unknown's avatar
unknown committed
1804
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
1805 1806 1807 1808 1809
  {
    if (!SetEvent(hEventShutdown))
    {
      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
    }
1810 1811 1812 1813 1814 1815
    /*
      or:
      HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
      SetEvent(hEventShutdown);
      CloseHandle(hEvent);
    */
unknown's avatar
unknown committed
1816
  }
unknown's avatar
unknown committed
1817
#endif
unknown's avatar
unknown committed
1818
#elif defined(HAVE_PTHREAD_KILL)
1819
  if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
unknown's avatar
unknown committed
1820 1821 1822 1823
  {
    DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
  }
#elif !defined(SIGNALS_DONT_BREAK_READ)
1824
  kill(current_pid, MYSQL_KILL_SIGNAL);
unknown's avatar
unknown committed
1825
#endif
unknown's avatar
unknown committed
1826 1827 1828
  DBUG_PRINT("quit",("After pthread_kill"));
  shutdown_in_progress=1;			// Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ
1829
  if (!kill_in_progress)
unknown's avatar
unknown committed
1830 1831
  {
    pthread_t tmp;
1832
    int error;
unknown's avatar
unknown committed
1833
    abort_loop=1;
1834 1835 1836 1837
    if ((error= mysql_thread_create(0, /* Not instrumented */
                                    &tmp, &connection_attrib,
                                    kill_server_thread, (void*) 0)))
      sql_print_error("Can't create thread to kill server (errno= %d).", error);
unknown's avatar
unknown committed
1838
  }
1839
#endif
unknown's avatar
unknown committed
1840
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1841 1842
}

unknown's avatar
unknown committed
1843 1844
/**
  Force server down. Kill all connections and threads and exit.
1845

unknown's avatar
unknown committed
1846
  @param  sig_ptr       Signal number that caused kill_server to be called.
1847

unknown's avatar
unknown committed
1848
  @note
1849 1850 1851 1852
    A signal number of 0 mean that the function was not called
    from a signal handler and there is thus no signal to block
    or stop, we just want to kill the server.
*/
unknown's avatar
unknown committed
1853

1854
#if !defined(__WIN__)
unknown's avatar
unknown committed
1855
static void *kill_server(void *sig_ptr)
1856
#define RETURN_FROM_KILL_SERVER return 0
unknown's avatar
unknown committed
1857 1858
#else
static void __cdecl kill_server(int sig_ptr)
1859
#define RETURN_FROM_KILL_SERVER return
unknown's avatar
unknown committed
1860 1861 1862
#endif
{
  DBUG_ENTER("kill_server");
1863
#ifndef EMBEDDED_LIBRARY
unknown's avatar
Merge  
unknown committed
1864
  int sig=(int) (long) sig_ptr;			// This is passed a int
1865
  // if there is a signal during the kill in progress, ignore the other
unknown's avatar
unknown committed
1866
  if (kill_in_progress)				// Safety
1867 1868
  {
    DBUG_LEAVE;
unknown's avatar
unknown committed
1869
    RETURN_FROM_KILL_SERVER;
1870
  }
unknown's avatar
unknown committed
1871 1872
  kill_in_progress=TRUE;
  abort_loop=1;					// This should be set
1873
  if (sig != 0) // 0 is not a valid signal number
1874
    my_sigset(sig, SIG_IGN);                    /* purify inspected */
unknown's avatar
unknown committed
1875
  if (sig == MYSQL_KILL_SIGNAL || sig == 0)
1876
    sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN),my_progname);
unknown's avatar
unknown committed
1877
  else
1878
    sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
unknown's avatar
unknown committed
1879

Sergei Golubchik's avatar
Sergei Golubchik committed
1880
#ifdef HAVE_SMEM
1881
  /*
Sergei Golubchik's avatar
Sergei Golubchik committed
1882 1883
    Send event to smem_event_connect_request for aborting
  */
1884
  if (opt_enable_shared_memory)
1885
  {
1886 1887 1888 1889 1890 1891
    if (!SetEvent(smem_event_connect_request))
    {
      DBUG_PRINT("error",
                 ("Got error: %ld from SetEvent of smem_event_connect_request",
                  GetLastError()));
    }
1892 1893 1894
  }
#endif

1895 1896 1897
  if (WSREP_ON)
    wsrep_stop_replication(NULL);

unknown's avatar
unknown committed
1898
  close_connections();
1899 1900 1901 1902

  if (wsrep_inited == 1)
    wsrep_deinit(true);

1903 1904
  if (sig != MYSQL_KILL_SIGNAL &&
      sig != 0)
unknown's avatar
unknown committed
1905 1906
    unireg_abort(1);				/* purecov: inspected */
  else
1907
    unireg_end();
unknown's avatar
Merge  
unknown committed
1908

1909
  /* purecov: begin deadcode */
1910
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
1911
  my_thread_end();
1912 1913
  pthread_exit(0);
  /* purecov: end */
unknown's avatar
unknown committed
1914

1915 1916 1917 1918 1919
  RETURN_FROM_KILL_SERVER;                      // Avoid compiler warnings

#else /* EMBEDDED_LIBRARY*/

  DBUG_LEAVE;
unknown's avatar
unknown committed
1920
  RETURN_FROM_KILL_SERVER;
1921 1922

#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1923 1924 1925
}


1926
#if defined(USE_ONE_SIGNAL_HAND)
1927
pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
1928 1929 1930
{
  my_thread_init();				// Initialize new thread
  kill_server(0);
1931 1932 1933
  /* purecov: begin deadcode */
  my_thread_end();
  pthread_exit(0);
unknown's avatar
unknown committed
1934
  return 0;
1935
  /* purecov: end */
unknown's avatar
unknown committed
1936 1937 1938
}
#endif

1939

1940
extern "C" sig_handler print_signal_warning(int sig)
unknown's avatar
unknown committed
1941
{
unknown's avatar
unknown committed
1942
  if (global_system_variables.log_warnings)
1943
    sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
1944
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
1945
  my_sigset(sig,print_signal_warning);		/* int. thread system calls */
unknown's avatar
unknown committed
1946
#endif
1947
#if !defined(__WIN__)
unknown's avatar
unknown committed
1948 1949 1950 1951 1952
  if (sig == SIGALRM)
    alarm(2);					/* reschedule alarm */
#endif
}

unknown's avatar
unknown committed
1953
#ifndef EMBEDDED_LIBRARY
1954

1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966
static void init_error_log_mutex()
{
  mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST);
}


static void clean_up_error_log_mutex()
{
  mysql_mutex_destroy(&LOCK_error_log);
}


unknown's avatar
unknown committed
1967 1968
/**
  cleanup all memory and end program nicely.
unknown's avatar
unknown committed
1969

1970 1971 1972
    If SIGNALS_DONT_BREAK_READ is defined, this function is called
    by the main thread. To get MySQL to shut down nicely in this case
    (Mac OS X) we have to call exit() instead if pthread_exit().
unknown's avatar
unknown committed
1973

unknown's avatar
unknown committed
1974 1975 1976
  @note
    This function never returns.
*/
1977
void unireg_end(void)
unknown's avatar
unknown committed
1978
{
unknown's avatar
unknown committed
1979
  clean_up(1);
unknown's avatar
unknown committed
1980
  my_thread_end();
1981
#if defined(SIGNALS_DONT_BREAK_READ)
1982 1983
  exit(0);
#else
unknown's avatar
unknown committed
1984
  pthread_exit(0);				// Exit is in main thread
1985
#endif
unknown's avatar
unknown committed
1986 1987
}

1988

1989
extern "C" void unireg_abort(int exit_code)
unknown's avatar
unknown committed
1990
{
1991
  DBUG_ENTER("unireg_abort");
1992

1993 1994
  if (opt_help)
    usage();
unknown's avatar
unknown committed
1995 1996
  if (exit_code)
    sql_print_error("Aborting\n");
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009

#ifdef WITH_WSREP
  /* Check if wsrep class is used. If yes, then cleanup wsrep */
  if (wsrep)
  {
    /*
      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);
    shutdown_in_progress= 1;
    wsrep->disconnect(wsrep);
    WSREP_INFO("Service disconnected.");
2010
    wsrep_close_threads(NULL); /* this won't close all threads */
2011 2012 2013 2014 2015 2016 2017 2018 2019
    sleep(1); /* so give some time to exit for those which can */
    WSREP_INFO("Some threads may fail to exit.");

    /* In bootstrap mode we deinitialize wsrep here. */
    if (opt_bootstrap && wsrep_inited)
      wsrep_deinit(true);
  }
#endif // WITH_WSREP

2020
  clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */
2021
  DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
2022 2023 2024 2025 2026
  mysqld_exit(exit_code);
}

static void mysqld_exit(int exit_code)
{
2027
  DBUG_ENTER("mysqld_exit");
2028 2029 2030 2031 2032
  /*
    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.
  */
2033
  rpl_deinit_gtid_waiting();
2034
  rpl_deinit_gtid_slave_state();
2035
  wait_for_signal_thread_to_end();
2036
  mysql_audit_finalize();
unknown's avatar
unknown committed
2037
  clean_up_mutexes();
Marc Alff's avatar
Marc Alff committed
2038
  clean_up_error_log_mutex();
2039
  my_end((opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0));
2040
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
2041
  shutdown_performance_schema();        // we do it as late as possible
2042
#endif
2043
  DBUG_LEAVE;
unknown's avatar
unknown committed
2044 2045
  exit(exit_code); /* purecov: inspected */
}
2046

2047
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
2048

2049
void clean_up(bool print_message)
unknown's avatar
unknown committed
2050 2051 2052 2053
{
  DBUG_PRINT("exit",("clean_up"));
  if (cleanup_done++)
    return; /* purecov: inspected */
unknown's avatar
unknown committed
2054

2055 2056 2057 2058
#ifdef HAVE_REPLICATION
  // We must call end_slave() as clean_up may have been called during startup
  end_slave();
  if (use_slave_mask)
2059
    my_bitmap_free(&slave_error_mask);
2060
#endif
2061
  stop_handle_manager();
2062 2063
  release_ddl_log();

unknown's avatar
unknown committed
2064 2065 2066 2067 2068
  /*
    make sure that handlers finish up
    what they have that is dependent on the binlog
  */
  ha_binlog_end(current_thd);
unknown's avatar
unknown committed
2069 2070 2071

  logger.cleanup_base();

2072
  injector::free_instance();
unknown's avatar
unknown committed
2073 2074
  mysql_bin_log.cleanup();

2075
  my_tz_free();
2076
  my_dboptions_cache_free();
2077
  ignore_db_dirs_free();
unknown's avatar
unknown committed
2078
  servers_free(1);
2079
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
2080 2081
  acl_free(1);
  grant_free();
unknown's avatar
unknown committed
2082
#endif
unknown's avatar
unknown committed
2083
  query_cache_destroy();
unknown's avatar
unknown committed
2084
  hostname_cache_free();
2085
  item_func_sleep_free();
unknown's avatar
unknown committed
2086
  lex_free();				/* Free some memory */
2087
  item_create_cleanup();
unknown's avatar
unknown committed
2088
  if (!opt_noacl)
2089
  {
2090
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
2091
    udf_free();
2092
#endif
2093
  }
2094
  tdc_start_shutdown();
2095
  plugin_shutdown();
2096
  ha_end();
unknown's avatar
Merge  
unknown committed
2097 2098
  if (tc_log)
    tc_log->close();
He Zhenxing's avatar
He Zhenxing committed
2099
  delegates_destroy();
2100
  xid_cache_free();
2101
  tdc_deinit();
Konstantin Osipov's avatar
Konstantin Osipov committed
2102
  mdl_destroy();
2103
  key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
2104
  wt_end();
2105
  multi_keycache_free();
2106
  sp_cache_end();
2107
  free_status_vars();
2108
  end_thr_alarm(1);			/* Free allocated memory */
Monty's avatar
Monty committed
2109 2110 2111
#ifndef EMBEDDED_LIBRARY
  end_thr_timer();
#endif
2112
  my_free_open_file_info();
unknown's avatar
unknown committed
2113 2114
  if (defaults_argv)
    free_defaults(defaults_argv);
unknown's avatar
unknown committed
2115
  free_tmpdir(&mysql_tmpdir_list);
2116
  my_bitmap_free(&temp_pool);
unknown's avatar
unknown committed
2117
  free_max_user_conn();
2118 2119 2120 2121
  free_global_user_stats();
  free_global_client_stats();
  free_global_table_stats();
  free_global_index_stats();
2122
  delete_dynamic(&all_options);
2123
  free_all_rpl_filters();
unknown's avatar
SCRUM  
unknown committed
2124
#ifdef HAVE_REPLICATION
2125
  end_slave_list();
2126
#endif
2127
  my_uuid_end();
unknown's avatar
unknown committed
2128
  delete binlog_filter;
2129
  delete global_rpl_filter;
2130
  end_ssl();
2131
#ifndef EMBEDDED_LIBRARY
2132
  vio_end();
2133
#endif /*!EMBEDDED_LIBRARY*/
2134 2135 2136 2137
#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
2138

2139
  delete_pid_file(MYF(0));
2140

2141
  if (print_message && my_default_lc_messages && server_start_time)
2142 2143
    sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
  cleanup_errmsgs();
Sergei Golubchik's avatar
Sergei Golubchik committed
2144
  MYSQL_CALLBACK(thread_scheduler, end, ());
2145
  mysql_library_end();
unknown's avatar
Merge  
unknown committed
2146
  finish_client_errs();
2147
  (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
2148
  DBUG_PRINT("quit", ("Error messages freed"));
unknown's avatar
unknown committed
2149
  /* Tell main we are ready */
unknown's avatar
unknown committed
2150
  logger.cleanup_end();
2151
  sys_var_end();
2152
  my_atomic_rwlock_destroy(&global_query_id_lock);
2153
  my_atomic_rwlock_destroy(&thread_running_lock);
Michael Widenius's avatar
Michael Widenius committed
2154
  my_atomic_rwlock_destroy(&thread_count_lock);
2155
  my_atomic_rwlock_destroy(&statistics_lock); 
2156
  my_atomic_rwlock_destroy(&slave_executed_entries_lock);
2157
  free_charsets();
Marc Alff's avatar
Marc Alff committed
2158
  mysql_mutex_lock(&LOCK_thread_count);
2159
  DBUG_PRINT("quit", ("got thread count lock"));
unknown's avatar
unknown committed
2160
  ready_to_exit=1;
unknown's avatar
unknown committed
2161
  /* do the broadcast inside the lock to ensure that my_end() is not called */
Marc Alff's avatar
Marc Alff committed
2162 2163
  mysql_cond_broadcast(&COND_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
2164

2165
  free_list(opt_plugin_load_list_ptr);
2166 2167 2168 2169 2170 2171 2172

  if (THR_THD)
    (void) pthread_key_delete(THR_THD);

  if (THR_MALLOC)
    (void) pthread_key_delete(THR_MALLOC);

unknown's avatar
unknown committed
2173 2174 2175 2176
  /*
    The following lines may never be executed as the main thread may have
    killed us
  */
2177
  DBUG_PRINT("quit", ("done with cleanup"));
unknown's avatar
unknown committed
2178 2179 2180
} /* clean_up */


2181 2182
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
2183
/**
2184
  This is mainly needed when running with purify, but it's still nice to
unknown's avatar
unknown committed
2185
  know that all child threads have died when mysqld exits.
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195
*/
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++)
  {
2196
    if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) == ESRCH)
2197 2198 2199 2200
      break;
    my_sleep(100);				// Give it time to die
  }
}
2201
#endif /*EMBEDDED_LIBRARY*/
2202

unknown's avatar
unknown committed
2203 2204
static void clean_up_mutexes()
{
2205
  DBUG_ENTER("clean_up_mutexes");
Marc Alff's avatar
Marc Alff committed
2206
  mysql_rwlock_destroy(&LOCK_grant);
Marc Alff's avatar
Marc Alff committed
2207
  mysql_mutex_destroy(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2208
  mysql_mutex_destroy(&LOCK_thread_cache);
Marc Alff's avatar
Marc Alff committed
2209 2210 2211 2212
  mysql_mutex_destroy(&LOCK_status);
  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
2213 2214 2215
  mysql_mutex_destroy(&LOCK_crypt);
  mysql_mutex_destroy(&LOCK_user_conn);
  mysql_mutex_destroy(&LOCK_connection_count);
Sergei Golubchik's avatar
Sergei Golubchik committed
2216 2217 2218 2219
  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);
2220
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
2221
  mysql_mutex_destroy(&LOCK_des_key_file);
unknown's avatar
unknown committed
2222
#ifndef HAVE_YASSL
2223
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
2224
    mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
2225
  OPENSSL_free(openssl_stdlocks);
Michael Widenius's avatar
Michael Widenius committed
2226 2227
#endif /* HAVE_YASSL */
#endif /* HAVE_OPENSSL */
2228
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
2229
  mysql_mutex_destroy(&LOCK_rpl_status);
Michael Widenius's avatar
Michael Widenius committed
2230
#endif /* HAVE_REPLICATION */
Marc Alff's avatar
Marc Alff committed
2231 2232 2233 2234 2235
  mysql_mutex_destroy(&LOCK_active_mi);
  mysql_rwlock_destroy(&LOCK_sys_init_connect);
  mysql_rwlock_destroy(&LOCK_sys_init_slave);
  mysql_mutex_destroy(&LOCK_global_system_variables);
  mysql_rwlock_destroy(&LOCK_system_variables_hash);
Sergei Golubchik's avatar
Sergei Golubchik committed
2236
  mysql_mutex_destroy(&LOCK_short_uuid_generator);
Marc Alff's avatar
Marc Alff committed
2237 2238
  mysql_mutex_destroy(&LOCK_prepared_stmt_count);
  mysql_mutex_destroy(&LOCK_error_messages);
Marc Alff's avatar
Marc Alff committed
2239 2240 2241
  mysql_cond_destroy(&COND_thread_count);
  mysql_cond_destroy(&COND_thread_cache);
  mysql_cond_destroy(&COND_flush_thread_cache);
Sergei Golubchik's avatar
Sergei Golubchik committed
2242 2243
  mysql_mutex_destroy(&LOCK_server_started);
  mysql_cond_destroy(&COND_server_started);
Sergei Golubchik's avatar
Sergei Golubchik committed
2244
  mysql_mutex_destroy(&LOCK_prepare_ordered);
2245
  mysql_cond_destroy(&COND_prepare_ordered);
Sergei Golubchik's avatar
Sergei Golubchik committed
2246
  mysql_mutex_destroy(&LOCK_commit_ordered);
2247
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2248
}
2249 2250


unknown's avatar
unknown committed
2251 2252 2253 2254
/****************************************************************************
** Init IP and UNIX socket
****************************************************************************/

2255 2256 2257 2258 2259 2260
#ifdef EMBEDDED_LIBRARY
static void set_ports()
{
}

#else
unknown's avatar
unknown committed
2261 2262 2263
static void set_ports()
{
  char	*env;
2264
  if (!mysqld_port && !opt_disable_networking)
unknown's avatar
unknown committed
2265
  {					// Get port if not from commandline
2266
    mysqld_port= MYSQL_PORT;
2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278

    /*
      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
2279
    struct  servent *serv_ptr;
2280 2281
    if ((serv_ptr= getservbyname("mysql", "tcp")))
      mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
2282
#endif
unknown's avatar
unknown committed
2283
    if ((env = getenv("MYSQL_TCP_PORT")))
2284
      mysqld_port= (uint) atoi(env);		/* purecov: inspected */
unknown's avatar
unknown committed
2285
  }
2286
  if (!mysqld_unix_port)
unknown's avatar
unknown committed
2287 2288
  {
#ifdef __WIN__
2289
    mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
unknown's avatar
unknown committed
2290
#else
2291
    mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
unknown's avatar
unknown committed
2292 2293
#endif
    if ((env = getenv("MYSQL_UNIX_PORT")))
2294
      mysqld_unix_port= env;			/* purecov: inspected */
unknown's avatar
unknown committed
2295 2296 2297 2298 2299
  }
}

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

2300
static struct passwd *check_user(const char *user)
unknown's avatar
unknown committed
2301
{
2302
#if !defined(__WIN__)
2303
  struct passwd *tmp_user_info;
2304
  uid_t user_id= geteuid();
unknown's avatar
unknown committed
2305

2306
  // Don't bother if we aren't superuser
2307
  if (user_id)
unknown's avatar
unknown committed
2308 2309
  {
    if (user)
2310
    {
2311 2312 2313 2314
      /* Don't give a warning, if real user is same as given with --user */
      /* purecov: begin tested */
      tmp_user_info= getpwnam(user);
      if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
2315
	  global_system_variables.log_warnings)
2316 2317
        sql_print_warning(
                    "One can only use the --user switch if running as root\n");
unknown's avatar
unknown committed
2318
      /* purecov: end */
2319
    }
2320
    return NULL;
unknown's avatar
unknown committed
2321
  }
2322
  if (!user)
unknown's avatar
unknown committed
2323
  {
2324
    if (!opt_bootstrap && !opt_help)
unknown's avatar
unknown committed
2325
    {
unknown's avatar
unknown committed
2326
      sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
unknown's avatar
unknown committed
2327 2328
      unireg_abort(1);
    }
2329
    return NULL;
unknown's avatar
unknown committed
2330
  }
2331
  /* purecov: begin tested */
unknown's avatar
unknown committed
2332
  if (!strcmp(user,"root"))
unknown's avatar
unknown committed
2333
    return NULL;                        // Avoid problem with dynamic libraries
unknown's avatar
unknown committed
2334

2335
  if (!(tmp_user_info= getpwnam(user)))
unknown's avatar
unknown committed
2336
  {
2337
    // Allow a numeric uid to be used
unknown's avatar
unknown committed
2338
    const char *pos;
unknown's avatar
unknown committed
2339 2340
    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
    if (*pos)                                   // Not numeric id
2341
      goto err;
2342
    if (!(tmp_user_info= getpwuid(atoi(user))))
2343
      goto err;
unknown's avatar
unknown committed
2344
  }
2345

unknown's avatar
unknown committed
2346 2347
  return tmp_user_info;
  /* purecov: end */
2348 2349

err:
unknown's avatar
unknown committed
2350
  sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
2351
  unireg_abort(1);
2352 2353 2354
#endif
  return NULL;
}
2355

2356 2357
static inline void allow_coredumps()
{
2358 2359 2360 2361 2362 2363 2364
#ifdef PR_SET_DUMPABLE
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* inform kernel that process is dumpable */
    (void) prctl(PR_SET_DUMPABLE, 1);
  }
#endif
2365 2366
}

2367

2368
static void set_user(const char *user, struct passwd *user_info_arg)
2369
{
2370
  /* purecov: begin tested */
2371
#if !defined(__WIN__)
2372
  DBUG_ASSERT(user_info_arg != 0);
unknown's avatar
unknown committed
2373
#ifdef HAVE_INITGROUPS
2374 2375 2376 2377 2378 2379
  /*
    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.
  */
2380
  calling_initgroups= 1;
2381
  initgroups((char*) user, user_info_arg->pw_gid);
2382
  calling_initgroups= 0;
unknown's avatar
unknown committed
2383
#endif
2384
  if (setgid(user_info_arg->pw_gid) == -1)
2385 2386 2387
  {
    sql_perror("setgid");
    unireg_abort(1);
unknown's avatar
unknown committed
2388
  }
2389
  if (setuid(user_info_arg->pw_uid) == -1)
unknown's avatar
unknown committed
2390 2391 2392 2393
  {
    sql_perror("setuid");
    unireg_abort(1);
  }
2394
  allow_coredumps();
unknown's avatar
unknown committed
2395
#endif
unknown's avatar
unknown committed
2396
  /* purecov: end */
unknown's avatar
unknown committed
2397 2398
}

unknown's avatar
unknown committed
2399

2400
static void set_effective_user(struct passwd *user_info_arg)
2401
{
2402
#if !defined(__WIN__)
2403 2404
  DBUG_ASSERT(user_info_arg != 0);
  if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
2405
  {
2406
    sql_perror("setregid");
2407
    unireg_abort(1);
unknown's avatar
unknown committed
2408
  }
2409
  if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
2410
  {
2411
    sql_perror("setreuid");
2412 2413
    unireg_abort(1);
  }
2414
  allow_coredumps();
2415 2416 2417 2418
#endif
}


unknown's avatar
unknown committed
2419
/** Change root user if started with @c --chroot . */
unknown's avatar
unknown committed
2420 2421
static void set_root(const char *path)
{
2422
#if !defined(__WIN__)
unknown's avatar
unknown committed
2423 2424 2425 2426 2427
  if (chroot(path) == -1)
  {
    sql_perror("chroot");
    unireg_abort(1);
  }
2428
  my_setwd("/", MYF(0));
unknown's avatar
unknown committed
2429 2430 2431
#endif
}

2432 2433 2434
/**
   Activate usage of a tcp port
*/
2435

2436
static MYSQL_SOCKET activate_tcp_port(uint port)
unknown's avatar
unknown committed
2437
{
Sergei Golubchik's avatar
Sergei Golubchik committed
2438 2439 2440
  struct addrinfo *ai, *a;
  struct addrinfo hints;
  int error;
2441 2442
  int	arg;
  char port_buf[NI_MAXSERV];
2443
  MYSQL_SOCKET ip_sock= MYSQL_INVALID_SOCKET;
2444 2445
  DBUG_ENTER("activate_tcp_port");
  DBUG_PRINT("general",("IP Socket is %d",port));
unknown's avatar
unknown committed
2446

Sergei Golubchik's avatar
Sergei Golubchik committed
2447 2448 2449 2450
  bzero(&hints, sizeof (hints));
  hints.ai_flags= AI_PASSIVE;
  hints.ai_socktype= SOCK_STREAM;
  hints.ai_family= AF_UNSPEC;
unknown's avatar
unknown committed
2451

2452
  my_snprintf(port_buf, NI_MAXSERV, "%d", port);
Sergei Golubchik's avatar
Sergei Golubchik committed
2453 2454
  error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai);
  if (error != 0)
unknown's avatar
unknown committed
2455
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2456 2457 2458 2459
    DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error));
    sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
    unireg_abort(1);				/* purecov: tested */
  }
2460

Sergei Golubchik's avatar
Sergei Golubchik committed
2461 2462
  for (a= ai; a != NULL; a= a->ai_next)
  {
2463 2464
    ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family,
                                 a->ai_socktype, a->ai_protocol);
2465

Sergei Golubchik's avatar
Sergei Golubchik committed
2466
    char ip_addr[INET6_ADDRSTRLEN];
2467 2468 2469 2470 2471 2472
    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
2473
    if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2474 2475 2476 2477 2478 2479 2480 2481 2482 2483
    {
      sql_print_error("Failed to create a socket for %s '%s': errno: %d.",
                      (a->ai_family == AF_INET) ? "IPv4" : "IPv6",
                      (const char *) ip_addr,
                      (int) socket_errno);
    }
    else 
    {
      sql_print_information("Server socket created on IP: '%s'.",
                          (const char *) ip_addr);
Sergei Golubchik's avatar
Sergei Golubchik committed
2484
      break;
2485
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2486
  }
2487

2488
  if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2489 2490
  {
    DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
Sergei Golubchik's avatar
Sergei Golubchik committed
2491
    sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
2492 2493
    unireg_abort(1);				/* purecov: tested */
  }
2494

2495 2496
  mysql_socket_set_thread_owner(ip_sock);

2497
#ifndef __WIN__
2498 2499 2500 2501
  /*
    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
2502
  arg= 1;
2503 2504
  (void) mysql_socket_setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
                                 sizeof(arg));
unknown's avatar
unknown committed
2505
#endif /* __WIN__ */
2506 2507

#ifdef IPV6_V6ONLY
Sergei Golubchik's avatar
Sergei Golubchik committed
2508 2509 2510 2511
   /*
     For interoperability with older clients, IPv6 socket should
     listen on both IPv6 and IPv4 wildcard addresses.
     Turn off IPV6_V6ONLY option.
2512

Sergei Golubchik's avatar
Sergei Golubchik committed
2513 2514 2515 2516 2517 2518 2519
     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;
2520 2521
    (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
                                   (char*)&arg, sizeof(arg));
Sergei Golubchik's avatar
Sergei Golubchik committed
2522
  }
2523
#endif
2524 2525 2526 2527 2528 2529 2530 2531
  /*
    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=#).
  */
2532 2533
  int ret;
  uint waited, retry, this_wait;
2534 2535
  for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
  {
2536
    if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
2537 2538 2539
        (socket_errno != SOCKET_EADDRINUSE) ||
        (waited >= mysqld_port_timeout))
      break;
2540
    sql_print_information("Retrying bind on TCP/IP port %u", port);
2541 2542
    this_wait= retry * retry / 3 + 1;
    sleep(this_wait);
unknown's avatar
unknown committed
2543
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
2544
  freeaddrinfo(ai);
2545 2546
  if (ret < 0)
  {
2547 2548 2549 2550
    char buff[100];
    sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
            (int) socket_errno);
    sql_perror(buff);
2551 2552 2553 2554
    sql_print_error("Do you already have another mysqld server running on "
                    "port: %u ?", port);
    unireg_abort(1);
  }
2555
  if (mysql_socket_listen(ip_sock,(int) back_log) < 0)
2556 2557 2558 2559 2560 2561
  {
    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);
  }
2562 2563 2564 2565

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

2567 2568
  DBUG_RETURN(ip_sock);
}
2569

2570 2571 2572 2573
static void network_init(void)
{
#ifdef HAVE_SYS_UN_H
  struct sockaddr_un	UNIXaddr;
2574
  int	arg;
2575
#endif
unknown's avatar
unknown committed
2576
  DBUG_ENTER("network_init");
unknown's avatar
unknown committed
2577

Sergei Golubchik's avatar
Sergei Golubchik committed
2578
  if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
unknown's avatar
unknown committed
2579 2580
    unireg_abort(1);			/* purecov: inspected */

unknown's avatar
unknown committed
2581 2582
  set_ports();

Sergei Golubchik's avatar
Sergei Golubchik committed
2583
  if (report_port == 0)
unknown's avatar
unknown committed
2584
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2585
    report_port= mysqld_port;
unknown's avatar
unknown committed
2586
  }
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
2587 2588 2589
#ifndef DBUG_OFF
  if (!opt_disable_networking)
    DBUG_ASSERT(report_port != 0);
2590
#endif
2591
  if (!opt_disable_networking && !opt_bootstrap)
unknown's avatar
unknown committed
2592
  {
2593 2594 2595 2596
    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
2597
  }
2598

2599
#ifdef _WIN32
unknown's avatar
unknown committed
2600
  /* create named pipe */
2601
  if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
unknown's avatar
unknown committed
2602
      opt_enable_named_pipe)
unknown's avatar
unknown committed
2603
  {
2604

2605
    strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
2606
	     mysqld_unix_port, NullS);
2607 2608
    bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
    bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
2609
    if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
2610
				      SECURITY_DESCRIPTOR_REVISION))
unknown's avatar
unknown committed
2611 2612 2613 2614 2615 2616 2617 2618 2619
    {
      sql_perror("Can't start server : Initialize security descriptor");
      unireg_abort(1);
    }
    if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
    {
      sql_perror("Can't start server : Set security descriptor");
      unireg_abort(1);
    }
unknown's avatar
Merge  
unknown committed
2620
    saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
unknown's avatar
unknown committed
2621 2622
    saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
    saPipeSecurity.bInheritHandle = FALSE;
2623
    if ((hPipe= CreateNamedPipe(pipe_name,
2624
				PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
2625 2626 2627 2628 2629 2630 2631 2632
				PIPE_TYPE_BYTE |
				PIPE_READMODE_BYTE |
				PIPE_WAIT,
				PIPE_UNLIMITED_INSTANCES,
				(int) global_system_variables.net_buffer_length,
				(int) global_system_variables.net_buffer_length,
				NMPWAIT_USE_DEFAULT_WAIT,
				&saPipeSecurity)) == INVALID_HANDLE_VALUE)
unknown's avatar
unknown committed
2633 2634 2635 2636 2637 2638 2639
      {
	LPVOID lpMsgBuf;
	int error=GetLastError();
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		      FORMAT_MESSAGE_FROM_SYSTEM,
		      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		      (LPTSTR) &lpMsgBuf, 0, NULL );
2640
	sql_perror((char *)lpMsgBuf);
unknown's avatar
Merge  
unknown committed
2641
	LocalFree(lpMsgBuf);
unknown's avatar
unknown committed
2642 2643 2644 2645 2646
	unireg_abort(1);
      }
  }
#endif

2647
#if defined(HAVE_SYS_UN_H)
unknown's avatar
unknown committed
2648 2649 2650
  /*
  ** Create the UNIX socket
  */
2651
  if (mysqld_unix_port[0] && !opt_bootstrap)
unknown's avatar
unknown committed
2652
  {
2653
    DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
unknown's avatar
unknown committed
2654

unknown's avatar
unknown committed
2655 2656
    if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
    {
2657
      sql_print_error("The socket file path is too long (> %u): %s",
unknown's avatar
unknown committed
2658
                      (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unknown's avatar
unknown committed
2659 2660
      unireg_abort(1);
    }
2661 2662
    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
2663 2664 2665 2666
    {
      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
      unireg_abort(1);				/* purecov: inspected */
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2667 2668 2669

    mysql_socket_set_thread_owner(unix_sock);

unknown's avatar
unknown committed
2670 2671
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
2672 2673
    strmov(UNIXaddr.sun_path, mysqld_unix_port);
    (void) unlink(mysqld_unix_port);
2674
    arg= 1;
2675 2676
    (void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,
                                   (char*)&arg, sizeof(arg));
unknown's avatar
unknown committed
2677
    umask(0);
2678 2679 2680
    if (mysql_socket_bind(unix_sock,
                          reinterpret_cast<struct sockaddr *>(&UNIXaddr),
                          sizeof(UNIXaddr)) < 0)
unknown's avatar
unknown committed
2681 2682
    {
      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
2683
      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
unknown's avatar
unknown committed
2684 2685 2686 2687
      unireg_abort(1);					/* purecov: tested */
    }
    umask(((~my_umask) & 0666));
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
2688
    (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
unknown's avatar
unknown committed
2689
#endif
2690
    if (mysql_socket_listen(unix_sock,(int) back_log) < 0)
2691
      sql_print_warning("listen() on Unix socket failed with error %d",
unknown's avatar
unknown committed
2692
		      socket_errno);
2693 2694 2695
#ifdef FD_CLOEXEC
    (void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC);
#endif
unknown's avatar
unknown committed
2696 2697 2698 2699 2700 2701
  }
#endif
  DBUG_PRINT("info",("server started"));
  DBUG_VOID_RETURN;
}

Sergei Golubchik's avatar
Sergei Golubchik committed
2702

unknown's avatar
unknown committed
2703 2704
/**
  Close a connection.
2705

2706 2707
  @param thd        Thread handle.
  @param sql_errno  The error code to send before disconnect.
2708

unknown's avatar
unknown committed
2709
  @note
2710 2711
    For the connection that is doing shutdown, this is called twice
*/
2712
void close_connection(THD *thd, uint sql_errno)
unknown's avatar
unknown committed
2713 2714
{
  DBUG_ENTER("close_connection");
2715 2716 2717 2718

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

Sergei Golubchik's avatar
Sergei Golubchik committed
2719 2720
  thd->print_aborted_warning(3, sql_errno ? ER_DEFAULT(sql_errno)
                                          : "CLOSE_CONNECTION");
2721

2722 2723 2724 2725
  thd->disconnect();

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

2726 2727 2728 2729
  if (MYSQL_CONNECTION_DONE_ENABLED())
  {
    sleep(0); /* Workaround to avoid tailcall optimisation */
  }
2730
  mysql_audit_notify_connection_disconnect(thd, sql_errno);
unknown's avatar
unknown committed
2731 2732
  DBUG_VOID_RETURN;
}
2733 2734
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
2735

2736
/** Called when mysqld is aborted with ^C */
unknown's avatar
unknown committed
2737
/* ARGSUSED */
2738
extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
unknown's avatar
unknown committed
2739
{
2740
  DBUG_ENTER("end_mysqld_signal");
2741 2742
  /* Don't call kill_mysql() if signal thread is not running */
  if (signal_thread_in_use)
Sergei Golubchik's avatar
Sergei Golubchik committed
2743
    kill_mysql();                          // Take down mysqld nicely
unknown's avatar
unknown committed
2744 2745 2746 2747
  DBUG_VOID_RETURN;				/* purecov: deadcode */
}


2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760
/*
  Cleanup THD object

  SYNOPSIS
    thd_cleanup()
    thd		 Thread handler
*/

void thd_cleanup(THD *thd)
{
  thd->cleanup();
}

2761 2762 2763 2764 2765 2766 2767
/*
  Decrease number of connections

  SYNOPSIS
    dec_connection_count()
*/

Sergei Golubchik's avatar
Sergei Golubchik committed
2768
void dec_connection_count(THD *thd)
2769
{
2770 2771 2772 2773 2774 2775 2776 2777 2778 2779
#ifdef WITH_WSREP
  /*
    Do not decrement when its wsrep system thread. wsrep_applier is set for
    applier as well as rollbacker threads.
  */
  if (thd->wsrep_applier)
    return;
#endif /* WITH_WSREP */

  DBUG_ASSERT(*thd->scheduler->connection_count > 0);
2780
  mysql_mutex_lock(&LOCK_connection_count);
Sergei Golubchik's avatar
Sergei Golubchik committed
2781
  (*thd->scheduler->connection_count)--;
2782 2783 2784 2785
  mysql_mutex_unlock(&LOCK_connection_count);
}


Michael Widenius's avatar
Michael Widenius committed
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807
/*
  Delete THD and decrement thread counters, including thread_running
*/

void delete_running_thd(THD *thd)
{
  mysql_mutex_lock(&LOCK_thread_count);
  thd->unlink();
  mysql_mutex_unlock(&LOCK_thread_count);

  delete thd;
  dec_thread_running();
  thread_safe_decrement32(&thread_count, &thread_count_lock);
  if (!thread_count)
  {
    mysql_mutex_lock(&LOCK_thread_count);
    mysql_cond_broadcast(&COND_thread_count);
    mysql_mutex_unlock(&LOCK_thread_count);
  }
}


unknown's avatar
unknown committed
2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819
/*
  Unlink thd from global list of available connections and free thd

  SYNOPSIS
    unlink_thd()
    thd		 Thread handler

  NOTES
    LOCK_thread_count is locked and left locked
*/

void unlink_thd(THD *thd)
unknown's avatar
unknown committed
2820
{
unknown's avatar
unknown committed
2821 2822
  DBUG_ENTER("unlink_thd");
  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
2823

2824
  thd_cleanup(thd);
Sergei Golubchik's avatar
Sergei Golubchik committed
2825
  dec_connection_count(thd);
2826

2827
  thd->add_status_to_global();
2828

Marc Alff's avatar
Marc Alff committed
2829
  mysql_mutex_lock(&LOCK_thread_count);
2830
  thd->unlink();
2831 2832 2833 2834 2835 2836
  /*
    Used by binlog_reset_master.  It would be cleaner to use
    DEBUG_SYNC here, but that's not possible because the THD's debug
    sync feature has been shut down at this point.
  */
  DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
2837 2838
  mysql_mutex_unlock(&LOCK_thread_count);

Michael Widenius's avatar
Michael Widenius committed
2839 2840 2841
  delete thd;
  thread_safe_decrement32(&thread_count, &thread_count_lock);

unknown's avatar
unknown committed
2842 2843 2844
  DBUG_VOID_RETURN;
}

2845

unknown's avatar
unknown committed
2846 2847 2848 2849 2850 2851 2852
/*
  Store thread in cache for reuse by new connections

  SYNOPSIS
    cache_thread()

  NOTES
Michael Widenius's avatar
Michael Widenius committed
2853
    LOCK_thread_cache is used to protect the cache variables
unknown's avatar
unknown committed
2854 2855 2856 2857 2858 2859 2860 2861 2862 2863

  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())
*/


static bool cache_thread()
{
Michael Widenius's avatar
Michael Widenius committed
2864 2865
  DBUG_ENTER("cache_thread");

Michael Widenius's avatar
Michael Widenius committed
2866
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2867
  if (cached_thread_count < thread_cache_size &&
2868
      ! abort_loop && !kill_cached_threads)
unknown's avatar
unknown committed
2869 2870
  {
    /* Don't kill the thread, just put it in cache for reuse */
unknown's avatar
unknown committed
2871
    DBUG_PRINT("info", ("Adding thread to cache"));
unknown's avatar
unknown committed
2872
    cached_thread_count++;
2873

2874
#ifdef HAVE_PSI_THREAD_INTERFACE
2875 2876 2877 2878
    /*
      Delete the instrumentation for the job that just completed,
      before parking this pthread in the cache (blocked on COND_thread_cache).
    */
2879
    PSI_THREAD_CALL(delete_current_thread)();
2880 2881
#endif

unknown's avatar
unknown committed
2882
    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
Michael Widenius's avatar
Michael Widenius committed
2883
      mysql_cond_wait(&COND_thread_cache, &LOCK_thread_cache);
unknown's avatar
unknown committed
2884 2885
    cached_thread_count--;
    if (kill_cached_threads)
Marc Alff's avatar
Marc Alff committed
2886
      mysql_cond_signal(&COND_flush_thread_cache);
unknown's avatar
unknown committed
2887 2888
    if (wake_thread)
    {
unknown's avatar
unknown committed
2889
      THD *thd;
unknown's avatar
unknown committed
2890
      wake_thread--;
unknown's avatar
unknown committed
2891
      thd= thread_cache.get();
Michael Widenius's avatar
Michael Widenius committed
2892 2893
      mysql_mutex_unlock(&LOCK_thread_cache);

2894
      thd->thread_stack= (char*) &thd;          // For store_globals
unknown's avatar
unknown committed
2895
      (void) thd->store_globals();
2896

2897
#ifdef HAVE_PSI_THREAD_INTERFACE
2898 2899 2900 2901
      /*
        Create new instrumentation for the new THD job,
        and attach it to this running pthread.
      */
2902 2903 2904
      PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_one_connection,
                                                   thd, thd->thread_id);
      PSI_THREAD_CALL(set_thread)(psi);
2905 2906
#endif

2907 2908 2909 2910 2911 2912
      /*
        THD::mysys_var::abort is associated with physical thread rather
        than with THD object. So we need to reset this flag before using
        this thread for handling of new THD object/connection.
      */
      thd->mysys_var->abort= 0;
2913
      thd->thr_create_utime= microsecond_interval_timer();
2914
      thd->start_utime= thd->thr_create_utime;
Michael Widenius's avatar
Michael Widenius committed
2915 2916 2917

      /* Link thd into list of all active threads (THD's) */
      mysql_mutex_lock(&LOCK_thread_count);
2918
      threads.append(thd);
Michael Widenius's avatar
Michael Widenius committed
2919
      mysql_mutex_unlock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2920
      DBUG_RETURN(1);
unknown's avatar
unknown committed
2921 2922
    }
  }
Michael Widenius's avatar
Michael Widenius committed
2923
  mysql_mutex_unlock(&LOCK_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2924
  DBUG_RETURN(0);
unknown's avatar
unknown committed
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
}


/*
  End thread for the current connection

  SYNOPSIS
    one_thread_per_connection_end()
    thd		  Thread handler
    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");
2950
  const bool wsrep_applier= IF_WSREP(thd->wsrep_applier, false);
2951

unknown's avatar
unknown committed
2952
  unlink_thd(thd);
2953
  /* Mark that current_thd is not valid anymore */
2954
  set_current_thd(0);
2955

2956
  if (put_in_cache && cache_thread() && !wsrep_applier)
Michael Widenius's avatar
Michael Widenius committed
2957
    DBUG_RETURN(0);                             // Thread is reused
unknown's avatar
unknown committed
2958

Michael Widenius's avatar
Michael Widenius committed
2959 2960 2961 2962 2963 2964 2965
  /*
    It's safe to check for thread_count outside of the mutex
    as we are only interested to see if it was counted to 0 by the
    above unlink_thd() call. We should only signal COND_thread_count if
    thread_count is likely to be 0. (false positives are ok)
  */
  if (!thread_count)
2966 2967
  {
    mysql_mutex_lock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2968 2969
    DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
    mysql_cond_broadcast(&COND_thread_count);
2970 2971
    mysql_mutex_unlock(&LOCK_thread_count);
  }
2972
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2973
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
2974 2975
  ERR_remove_state(0);
#endif
2976
  my_thread_end();
unknown's avatar
unknown committed
2977 2978

  pthread_exit(0);
2979
  return 0;                                     // Avoid compiler warnings
unknown's avatar
unknown committed
2980 2981 2982 2983 2984
}


void flush_thread_cache()
{
Michael Widenius's avatar
Michael Widenius committed
2985 2986
  DBUG_ENTER("flush_thread_cache");
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2987 2988 2989
  kill_cached_threads++;
  while (cached_thread_count)
  {
Marc Alff's avatar
Marc Alff committed
2990
    mysql_cond_broadcast(&COND_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2991
    mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache);
unknown's avatar
unknown committed
2992 2993
  }
  kill_cached_threads--;
Michael Widenius's avatar
Michael Widenius committed
2994 2995
  mysql_mutex_unlock(&LOCK_thread_cache);
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2996 2997 2998 2999
}


/******************************************************************************
3000 3001 3002
  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
3003 3004
******************************************************************************/

3005
#if defined(__WIN__)
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019


/*
  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
3020
#ifndef EMBEDDED_LIBRARY
3021 3022 3023 3024 3025 3026 3027 3028
  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.
     */
3029
#ifndef EMBEDDED_LIBRARY
3030 3031 3032
     if(hEventShutdown)
       kill_mysql();
     else
3033
#endif
3034 3035 3036
       sql_print_warning("CTRL-C ignored during startup");
     DBUG_RETURN(TRUE);
  }
unknown's avatar
unknown committed
3037
#endif
3038 3039 3040 3041 3042 3043 3044 3045 3046
  DBUG_RETURN(FALSE);
}




#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
/*
3047 3048
  Wait for debugger to attach and break into debugger. If debugger is
  not attached, resume after timeout.
3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098
*/
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
  {
3099
    my_set_exception_pointers(ex_pointers);
3100
    handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118
  }
  __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;
}


unknown's avatar
unknown committed
3119 3120
static void init_signals(void)
{
3121 3122
  if(opt_console)
    SetConsoleCtrlHandler(console_event_handler,TRUE);
3123

3124
    /* Avoid MessageBox()es*/
3125 3126 3127 3128 3129 3130
  _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);
3131 3132 3133 3134 3135 3136 3137 3138

   /*
     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)
   */
3139 3140
  SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
                               | SEM_NOOPENFILEERRORBOX);
3141
  SetUnhandledExceptionFilter(my_unhandler_exception_filter);
unknown's avatar
unknown committed
3142 3143
}

unknown's avatar
unknown committed
3144

3145
static void start_signal_handler(void)
3146
{
3147
#ifndef EMBEDDED_LIBRARY
3148 3149 3150
  // Save vm id of this process
  if (!opt_bootstrap)
    create_pid_file();
3151
#endif /* EMBEDDED_LIBRARY */
3152
}
unknown's avatar
unknown committed
3153

unknown's avatar
unknown committed
3154

unknown's avatar
unknown committed
3155 3156
static void check_data_home(const char *path)
{}
3157

3158
#endif /* __WIN__ */
unknown's avatar
unknown committed
3159

unknown's avatar
unknown committed
3160 3161 3162 3163 3164 3165 3166 3167 3168

#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

3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239

/*
  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


3240
#if !defined(__WIN__)
unknown's avatar
unknown committed
3241 3242
#ifndef SA_RESETHAND
#define SA_RESETHAND 0
3243
#endif /* SA_RESETHAND */
unknown's avatar
unknown committed
3244 3245
#ifndef SA_NODEFER
#define SA_NODEFER 0
3246
#endif /* SA_NODEFER */
3247

3248 3249
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
3250 3251 3252
static void init_signals(void)
{
  sigset_t set;
3253
  struct sigaction sa;
unknown's avatar
unknown committed
3254 3255
  DBUG_ENTER("init_signals");

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

Michael Widenius's avatar
Michael Widenius committed
3258
  if (opt_stack_trace || (test_flags & TEST_CORE_ON_SIGNAL))
unknown's avatar
unknown committed
3259
  {
unknown's avatar
unknown committed
3260 3261 3262 3263
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
    sigemptyset(&sa.sa_mask);
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);

3264
    my_init_stacktrace();
unknown's avatar
unknown committed
3265
#if defined(__amiga__)
3266
    sa.sa_handler=(void(*)())handle_fatal_signal;
unknown's avatar
unknown committed
3267
#else
3268
    sa.sa_handler=handle_fatal_signal;
unknown's avatar
unknown committed
3269
#endif
unknown's avatar
unknown committed
3270
    sigaction(SIGSEGV, &sa, NULL);
3271
    sigaction(SIGABRT, &sa, NULL);
unknown's avatar
unknown committed
3272
#ifdef SIGBUS
unknown's avatar
unknown committed
3273
    sigaction(SIGBUS, &sa, NULL);
unknown's avatar
unknown committed
3274
#endif
unknown's avatar
unknown committed
3275
    sigaction(SIGILL, &sa, NULL);
3276
    sigaction(SIGFPE, &sa, NULL);
unknown's avatar
unknown committed
3277
  }
3278 3279 3280 3281 3282

#ifdef HAVE_GETRLIMIT
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* Change limits so that we will get a core file */
3283
    STRUCT_RLIMIT rl;
3284
    rl.rlim_cur = rl.rlim_max = (rlim_t) RLIM_INFINITY;
unknown's avatar
unknown committed
3285
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
3286
      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");
3287 3288
  }
#endif
unknown's avatar
unknown committed
3289
  (void) sigemptyset(&set);
3290
  my_sigset(SIGPIPE,SIG_IGN);
unknown's avatar
unknown committed
3291
  sigaddset(&set,SIGPIPE);
3292
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3293 3294
  sigaddset(&set,SIGQUIT);
  sigaddset(&set,SIGHUP);
3295 3296
#endif
  sigaddset(&set,SIGTERM);
3297 3298

  /* Fix signals if blocked by parents (can happen on Mac OS X) */
unknown's avatar
unknown committed
3299
  sigemptyset(&sa.sa_mask);
3300 3301 3302 3303 3304 3305
  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);
unknown's avatar
unknown committed
3306 3307 3308
#ifdef SIGTSTP
  sigaddset(&set,SIGTSTP);
#endif
3309 3310
  if (thd_lib_detected != THD_LIB_LT)
    sigaddset(&set,THR_SERVER_ALARM);
3311
  if (test_flags & TEST_SIGINT)
3312
  {
3313 3314
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    my_sigset(SIGINT, end_mysqld_signal);
unknown's avatar
unknown committed
3315
    sigdelset(&set, SIGINT);
3316
  }
3317 3318
  else
    sigaddset(&set,SIGINT);
unknown's avatar
unknown committed
3319

3320 3321
  sigprocmask(SIG_SETMASK,&set,NULL);
  pthread_sigmask(SIG_SETMASK,&set,NULL);
3322 3323 3324 3325 3326 3327 3328 3329 3330
  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
3331 3332 3333 3334

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

Marc Alff's avatar
Marc Alff committed
3337
  mysql_mutex_lock(&LOCK_thread_count);
Marc Alff's avatar
Marc Alff committed
3338 3339
  if ((error= mysql_thread_create(key_thread_signal_hand,
                                  &signal_thread, &thr_attr, signal_hand, 0)))
unknown's avatar
unknown committed
3340 3341 3342 3343 3344
  {
    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
		    error,errno);
    exit(1);
  }
Marc Alff's avatar
Marc Alff committed
3345 3346
  mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
3347 3348 3349 3350 3351 3352

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


unknown's avatar
unknown committed
3353
/** This threads handles all signals and alarms. */
unknown's avatar
unknown committed
3354
/* ARGSUSED */
3355
pthread_handler_t signal_hand(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
3356 3357 3358 3359 3360
{
  sigset_t set;
  int sig;
  my_thread_init();				// Init new thread
  DBUG_ENTER("signal_hand");
unknown's avatar
unknown committed
3361 3362
  signal_thread_in_use= 1;

unknown's avatar
unknown committed
3363 3364
  /*
    Setup alarm handler
3365 3366
    This should actually be '+ max_number_of_slaves' instead of +10,
    but the +10 should be quite safe.
unknown's avatar
unknown committed
3367
  */
Sergei Golubchik's avatar
Sergei Golubchik committed
3368
  init_thr_alarm(thread_scheduler->max_threads + extra_max_connections +
3369
		 global_system_variables.max_insert_delayed_threads + 10);
3370
  if (test_flags & TEST_SIGINT)
3371
  {
3372 3373 3374
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    (void) sigemptyset(&set);
    (void) sigaddset(&set,SIGINT);
3375 3376
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
  }
unknown's avatar
unknown committed
3377 3378 3379 3380
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND
  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
#endif
3381
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3382 3383
  (void) sigaddset(&set,SIGQUIT);
  (void) sigaddset(&set,SIGHUP);
3384 3385
#endif
  (void) sigaddset(&set,SIGTERM);
unknown's avatar
unknown committed
3386 3387 3388
  (void) sigaddset(&set,SIGTSTP);

  /* Save pid to this process (or thread on Linux) */
3389
  if (!opt_bootstrap)
3390 3391
    create_pid_file();

3392 3393 3394 3395 3396
  /*
    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.
    At this pointer there is no other threads running, so there
Marc Alff's avatar
Marc Alff committed
3397
    should not be any other mysql_cond_signal() calls.
3398
  */
Marc Alff's avatar
Marc Alff committed
3399 3400 3401
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
3402

3403
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
unknown's avatar
unknown committed
3404 3405 3406 3407 3408
  for (;;)
  {
    int error;					// Used when debugging
    if (shutdown_in_progress && !abort_loop)
    {
3409
      sig= SIGTERM;
unknown's avatar
unknown committed
3410 3411 3412 3413 3414
      error=0;
    }
    else
      while ((error=my_sigwait(&set,&sig)) == EINTR) ;
    if (cleanup_done)
3415
    {
3416
      DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
3417
      my_thread_end();
3418
      DBUG_LEAVE;                               // Must match DBUG_ENTER()
Sergei Golubchik's avatar
Sergei Golubchik committed
3419
      signal_thread_in_use= 0;
unknown's avatar
unknown committed
3420
      pthread_exit(0);				// Safety
3421
      return 0;                                 // Avoid compiler warnings
3422
    }
unknown's avatar
unknown committed
3423 3424 3425 3426 3427
    switch (sig) {
    case SIGTERM:
    case SIGQUIT:
    case SIGKILL:
#ifdef EXTRA_DEBUG
3428
      sql_print_information("Got signal %d to shutdown mysqld",sig);
unknown's avatar
unknown committed
3429
#endif
3430
      /* switch to the old log message processing */
Monty's avatar
Monty committed
3431
      logger.set_handlers(LOG_FILE, global_system_variables.sql_log_slow ? LOG_FILE:LOG_NONE,
3432
                          opt_log ? LOG_FILE:LOG_NONE);
unknown's avatar
unknown committed
3433 3434 3435 3436
      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
      if (!abort_loop)
      {
	abort_loop=1;				// mark abort for threads
3437
#ifdef HAVE_PSI_THREAD_INTERFACE
3438
        /* Delete the instrumentation for the signal thread */
3439
        PSI_THREAD_CALL(delete_current_thread)();
3440
#endif
unknown's avatar
unknown committed
3441 3442
#ifdef USE_ONE_SIGNAL_HAND
	pthread_t tmp;
3443 3444 3445 3446 3447 3448
        if ((error= mysql_thread_create(0, /* Not instrumented */
                                        &tmp, &connection_attrib,
                                        kill_server_thread,
                                        (void*) &sig)))
          sql_print_error("Can't create thread to kill server (errno= %d)",
                          error);
unknown's avatar
unknown committed
3449
#else
unknown's avatar
unknown committed
3450
	kill_server((void*) sig);	// MIT THREAD has a alarm thread
unknown's avatar
unknown committed
3451 3452 3453 3454
#endif
      }
      break;
    case SIGHUP:
unknown's avatar
unknown committed
3455 3456
      if (!abort_loop)
      {
3457
        int not_used;
unknown's avatar
Merge  
unknown committed
3458
	mysql_print_status();		// Print some debug info
unknown's avatar
unknown committed
3459 3460
	reload_acl_and_cache((THD*) 0,
			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
unknown's avatar
Merge  
unknown committed
3461
			      REFRESH_GRANT |
unknown's avatar
unknown committed
3462
			      REFRESH_THREADS | REFRESH_HOSTS),
unknown's avatar
unknown committed
3463
			     (TABLE_LIST*) 0, &not_used); // Flush logs
unknown's avatar
unknown committed
3464
      }
3465
      /* reenable logs after the options were reloaded */
3466 3467 3468
      if (log_output_options & LOG_NONE)
      {
        logger.set_handlers(LOG_FILE,
Monty's avatar
Monty committed
3469 3470
                            global_system_variables.sql_log_slow ?
                            LOG_TABLE : LOG_NONE,
3471 3472 3473 3474 3475
                            opt_log ? LOG_TABLE : LOG_NONE);
      }
      else
      {
        logger.set_handlers(LOG_FILE,
Monty's avatar
Monty committed
3476 3477
                            global_system_variables.sql_log_slow ?
                            log_output_options : LOG_NONE,
3478 3479
                            opt_log ? log_output_options : LOG_NONE);
      }
unknown's avatar
unknown committed
3480 3481 3482 3483 3484 3485 3486 3487
      break;
#ifdef USE_ONE_SIGNAL_HAND
    case THR_SERVER_ALARM:
      process_alarm(sig);			// Trigger alarms.
      break;
#endif
    default:
#ifdef EXTRA_DEBUG
3488
      sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
unknown's avatar
unknown committed
3489 3490 3491 3492 3493 3494 3495
#endif
      break;					/* purecov: tested */
    }
  }
  return(0);					/* purecov: deadcode */
}

unknown's avatar
unknown committed
3496
static void check_data_home(const char *path)
unknown's avatar
unknown committed
3497
{}
unknown's avatar
unknown committed
3498

3499
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
3500 3501 3502
#endif	/* __WIN__*/


unknown's avatar
unknown committed
3503
/**
unknown's avatar
Merge  
unknown committed
3504
  All global error messages are sent here where the first one is stored
unknown's avatar
unknown committed
3505
  for the client.
unknown's avatar
unknown committed
3506 3507
*/
/* ARGSUSED */
Marc Alff's avatar
Marc Alff committed
3508
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3509

Marc Alff's avatar
Marc Alff committed
3510
void my_message_sql(uint error, const char *str, myf MyFlags)
unknown's avatar
unknown committed
3511
{
Marc Alff's avatar
Marc Alff committed
3512
  THD *thd= current_thd;
3513
  Sql_condition::enum_warning_level level;
3514
  sql_print_message_func func;
unknown's avatar
unknown committed
3515
  DBUG_ENTER("my_message_sql");
3516 3517
  DBUG_PRINT("error", ("error: %u  message: '%s'  Flag: %lu", error, str,
                       MyFlags));
3518 3519

  DBUG_ASSERT(str != NULL);
3520
  DBUG_ASSERT(error != 0);
3521

3522 3523
  if (MyFlags & ME_JUST_INFO)
  {
3524
    level= Sql_condition::WARN_LEVEL_NOTE;
3525 3526 3527 3528
    func= sql_print_information;
  }
  else if (MyFlags & ME_JUST_WARNING)
  {
3529
    level= Sql_condition::WARN_LEVEL_WARN;
3530 3531 3532 3533
    func= sql_print_warning;
  }
  else
  {
3534
    level= Sql_condition::WARN_LEVEL_ERROR;
3535 3536
    func= sql_print_error;
  }
3537

Marc Alff's avatar
Marc Alff committed
3538
  if (thd)
unknown's avatar
unknown committed
3539
  {
Marc Alff's avatar
Marc Alff committed
3540 3541
    if (MyFlags & ME_FATALERROR)
      thd->is_fatal_error= 1;
Sergei Golubchik's avatar
Sergei Golubchik committed
3542
    (void) thd->raise_condition(error, NULL, level, str);
unknown's avatar
unknown committed
3543
  }
3544 3545
  else
    mysql_audit_general(0, MYSQL_AUDIT_GENERAL_ERROR, error, str);
3546 3547

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

3550
  if (!thd || thd->log_all_errors || (MyFlags & ME_NOREFRESH))
3551
    (*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
Marc Alff's avatar
Marc Alff committed
3552
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
3553 3554
}

3555

3556 3557
extern "C" void *my_str_malloc_mysqld(size_t size);
extern "C" void my_str_free_mysqld(void *ptr);
3558
extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
3559 3560

void *my_str_malloc_mysqld(size_t size)
3561 3562 3563 3564 3565
{
  return my_malloc(size, MYF(MY_FAE));
}


3566
void my_str_free_mysqld(void *ptr)
3567
{
3568
  my_free(ptr);
3569
}
3570 3571 3572 3573 3574

void *my_str_realloc_mysqld(void *ptr, size_t size)
{
  return my_realloc(ptr, size, MYF(MY_FAE));
}
3575 3576


unknown's avatar
unknown committed
3577 3578
#ifdef __WIN__

3579
pthread_handler_t handle_shutdown(void *arg)
unknown's avatar
unknown committed
3580 3581 3582 3583 3584 3585
{
  MSG msg;
  my_thread_init();

  /* this call should create the message queue for this thread */
  PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
unknown's avatar
unknown committed
3586
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
3587
  if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
3588
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
3589 3590 3591 3592 3593
     kill_server(MYSQL_KILL_SIGNAL);
  return 0;
}
#endif

3594
#include <mysqld_default_groups.h>
unknown's avatar
Merge  
unknown committed
3595

3596
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
3597 3598
static const int load_default_groups_sz=
sizeof(load_default_groups)/sizeof(load_default_groups[0]);
unknown's avatar
Merge  
unknown committed
3599
#endif
unknown's avatar
unknown committed
3600

unknown's avatar
unknown committed
3601

3602
#ifndef EMBEDDED_LIBRARY
3603 3604 3605
/**
  This function is used to check for stack overrun for pathological
  cases of  regular expressions and 'like' expressions.
3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620
*/
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.
3621 3622 3623 3624 3625
  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)
3626
{
3627 3628
  if (recurse_level % 16 != 0)
    return 0;
3629
  return check_enough_stack_size_slow();
3630 3631 3632 3633
}
#endif


3634 3635 3636 3637 3638 3639 3640 3641

/*
   Initialize my_str_malloc() and my_str_free()
*/
static void init_libstrings()
{
  my_str_malloc= &my_str_malloc_mysqld;
  my_str_free= &my_str_free_mysqld;
Alexander Barkov's avatar
Alexander Barkov committed
3642
  my_str_realloc= &my_str_realloc_mysqld;
3643 3644 3645
#ifndef EMBEDDED_LIBRARY
  my_string_stack_guard= check_enough_stack_size;
#endif
3646
}
3647 3648 3649 3650 3651 3652 3653 3654


static void init_pcre()
{
  pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld;
  pcre_free= pcre_stack_free= my_str_free_mysqld;
#ifndef EMBEDDED_LIBRARY
  pcre_stack_guard= check_enough_stack_size_slow;
3655
#endif
3656
}
3657 3658


unknown's avatar
unknown committed
3659 3660
/**
  Initialize one of the global date/time format variables.
3661

unknown's avatar
unknown committed
3662 3663
  @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
3664

unknown's avatar
unknown committed
3665
  @retval
3666
    0 ok
unknown's avatar
unknown committed
3667
  @retval
3668 3669 3670
    1 error
*/

unknown's avatar
unknown committed
3671
static bool init_global_datetime_format(timestamp_type format_type,
3672
                                        DATE_TIME_FORMAT *format)
3673
{
3674 3675 3676 3677 3678
  /*
    Get command line option
    format->format.str is already set by my_getopt
  */
  format->format.length= strlen(format->format.str);
3679

3680
  if (parse_date_time_format(format_type, format))
3681
  {
3682 3683 3684
    fprintf(stderr, "Wrong date/time format specifier: %s\n",
            format->format.str);
    return true;
3685
  }
3686
  return false;
3687 3688
}

unknown's avatar
unknown committed
3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699
SHOW_VAR com_status_vars[]= {
  {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
  {"alter_db",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
  {"alter_db_upgrade",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS},
  {"alter_event",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS},
  {"alter_function",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS},
  {"alter_procedure",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS},
  {"alter_server",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS},
  {"alter_table",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
  {"alter_tablespace",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS},
  {"analyze",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
3700
  {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3701 3702 3703 3704 3705 3706 3707 3708
  {"begin",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
  {"binlog",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS},
  {"call_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS},
  {"change_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
  {"change_master",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
  {"check",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
  {"checksum",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
  {"commit",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
3709
  {"compound_sql",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMPOUND]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3710 3711 3712 3713 3714
  {"create_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
  {"create_event",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS},
  {"create_function",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS},
  {"create_index",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
  {"create_procedure",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS},
3715
  {"create_role",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730
  {"create_server",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS},
  {"create_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
  {"create_trigger",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS},
  {"create_udf",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
  {"create_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
  {"create_view",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS},
  {"dealloc_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
  {"delete",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
  {"delete_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
  {"do",                   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
  {"drop_db",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
  {"drop_event",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS},
  {"drop_function",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
  {"drop_index",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
  {"drop_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS},
3731
  {"drop_role",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3732 3733 3734 3735 3736 3737 3738 3739
  {"drop_server",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS},
  {"drop_table",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
  {"drop_trigger",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS},
  {"drop_user",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
  {"drop_view",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS},
  {"empty_query",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
  {"execute_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
  {"flush",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
3740
  {"get_diagnostics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3741
  {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
3742
  {"grant_role",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764
  {"ha_close",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
  {"ha_open",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
  {"ha_read",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
  {"help",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
  {"insert",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
  {"insert_select",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
  {"install_plugin",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS},
  {"kill",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
  {"load",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
  {"lock_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
  {"optimize",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
  {"preload_keys",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
  {"prepare_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
  {"purge",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
  {"purge_before_date",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
  {"release_savepoint",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
  {"rename_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
  {"rename_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS},
  {"repair",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
  {"replace",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
  {"replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
  {"reset",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
Marc Alff's avatar
Marc Alff committed
3765
  {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3766 3767
  {"revoke",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
  {"revoke_all",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
3768
  {"revoke_role",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3769 3770 3771 3772 3773 3774 3775 3776 3777
  {"rollback",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
  {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
  {"savepoint",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
  {"select",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
  {"set_option",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
  {"show_authors",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS},
  {"show_binlog_events",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
  {"show_binlogs",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
  {"show_charsets",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
3778
  {"show_client_statistics",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CLIENT_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791
  {"show_collations",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
  {"show_contributors",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS},
  {"show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
  {"show_create_event",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS},
  {"show_create_func",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS},
  {"show_create_proc",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS},
  {"show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
  {"show_create_trigger",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS},
  {"show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
  {"show_engine_logs",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS},
  {"show_engine_mutex",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS},
  {"show_engine_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
  {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
3792
  {"show_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
3793
  {"show_explain",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EXPLAIN]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3794 3795 3796 3797 3798 3799
  {"show_fields",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
#ifndef DBUG_OFF
  {"show_function_code",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS},
#endif
  {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
  {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
3800
  {"show_index_statistics",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS},
3801
  {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3802 3803 3804 3805 3806 3807 3808 3809 3810
  {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
  {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
  {"show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
  {"show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
#ifndef DBUG_OFF
  {"show_procedure_code",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS},
#endif
  {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS},
  {"show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3811 3812
  {"show_profile",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS},
  {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS},
3813
  {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3814 3815 3816 3817
  {"show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
  {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
  {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
  {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
3818
  {"show_table_statistics",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3819 3820 3821
  {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
  {"show_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
  {"show_triggers",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
3822
  {"show_user_statistics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3823 3824
  {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
  {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
3825
  {"shutdown",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHUTDOWN]), SHOW_LONG_STATUS},
3826
  {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
3827 3828
  {"start_all_slaves",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_START]), SHOW_LONG_STATUS},
  {"start_slave",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3829 3830 3831 3832
  {"stmt_close",           (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
  {"stmt_execute",         (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
  {"stmt_fetch",           (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
  {"stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3833
  {"stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3834 3835
  {"stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
  {"stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
3836 3837
  {"stop_all_slaves",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_ALL_STOP]), SHOW_LONG_STATUS},
  {"stop_slave",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848
  {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
  {"uninstall_plugin",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS},
  {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
  {"update",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
  {"update_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
  {"xa_commit",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
  {"xa_end",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
  {"xa_prepare",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
  {"xa_recover",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
  {"xa_rollback",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
  {"xa_start",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
3849
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
3850
};
3851

Sergei Golubchik's avatar
Sergei Golubchik committed
3852

3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
#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()
{
  char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]);
  char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
  int record_size= (char*) offsetof(STATUS_VAR, com_stat[1])
                   - (char*) offsetof(STATUS_VAR, com_stat[0]);
  char *ptr;
  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)
  {
    ptr= var->value;
    if ((first_com <= ptr) && (ptr <= last_com))
    {
      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
3909
  /* "statement/abstract/query" can mutate into "statement/sql/..." */
3910 3911 3912 3913 3914
  com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE;
}
#endif


3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931
#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;
  if ((thd= current_thd))
  {
    return thd->thread_id;
  }
  return my_thread_dbug_id();
}
#endif /* SAFEMALLOC */

Sergei Golubchik's avatar
Sergei Golubchik committed
3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957
/* Thread Mem Usage By P.Linux */
extern "C" {
static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific)
{
  /* If thread specific memory */
  if (is_thread_specific)
  {
    THD *thd= current_thd;
    if (mysqld_server_initialized || thd)
    {
      /*
        THD may not be set if we are called from my_net_init() before THD
        thread has started.
        However, this should never happen, so better to assert and
        fix this.
      */
      DBUG_ASSERT(thd);
      if (thd)
      {
        DBUG_PRINT("info", ("memory_used: %lld  size: %lld",
                            (longlong) thd->status_var.memory_used, size));
        thd->status_var.memory_used+= size;
        DBUG_ASSERT((longlong) thd->status_var.memory_used >= 0);
      }
    }
  }
3958 3959 3960
  // workaround for gcc 4.2.4-1ubuntu4 -fPIE (from DEB_BUILD_HARDENING=1)
  int64 volatile * volatile ptr=&global_status_var.memory_used;
  my_atomic_add64(ptr, size);
Sergei Golubchik's avatar
Sergei Golubchik committed
3961 3962 3963
}
}

3964

Marc Alff's avatar
Marc Alff committed
3965
static int init_common_variables()
unknown's avatar
unknown committed
3966
{
unknown's avatar
unknown committed
3967
  umask(((~my_umask) & 0666));
unknown's avatar
unknown committed
3968 3969 3970 3971 3972 3973
  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
3974
  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
Sergei Golubchik's avatar
Sergei Golubchik committed
3975

3976 3977 3978 3979 3980 3981 3982 3983
  if (pthread_key_create(&THR_THD,NULL) ||
      pthread_key_create(&THR_MALLOC,NULL))
  {
    sql_print_error("Can't create thread-keys");
    return 1;
  }

  set_current_thd(0);
Sergei Golubchik's avatar
Sergei Golubchik committed
3984 3985
  set_malloc_size_cb(my_malloc_size_cb_func);

3986
  init_libstrings();
unknown's avatar
unknown committed
3987 3988
  tzset();			// Set tzname

3989
  sf_leaking_memory= 0; // no memory leaks from now on
3990 3991 3992
#ifdef SAFEMALLOC
  sf_malloc_dbug_id= mariadb_dbug_id;
#endif
3993

unknown's avatar
SCRUM  
unknown committed
3994
  max_system_variables.pseudo_thread_id= (ulong)~0;
3995
  server_start_time= flush_status_time= my_time(0);
3996

3997
  global_rpl_filter= new Rpl_filter;
3998
  binlog_filter= new Rpl_filter;
3999
  if (!global_rpl_filter || !binlog_filter)
4000 4001
  {
    sql_perror("Could not allocate replication and binlog filters");
4002
    return 1;
4003 4004
  }

4005 4006
  if (init_thread_environment() ||
      mysql_init_variables())
unknown's avatar
unknown committed
4007
    return 1;
unknown's avatar
unknown committed
4008

4009 4010 4011
  if (ignore_db_dirs_init())
    return 1;

unknown's avatar
unknown committed
4012
#ifdef HAVE_TZNAME
4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025
  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
4026
  strmake_buf(system_time_zone, tz_name);
4027 4028
#endif /* _WIN32 */
#endif /* HAVE_TZNAME */
4029

4030
  /*
unknown's avatar
unknown committed
4031
    We set SYSTEM time zone as reasonable default and
4032 4033 4034 4035 4036
    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
4037

4038 4039 4040
#ifdef HAVE_PSI_INTERFACE
  /*
    Complete the mysql_bin_log initialization.
4041 4042 4043
    Instrumentation keys are known only after the performance schema
    initialization, and can not be set in the MYSQL_BIN_LOG
    constructor (called before main()).
4044 4045 4046 4047
  */
  mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
                             key_BINLOG_update_cond,
                             key_file_binlog,
4048 4049
                             key_file_binlog_index,
                             key_BINLOG_COND_queue_busy);
4050 4051
#endif

unknown's avatar
unknown committed
4052
  /*
4053
    Init mutexes for the global MYSQL_BIN_LOG objects.
unknown's avatar
unknown committed
4054
    As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
4055 4056
    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
4057 4058
  */
  mysql_bin_log.init_pthread_objects();
4059

4060 4061 4062 4063 4064 4065 4066
  /* TODO: remove this when my_time_t is 64 bit compatible */
  if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
  {
    sql_print_error("This MySQL server doesn't support dates later then 2038");
    return 1;
  }

4067 4068
  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
  {
4069 4070 4071 4072
    /*
      Get hostname of computer (used by 'show variables') and as default
      basename for the pid file if --log-basename is not given.
    */
4073 4074
    strmake(glob_hostname, STRING_WITH_LEN("localhost"));
    sql_print_warning("gethostname failed, using '%s' as hostname",
4075
                        glob_hostname);
Sergei Golubchik's avatar
Sergei Golubchik committed
4076
    opt_log_basename= const_cast<char *>("mysql");
4077 4078
  }
  else
Sergei Golubchik's avatar
Sergei Golubchik committed
4079
    opt_log_basename= glob_hostname;
4080

4081
#ifdef WITH_WSREP
4082
  if (wsrep_node_name == 0 || wsrep_node_name[0] == 0)
4083 4084 4085 4086 4087 4088
  {
    my_free((void *)wsrep_node_name);
    wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME));
  }
#endif /* WITH_WSREP */

Sergei Golubchik's avatar
Sergei Golubchik committed
4089
  if (!*pidfile_name)
4090
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
4091 4092
    strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
    strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
4093
  }
unknown's avatar
unknown committed
4094

4095 4096 4097 4098 4099 4100 4101
  /*
    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.
4102 4103 4104 4105

    From MySQL 5.5 onwards, the default storage engine is InnoDB
    (except in the embedded server, where the default continues to
    be MyISAM)
4106
  */
4107
#if defined(WITH_INNOBASE_STORAGE_ENGINE) || defined(WITH_XTRADB_STORAGE_ENGINE)
4108
  default_storage_engine= const_cast<char *>("InnoDB");
4109 4110
#else
  default_storage_engine= const_cast<char *>("MyISAM");
4111
#endif
4112
  default_tmp_storage_engine= NULL;
4113

4114 4115 4116
  /*
    Add server status variables to the dynamic list of
    status variables that is shown by SHOW STATUS.
4117
    Later, in plugin_init, and mysql_install_plugin
4118 4119 4120 4121 4122
    new entries could be added to that list.
  */
  if (add_status_vars(status_vars))
    return 1; // an error was already reported

unknown's avatar
unknown committed
4123 4124 4125 4126 4127
#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

unknown's avatar
unknown committed
4128
    There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
unknown's avatar
unknown committed
4129 4130 4131 4132 4133 4134 4135 4136
    (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
    that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)

      Com_admin_commands       => com_other
      Com_stmt_close           => com_stmt_close
      Com_stmt_execute         => com_stmt_execute
      Com_stmt_fetch           => com_stmt_fetch
      Com_stmt_prepare         => com_stmt_prepare
unknown's avatar
unknown committed
4137
      Com_stmt_reprepare       => com_stmt_reprepare
unknown's avatar
unknown committed
4138 4139 4140
      Com_stmt_reset           => com_stmt_reset
      Com_stmt_send_long_data  => com_stmt_send_long_data

4141 4142 4143
    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
4144
  */
4145
  compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
unknown's avatar
unknown committed
4146
                     SQLCOM_END + 8);
unknown's avatar
unknown committed
4147 4148
#endif

Marc Alff's avatar
Marc Alff committed
4149
  if (get_options(&remaining_argc, &remaining_argv))
4150
    return 1;
4151 4152
  set_server_version();

4153
#ifndef EMBEDDED_LIBRARY
4154
  if (opt_abort && !opt_verbose)
4155 4156 4157
    unireg_abort(0);
#endif /*!EMBEDDED_LIBRARY*/

unknown's avatar
unknown committed
4158 4159 4160
  DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
		     server_version, SYSTEM_TYPE,MACHINE_TYPE));

unknown's avatar
Merge  
unknown committed
4161 4162 4163 4164
#ifdef HAVE_LARGE_PAGES
  /* Initialize large page size */
  if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
  {
4165 4166
      DBUG_PRINT("info", ("Large page set, large_page_size = %d",
                 opt_large_page_size));
unknown's avatar
Merge  
unknown committed
4167 4168 4169
      my_use_large_pages= 1;
      my_large_page_size= opt_large_page_size;
  }
4170 4171 4172 4173 4174 4175 4176 4177
  else
  {
    opt_large_pages= 0;
    /* 
       Either not configured to use large pages or Linux haven't
       been compiled with large page support
    */
  }
unknown's avatar
Merge  
unknown committed
4178
#endif /* HAVE_LARGE_PAGES */
4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
#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;
4195
   size_t max_desired_page_size;
4196
   if (opt_super_large_pages)
4197
     max_desired_page_size= SUPER_LARGE_PAGESIZE;
4198
   else
4199
     max_desired_page_size= LARGE_PAGESIZE;
4200 4201 4202 4203 4204 4205
   nelem = getpagesizes(NULL, 0);
   if (nelem > 0)
   {
     size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
     if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
     {
4206 4207
       size_t max_page_size= 0;
       for (int i= 0; i < nelem; i++)
4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228
       {
         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
4229

unknown's avatar
unknown committed
4230 4231
  /* connections and databases needs lots of files */
  {
4232
    uint files, wanted_files, max_open_files;
4233

4234
    /* MyISAM requires two file handles per table. */
4235
    wanted_files= (10 + max_connections + extra_max_connections +
4236
                   tc_size * 2);
4237 4238 4239 4240 4241 4242 4243 4244 4245 4246
    /*
      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).
    */
4247
    max_open_files= MY_MAX(MY_MAX(wanted_files,
4248
                            (max_connections + extra_max_connections)*5),
4249 4250
                        open_files_limit);
    files= my_set_max_open_files(max_open_files);
4251 4252

    if (files < wanted_files)
unknown's avatar
unknown committed
4253
    {
4254 4255
      if (!open_files_limit)
      {
4256 4257 4258 4259
        /*
          If we have requested too much file handles than we bring
          max_connections in supported bounds.
        */
4260
        max_connections= (ulong) MY_MIN(files-10-TABLE_OPEN_CACHE_MIN*2,
4261 4262
                                     max_connections);
        /*
4263
          Decrease tc_size according to max_connections, but
4264
          not below TABLE_OPEN_CACHE_MIN.  Outer MY_MIN() ensures that we
4265
          never increase tc_size automatically (that could
4266 4267
          happen if max_connections is decreased above).
        */
4268 4269
        tc_size= (ulong) MY_MIN(MY_MAX((files - 10 - max_connections) / 2,
                                       TABLE_OPEN_CACHE_MIN), tc_size);
4270 4271
	DBUG_PRINT("warning",
		   ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
4272
		    files, max_connections, tc_size));
unknown's avatar
unknown committed
4273
	if (global_system_variables.log_warnings)
4274
	  sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
4275
			files, max_connections, tc_size);
4276
      }
unknown's avatar
unknown committed
4277
      else if (global_system_variables.log_warnings)
4278
	sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
unknown's avatar
unknown committed
4279
    }
unknown's avatar
unknown committed
4280
    open_files_limit= files;
unknown's avatar
unknown committed
4281 4282
  }
  unireg_init(opt_specialflag); /* Set up extern variabels */
4283 4284 4285 4286 4287 4288 4289
  if (!(my_default_lc_messages=
        my_locale_by_name(lc_messages)))
  {
    sql_print_error("Unknown locale: '%s'", lc_messages);
    return 1;
  }
  global_system_variables.lc_messages= my_default_lc_messages;
4290 4291
  if (init_errmessage())	/* Read error messages from file */
    return 1;
4292
  init_client_errs();
Sergei Golubchik's avatar
Sergei Golubchik committed
4293
  mysql_library_init(unused,unused,unused); /* for replication */
unknown's avatar
unknown committed
4294
  lex_init();
4295 4296
  if (item_create_init())
    return 1;
unknown's avatar
unknown committed
4297
  item_init();
4298
  init_pcre();
4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325
  /*
    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;
  }

4326 4327
  if (default_collation_name)
  {
unknown's avatar
unknown committed
4328 4329
    CHARSET_INFO *default_collation;
    default_collation= get_charset_by_name(default_collation_name, MYF(0));
unknown's avatar
unknown committed
4330 4331
    if (!default_collation)
    {
4332 4333 4334 4335
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
      buffered_logs.print();
      buffered_logs.cleanup();
#endif
4336
      sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
unknown's avatar
unknown committed
4337 4338 4339
      return 1;
    }
    if (!my_charset_same(default_charset_info, default_collation))
4340
    {
4341
      sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
4342 4343 4344 4345 4346 4347
		      default_collation_name,
		      default_charset_info->csname);
      return 1;
    }
    default_charset_info= default_collation;
  }
4348 4349 4350 4351
  /* Set collactions that depends on the default collation */
  global_system_variables.collation_server=	 default_charset_info;
  global_system_variables.collation_database=	 default_charset_info;
  global_system_variables.collation_connection=  default_charset_info;
4352
  global_system_variables.character_set_results= default_charset_info;
4353
  global_system_variables.character_set_client=  default_charset_info;
4354

4355
  if (!(character_set_filesystem=
unknown's avatar
unknown committed
4356 4357 4358 4359 4360
        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;

4361 4362 4363
  if (!(my_default_lc_time_names=
        my_locale_by_name(lc_time_names_name)))
  {
unknown's avatar
unknown committed
4364
    sql_print_error("Unknown locale: '%s'", lc_time_names_name);
4365 4366 4367
    return 1;
  }
  global_system_variables.lc_time_names= my_default_lc_time_names;
4368

4369
  /* check log options and issue warnings if needed */
4370 4371
  if (opt_log && opt_logname && *opt_logname &&
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4372 4373
    sql_print_warning("Although a path was specified for the "
                      "--log option, log tables are used. "
4374
                      "To enable logging to files use the --log-output option.");
4375

Monty's avatar
Monty committed
4376 4377
  if (global_system_variables.sql_log_slow && opt_slow_logname &&
      *opt_slow_logname &&
4378
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4379
    sql_print_warning("Although a path was specified for the "
Konstantin Osipov's avatar
Konstantin Osipov committed
4380
                      "--log-slow-queries option, log tables are used. "
4381
                      "To enable logging to files use the --log-output=file option.");
4382

Sergei Golubchik's avatar
Sergei Golubchik committed
4383 4384 4385 4386
  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);
4387

4388 4389 4390 4391 4392 4393
#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) */

4394
#if (ENABLE_TEMP_POOL)
4395
  if (use_temp_pool && my_bitmap_init(&temp_pool,0,1024,1))
4396
    return 1;
4397 4398 4399 4400
#else
  use_temp_pool= 0;
#endif

4401
  if (my_dboptions_cache_init())
unknown's avatar
unknown committed
4402 4403
    return 1;

4404 4405 4406 4407 4408 4409
  /*
    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));
4410 4411
  lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
  if (!lower_case_table_names && lower_case_file_system == 1)
4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430
  {
    if (lower_case_table_names_used)
    {
      if (global_system_variables.log_warnings)
	sql_print_warning("\
You have forced lower_case_table_names to 0 through a command-line \
option, even though your file system '%s' is case insensitive.  This means \
that you can corrupt a MyISAM table by accessing it with different cases. \
You should consider changing lower_case_table_names to 1 or 2",
			mysql_real_data_home);
    }
    else
    {
      if (global_system_variables.log_warnings)
	sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
      lower_case_table_names= 2;
    }
  }
  else if (lower_case_table_names == 2 &&
4431
           !(lower_case_file_system= (lower_case_file_system == 1)))
4432 4433 4434 4435 4436 4437 4438 4439
  {
    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);
    lower_case_table_names= 0;
  }
4440 4441
  else
  {
4442
    lower_case_file_system= (lower_case_file_system == 1);
4443
  }
4444 4445 4446 4447 4448 4449

  /* 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);

4450 4451 4452 4453 4454 4455
  if (ignore_db_dirs_process_additions())
  {
    sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
    return 1;
  }

unknown's avatar
unknown committed
4456 4457
  return 0;
}
unknown's avatar
unknown committed
4458

4459 4460

static int init_thread_environment()
unknown's avatar
unknown committed
4461
{
4462
  DBUG_ENTER("init_thread_environment");
Marc Alff's avatar
Marc Alff committed
4463
  mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
Michael Widenius's avatar
Michael Widenius committed
4464
  mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4465
  mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4466
  mysql_mutex_init(key_LOCK_delayed_insert,
Marc Alff's avatar
Marc Alff committed
4467 4468 4469 4470 4471
                   &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
4472 4473 4474 4475 4476
  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
4477
  mysql_mutex_record_order(&LOCK_active_mi, &LOCK_global_system_variables);
Marc Alff's avatar
Marc Alff committed
4478 4479 4480 4481 4482 4483
  mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
                    &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);
4484
  mysql_mutex_init(key_LOCK_uuid_short_generator,
Sergei Golubchik's avatar
Sergei Golubchik committed
4485
                   &LOCK_short_uuid_generator, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4486 4487
  mysql_mutex_init(key_LOCK_connection_count,
                   &LOCK_connection_count, MY_MUTEX_INIT_FAST);
4488 4489 4490 4491 4492 4493 4494
  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
4495 4496
  mysql_mutex_init(key_LOCK_prepare_ordered, &LOCK_prepare_ordered,
                   MY_MUTEX_INIT_SLOW);
4497
  mysql_cond_init(key_COND_prepare_ordered, &COND_prepare_ordered, NULL);
Sergei Golubchik's avatar
Sergei Golubchik committed
4498 4499
  mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered,
                   MY_MUTEX_INIT_SLOW);
4500

4501
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
4502 4503
  mysql_mutex_init(key_LOCK_des_key_file,
                   &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
unknown's avatar
unknown committed
4504 4505 4506 4507
#ifndef HAVE_YASSL
  openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
                                                     sizeof(openssl_lock_t));
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
4508
    mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
unknown's avatar
unknown committed
4509 4510 4511 4512 4513 4514
  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);
  CRYPTO_set_id_callback(openssl_id_function);
#endif
4515
#endif
Marc Alff's avatar
Marc Alff committed
4516 4517 4518
  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);
  mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
Marc Alff's avatar
Marc Alff committed
4519 4520 4521
  mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
  mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
  mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
unknown's avatar
SCRUM  
unknown committed
4522
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
4523
  mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
4524
#endif
Marc Alff's avatar
Marc Alff committed
4525 4526 4527
  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
4528
  sp_cache_init();
4529
#ifdef HAVE_EVENT_SCHEDULER
4530
  Events::init_mutexes();
4531
#endif
4532
  init_show_explain_psi_keys();
unknown's avatar
unknown committed
4533 4534 4535 4536 4537
  /* 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
4538

4539 4540
#ifdef HAVE_REPLICATION
  rpl_init_gtid_slave_state();
4541
  rpl_init_gtid_waiting();
4542 4543
#endif

4544
  DBUG_RETURN(0);
unknown's avatar
unknown committed
4545 4546
}

4547

unknown's avatar
unknown committed
4548
#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
4549
static unsigned long openssl_id_function()
4550
{
4551
  return (unsigned long) pthread_self();
4552
}
4553 4554 4555


static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
4556
{
4557
  openssl_lock_t *lock= new openssl_lock_t;
4558
  mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
4559 4560 4561 4562
  return lock;
}


4563
static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
4564 4565
				    int line)
{
4566
  mysql_rwlock_destroy(&lock->lock);
4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582
  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);
}


4583
static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
4584 4585 4586 4587 4588 4589 4590 4591
			 int line)
{
  int err;
  char const *what;

  switch (mode) {
  case CRYPTO_LOCK|CRYPTO_READ:
    what = "read lock";
4592
    err= mysql_rwlock_rdlock(&lock->lock);
4593 4594 4595
    break;
  case CRYPTO_LOCK|CRYPTO_WRITE:
    what = "write lock";
4596
    err= mysql_rwlock_wrlock(&lock->lock);
4597 4598 4599 4600
    break;
  case CRYPTO_UNLOCK|CRYPTO_READ:
  case CRYPTO_UNLOCK|CRYPTO_WRITE:
    what = "unlock";
4601
    err= mysql_rwlock_unlock(&lock->lock);
4602 4603 4604 4605 4606 4607
    break;
  default:
    /* Unknown locking mode. */
    sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
    abort();
  }
4608
  if (err)
4609
  {
4610
    sql_print_error("Fatal: can't %s OpenSSL lock", what);
4611 4612 4613 4614 4615 4616
    abort();
  }
}
#endif /* HAVE_OPENSSL */


unknown's avatar
unknown committed
4617 4618
static void init_ssl()
{
unknown's avatar
unknown committed
4619
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
4620 4621
  if (opt_use_ssl)
  {
4622 4623
    enum enum_ssl_init_error error= SSL_INITERR_NOERROR;

4624 4625 4626
    /* 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,
4627 4628
					  opt_ssl_cipher, &error,
                                          opt_ssl_crl, opt_ssl_crlpath);
unknown's avatar
Merge  
unknown committed
4629
    DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
4630
    ERR_remove_state(0);
unknown's avatar
unknown committed
4631
    if (!ssl_acceptor_fd)
4632
    {
4633
      sql_print_warning("Failed to setup SSL");
4634
      sql_print_warning("SSL error: %s", sslGetErrString(error));
unknown's avatar
unknown committed
4635
      opt_use_ssl = 0;
4636
      have_ssl= SHOW_OPTION_DISABLED;
4637 4638 4639 4640
    }
  }
  else
  {
4641
    have_ssl= SHOW_OPTION_DISABLED;
unknown's avatar
unknown committed
4642
  }
unknown's avatar
unknown committed
4643 4644
  if (des_key_file)
    load_des_key_file(des_key_file);
unknown's avatar
unknown committed
4645
#endif /* HAVE_OPENSSL && ! EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
4646
}
unknown's avatar
unknown committed
4647

4648

4649 4650 4651
static void end_ssl()
{
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
4652
#ifndef EMBEDDED_LIBRARY
4653 4654 4655 4656 4657
  if (ssl_acceptor_fd)
  {
    free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
    ssl_acceptor_fd= 0;
  }
Konstantin Osipov's avatar
Konstantin Osipov committed
4658
#endif /* ! EMBEDDED_LIBRARY */
4659 4660 4661
#endif /* HAVE_OPENSSL */
}

4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687
#ifdef _WIN32
/**
  Registers a file to be collected when Windows Error Reporting creates a crash 
  report.

  @note only works on Vista and later, since WerRegisterFile() is not available
  on earlier Windows.
*/
#include <werapi.h>
static void add_file_to_crash_report(char *file)
{
  /* Load WerRegisterFile function dynamically.*/
  HRESULT (WINAPI *pWerRegisterFile)(PCWSTR, WER_REGISTER_FILE_TYPE, DWORD)
    =(HRESULT (WINAPI *) (PCWSTR, WER_REGISTER_FILE_TYPE, DWORD))
    GetProcAddress(GetModuleHandle("kernel32"),"WerRegisterFile");

  if (pWerRegisterFile)
  {
    wchar_t wfile[MAX_PATH+1]= {0};
    if (mbstowcs(wfile, file, MAX_PATH) != (size_t)-1)
    {
      pWerRegisterFile(wfile, WerRegFileTypeOther, WER_FILE_ANONYMOUS_DATA);
    }
  }
}
#endif
4688

4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734
#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;
  }

  LEX_STRING name= { engine_name, strlen(engine_name) };
  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;
}

unknown's avatar
unknown committed
4735 4736
static int init_server_components()
{
4737
  DBUG_ENTER("init_server_components");
unknown's avatar
unknown committed
4738 4739 4740 4741
  /*
    We need to call each of these following functions to ensure that
    all things are initialized so that unireg_abort() doesn't fail
  */
4742
  mdl_init();
4743
  if (tdc_init() | hostname_cache_init())
4744
    unireg_abort(1);
unknown's avatar
unknown committed
4745

4746
  query_cache_set_min_res_unit(query_cache_min_res_unit);
unknown's avatar
unknown committed
4747
  query_cache_init();
unknown's avatar
unknown committed
4748
  query_cache_resize(query_cache_size);
4749
  query_cache_result_size_limit(query_cache_limit);
4750
  my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
4751
  setup_fpu();
unknown's avatar
unknown committed
4752
  init_thr_lock();
Monty's avatar
Monty committed
4753 4754 4755 4756 4757 4758 4759 4760
#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

4761
  my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345);
unknown's avatar
SCRUM  
unknown committed
4762
#ifdef HAVE_REPLICATION
4763
  init_slave_list();
4764
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
4765
  wt_init();
unknown's avatar
unknown committed
4766

4767 4768
  /* Setup logs */

4769 4770 4771 4772 4773
  /*
    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.
  */
4774
  if (opt_error_log && !opt_abort)
4775 4776
  {
    if (!log_error_file_ptr[0])
4777
      fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
4778 4779 4780 4781
                MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
    else
      fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
                MY_UNPACK_FILENAME | MY_SAFE_PATH);
4782 4783 4784 4785 4786
    /*
      _ptr may have been set to my_disabled_option or "" if no argument was
      passed, but we need to show the real name in SHOW VARIABLES:
    */
    log_error_file_ptr= log_error_file;
4787
    if (!log_error_file[0])
4788
      opt_error_log= 0;                         // Too long file name
4789 4790
    else
    {
4791
      my_bool res;
4792
#ifndef EMBEDDED_LIBRARY
4793 4794 4795
      res= reopen_fstreams(log_error_file, stdout, stderr);
#else
      res= reopen_fstreams(log_error_file, NULL, stderr);
4796
#endif
4797 4798 4799

      if (!res)
        setbuf(stderr, NULL);
4800 4801 4802 4803 4804

#ifdef _WIN32
      /* Add error log to windows crash reporting. */
      add_file_to_crash_report(log_error_file);
#endif
4805 4806 4807
    }
  }

4808 4809
  /* set up the hook before initializing plugins which may use it */
  error_handler_hook= my_message_sql;
Sergei Golubchik's avatar
Sergei Golubchik committed
4810
  proc_info_hook= set_thd_stage_info;
4811

Marc Alff's avatar
Marc Alff committed
4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823
#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 */

4824 4825 4826 4827 4828 4829 4830 4831 4832
#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

unknown's avatar
unknown committed
4833 4834 4835 4836 4837 4838
  if (xid_cache_init())
  {
    sql_print_error("Out of memory");
    unireg_abort(1);
  }

4839 4840 4841 4842
  /*
    initialize delegates for extension observers, errors have already
    been reported in the function
  */
He Zhenxing's avatar
He Zhenxing committed
4843 4844 4845
  if (delegates_init())
    unireg_abort(1);

unknown's avatar
unknown committed
4846
  /* need to configure logging before initializing storage engines */
Sergei Golubchik's avatar
Sergei Golubchik committed
4847
  if (!opt_bin_log_used && !WSREP_ON)
unknown's avatar
unknown committed
4848
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
4849
    if (opt_log_slave_updates)
4850 4851
      sql_print_warning("You need to use --log-bin to make "
                        "--log-slave-updates work.");
Sergei Golubchik's avatar
Sergei Golubchik committed
4852
    if (binlog_format_used)
4853 4854
      sql_print_warning("You need to use --log-bin to make "
                        "--binlog-format work.");
4855
  }
4856

4857
  /* Check that we have not let the format to unspecified at this point */
4858
  DBUG_ASSERT((uint)global_system_variables.binlog_format <=
4859
              array_elements(binlog_format_names)-1);
4860

unknown's avatar
unknown committed
4861
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
4862 4863
  if (opt_log_slave_updates && replicate_same_server_id)
  {
4864 4865 4866
    if (opt_bin_log)
    {
      sql_print_error("using --replicate-same-server-id in conjunction with \
unknown's avatar
unknown committed
4867 4868
--log-slave-updates is impossible, it would lead to infinite loops in this \
server.");
4869 4870 4871 4872 4873 4874
      unireg_abort(1);
    }
    else
      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
4875
  }
unknown's avatar
unknown committed
4876
#endif
4877

4878 4879
  DBUG_ASSERT(!opt_bin_log || opt_bin_logname);

unknown's avatar
Merge  
unknown committed
4880
  if (opt_bin_log)
4881
  {
4882 4883
    /* Reports an error and aborts, if the --log-bin's path 
       is a directory.*/
4884
    if (opt_bin_logname[0] && 
4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902
        opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
    {
      sql_print_error("Path '%s' is a directory name, please specify \
a file name for --log-bin option", opt_bin_logname);
      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)
    {
      sql_print_error("Path '%s' is a directory name, please specify \
a file name for --log-bin-index option", opt_binlog_index_name);
      unireg_abort(1);
    }

unknown's avatar
Merge  
unknown committed
4903 4904 4905
    char buf[FN_REFLEN];
    const char *ln;
    ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
4906
    if (!opt_bin_logname[0] && !opt_binlog_index_name)
4907 4908
    {
      /*
unknown's avatar
Merge  
unknown committed
4909 4910 4911 4912 4913
        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.
4914
      */
4915 4916 4917 4918
      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
4919
                        "changed! Please use '--log-basename=%s' or "
4920
                        "'--log-bin=%s' to avoid this problem.",
Sergei Golubchik's avatar
Sergei Golubchik committed
4921
                        opt_log_basename, ln);
4922
    }
unknown's avatar
Merge  
unknown committed
4923
    if (ln == buf)
4924
      opt_bin_logname= my_once_strdup(buf, MYF(MY_WME));
4925 4926
  }

4927 4928 4929 4930 4931 4932 4933
    /*
      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
     */
4934
  if (WSREP_ON && !wsrep_recovery) /* WSREP BEFORE SE */
4935 4936 4937 4938
  {
    if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
    {
      wsrep_provider_init(WSREP_NONE);
4939 4940
      if (wsrep_init())
        unireg_abort(1);
4941 4942 4943 4944
    }
    else // full wsrep initialization
    {
      // add basedir/bin to PATH to resolve wsrep script names
4945 4946
      char* const tmp_path= (char*)my_alloca(strlen(mysql_home) +
                                             strlen("/bin") + 1);
4947 4948 4949 4950 4951 4952 4953 4954 4955 4956
      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);
      }
4957
      my_afree(tmp_path);
4958 4959 4960 4961 4962 4963 4964 4965 4966

      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);
      }
    }
  }
4967

4968 4969 4970 4971 4972 4973 4974
  if (opt_bin_log)
  {
    if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
                                      TRUE))
    {
      unireg_abort(1);
    }
4975 4976
  }

4977
  /* call ha_init_key_cache() on all key caches to init them */
4978
  process_key_caches(&ha_init_key_cache, 0);
4979

4980 4981 4982
  init_global_table_stats();
  init_global_index_stats();

4983 4984 4985 4986
  /* Allow storage engine to give real error messages */
  if (ha_init_errors())
    DBUG_RETURN(1);

Marc Alff's avatar
Marc Alff committed
4987
  if (plugin_init(&remaining_argc, remaining_argv,
4988
                  (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
4989
                  (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
4990 4991 4992
  {
    sql_print_error("Failed to initialize plugins.");
    unireg_abort(1);
unknown's avatar
unknown committed
4993
  }
4994
  plugins_are_initialized= TRUE;  /* Don't separate from init function */
unknown's avatar
unknown committed
4995

4996 4997 4998 4999
#ifdef WITH_WSREP
  if (WSREP_ON && wsrep_check_opts())
    global_system_variables.wsrep_on= 0;
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
5000

unknown's avatar
unknown committed
5001
  /* we do want to exit if there are any other unknown options */
Marc Alff's avatar
Marc Alff committed
5002
  if (remaining_argc > 1)
unknown's avatar
unknown committed
5003 5004
  {
    int ho_error;
unknown's avatar
unknown committed
5005
    struct my_option no_opts[]=
unknown's avatar
unknown committed
5006 5007 5008 5009 5010
    {
      {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
5011
      that there are unprocessed options.
unknown's avatar
unknown committed
5012 5013
    */
    my_getopt_skip_unknown= 0;
unknown's avatar
unknown committed
5014

Marc Alff's avatar
Marc Alff committed
5015
    if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
5016
                                  mysqld_get_one_option)))
unknown's avatar
unknown committed
5017
      unireg_abort(ho_error);
Marc Alff's avatar
Marc Alff committed
5018 5019 5020
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
5021
    my_getopt_skip_unknown= TRUE;
unknown's avatar
unknown committed
5022

Marc Alff's avatar
Marc Alff committed
5023
    if (remaining_argc > 1)
unknown's avatar
unknown committed
5024
    {
5025
      fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n",
Marc Alff's avatar
Marc Alff committed
5026
              my_progname, remaining_argv[1]);
unknown's avatar
unknown committed
5027 5028
      unireg_abort(1);
    }
unknown's avatar
unknown committed
5029 5030
  }

5031
  if (opt_abort)
5032 5033
    unireg_abort(0);

unknown's avatar
unknown committed
5034
  /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
5035 5036
  if (!DEFAULT_ERRMSGS[0][0])
    unireg_abort(1);  
unknown's avatar
unknown committed
5037

unknown's avatar
unknown committed
5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064
  /* 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 */
unknown's avatar
unknown committed
5065 5066
    LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
unknown's avatar
unknown committed
5067
    {
5068
      /* purecov: begin inspected */
unknown's avatar
unknown committed
5069 5070
      sql_print_error("CSV engine is not present, falling back to the "
                      "log files");
unknown's avatar
unknown committed
5071
      log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
5072
      /* purecov: end */
unknown's avatar
unknown committed
5073 5074
    }

Monty's avatar
Monty committed
5075 5076 5077
    logger.set_handlers(LOG_FILE,
                        global_system_variables.sql_log_slow ?
                        log_output_options:LOG_NONE,
unknown's avatar
unknown committed
5078 5079 5080
                        opt_log ? log_output_options:LOG_NONE);
  }

5081
  if (init_default_storage_engine(default_storage_engine, table_plugin))
5082
    unireg_abort(1);
5083 5084 5085 5086 5087 5088 5089

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

  if (init_default_storage_engine(default_tmp_storage_engine, tmp_table_plugin))
    unireg_abort(1);

Sergei Golubchik's avatar
Sergei Golubchik committed
5090
#ifdef USE_ARIA_FOR_TMP_TABLES
5091
  if (!ha_storage_engine_is_enabled(maria_hton) && !opt_bootstrap)
5092
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
5093
    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");
5094 5095
    unireg_abort(1);
  }
5096 5097 5098 5099 5100
  internal_tmp_table_max_key_length=   maria_max_key_length();
  internal_tmp_table_max_key_segments= maria_max_key_segments();
#else
  internal_tmp_table_max_key_length=   myisam_max_key_length();
  internal_tmp_table_max_key_segments= myisam_max_key_segments();
5101
#endif
5102

5103 5104 5105 5106 5107 5108 5109
#ifdef WITH_WSREP
  if (WSREP_ON && !opt_bin_log)
  {
    wsrep_emulate_bin_log= 1;
  }
#endif

5110
  tc_log= get_tc_log_implementation();
5111 5112 5113 5114 5115 5116

  WSREP_DEBUG("Initial TC log open: %s",
              (tc_log == &mysql_bin_log) ? "binlog" :
              (tc_log == &tc_log_mmap) ? "mmap" :
              (tc_log == &tc_log_dummy) ? "dummy" : "unknown"
              );
unknown's avatar
unknown committed
5117

unknown's avatar
unknown committed
5118
  if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
unknown's avatar
Merge  
unknown committed
5119 5120 5121 5122 5123
  {
    sql_print_error("Can't init tc log");
    unireg_abort(1);
  }

unknown's avatar
unknown committed
5124 5125 5126 5127 5128
  if (ha_recover(0))
  {
    unireg_abort(1);
  }

unknown's avatar
Merge  
unknown committed
5129
  if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
5130
                                        WRITE_CACHE, max_binlog_size, 0, TRUE))
unknown's avatar
unknown committed
5131
    unireg_abort(1);
unknown's avatar
Merge  
unknown committed
5132 5133 5134

#ifdef HAVE_REPLICATION
  if (opt_bin_log && expire_logs_days)
5135
  {
5136
    time_t purge_time= server_start_time - expire_logs_days*24*60*60;
unknown's avatar
Merge  
unknown committed
5137 5138
    if (purge_time >= 0)
      mysql_bin_log.purge_logs_before_date(purge_time);
5139
  }
unknown's avatar
Merge  
unknown committed
5140 5141 5142 5143
#endif

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

unknown's avatar
unknown committed
5145
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
5146
  if (locked_in_memory && !getuid())
5147
  {
5148
    if (setreuid((uid_t)-1, 0) == -1)
5149
    {                        // this should never happen
5150
      sql_perror("setreuid");
5151 5152
      unireg_abort(1);
    }
5153 5154
    if (mlockall(MCL_CURRENT))
    {
5155
      if (global_system_variables.log_warnings)
5156
	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
unknown's avatar
unknown committed
5157
      locked_in_memory= 0;
5158
    }
5159 5160
    if (user_info)
      set_user(mysqld_user, user_info);
5161
  }
unknown's avatar
unknown committed
5162
  else
5163
#endif
unknown's avatar
unknown committed
5164
    locked_in_memory=0;
5165

5166
  ft_init_stopwords();
unknown's avatar
unknown committed
5167

unknown's avatar
unknown committed
5168
  init_max_user_conn();
5169
  init_update_queries();
5170 5171
  init_global_user_stats();
  init_global_client_stats();
5172 5173
  if (!opt_bootstrap)
    servers_init(0);
5174
  DBUG_RETURN(0);
unknown's avatar
unknown committed
5175
}
unknown's avatar
unknown committed
5176

5177

5178
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
5179

unknown's avatar
unknown committed
5180 5181 5182
static void create_shutdown_thread()
{
#ifdef __WIN__
5183 5184
  hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
  pthread_t hThread;
5185 5186 5187 5188 5189 5190
  int error;
  if ((error= mysql_thread_create(key_thread_handle_shutdown,
                                  &hThread, &connection_attrib,
                                  handle_shutdown, 0)))
    sql_print_warning("Can't create thread to handle shutdown requests"
                      " (errno= %d)", error);
unknown's avatar
unknown committed
5191

5192 5193
  // On "Stop Service" we have to do regular shutdown
  Service.SetShutdownEvent(hEventShutdown);
unknown's avatar
unknown committed
5194
#endif /* __WIN__ */
unknown's avatar
unknown committed
5195
}
unknown's avatar
unknown committed
5196

5197
#endif /* EMBEDDED_LIBRARY */
5198 5199


Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
5200
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
5201
static void handle_connections_methods()
unknown's avatar
unknown committed
5202
{
5203
  pthread_t hThread;
5204
  int error;
5205
  DBUG_ENTER("handle_connections_methods");
unknown's avatar
unknown committed
5206
  if (hPipe == INVALID_HANDLE_VALUE &&
5207 5208
      (!have_tcpip || opt_disable_networking) &&
      !opt_enable_shared_memory)
unknown's avatar
unknown committed
5209
  {
unknown's avatar
unknown committed
5210
    sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
5211
    unireg_abort(1);				// Will not return
unknown's avatar
unknown committed
5212
  }
5213

Marc Alff's avatar
Marc Alff committed
5214 5215
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
5216 5217
  handler_count=0;
  if (hPipe != INVALID_HANDLE_VALUE)
unknown's avatar
unknown committed
5218
  {
5219
    handler_count++;
5220 5221 5222
    if ((error= mysql_thread_create(key_thread_handle_con_namedpipes,
                                    &hThread, &connection_attrib,
                                    handle_connections_namedpipes, 0)))
unknown's avatar
unknown committed
5223
    {
5224 5225
      sql_print_warning("Can't create thread to handle named pipes"
                        " (errno= %d)", error);
5226 5227 5228 5229 5230 5231
      handler_count--;
    }
  }
  if (have_tcpip && !opt_disable_networking)
  {
    handler_count++;
5232 5233 5234
    if ((error= mysql_thread_create(key_thread_handle_con_sockets,
                                    &hThread, &connection_attrib,
                                    handle_connections_sockets_thread, 0)))
5235
    {
5236 5237
      sql_print_warning("Can't create thread to handle TCP/IP",
                        " (errno= %d)", error);
5238 5239 5240 5241 5242 5243 5244
      handler_count--;
    }
  }
#ifdef HAVE_SMEM
  if (opt_enable_shared_memory)
  {
    handler_count++;
5245 5246 5247
    if ((error= mysql_thread_create(key_thread_handle_con_sharedmem,
                                    &hThread, &connection_attrib,
                                    handle_connections_shared_memory, 0)))
5248
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
5249 5250
      sql_print_warning("Can't create thread to handle shared memory",
                        " (errno= %d)", error);
5251
      handler_count--;
unknown's avatar
unknown committed
5252 5253
    }
  }
5254
#endif
unknown's avatar
unknown committed
5255

5256
  while (handler_count > 0)
Marc Alff's avatar
Marc Alff committed
5257 5258
    mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
5259 5260
  DBUG_VOID_RETURN;
}
5261 5262 5263

void decrement_handler_count()
{
Marc Alff's avatar
Marc Alff committed
5264
  mysql_mutex_lock(&LOCK_thread_count);
5265
  handler_count--;
Marc Alff's avatar
Marc Alff committed
5266 5267
  mysql_cond_signal(&COND_handler_count);
  mysql_mutex_unlock(&LOCK_thread_count);
5268
  my_thread_end();
5269 5270 5271
}
#else
#define decrement_handler_count()
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
5272
#endif /* defined(_WIN32) || defined(HAVE_SMEM) */
5273 5274


5275
#ifndef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301

LEX_STRING sql_statement_names[(uint) SQLCOM_END + 1];

static void init_sql_statement_names()
{
  char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]);
  char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
  int record_size= (char*) offsetof(STATUS_VAR, com_stat[1])
                   - (char*) offsetof(STATUS_VAR, com_stat[0]);
  char *ptr;
  uint i;
  uint com_index;

  for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
    sql_statement_names[i]= empty_lex_str;

  SHOW_VAR *var= &com_status_vars[0];
  while (var->name != NULL)
  {
    ptr= var->value;
    if ((first_com <= ptr) && (ptr <= last_com))
    {
      com_index= ((int)(ptr - first_com))/record_size;
      DBUG_ASSERT(com_index < (uint) SQLCOM_END);
      sql_statement_names[com_index].str= const_cast<char *>(var->name);
      sql_statement_names[com_index].length= strlen(var->name);
unknown's avatar
unknown committed
5302
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
5303
    var++;
unknown's avatar
unknown committed
5304
  }
unknown's avatar
unknown committed
5305

Sergei Golubchik's avatar
Sergei Golubchik committed
5306 5307
  DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SELECT].str, "select") == 0);
  DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SIGNAL].str, "signal") == 0);
5308

Sergei Golubchik's avatar
Sergei Golubchik committed
5309
  sql_statement_names[(uint) SQLCOM_END].str= const_cast<char*>("error");
5310
}
5311

5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348
#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++)
  {
    uint max_month_len= 0;
    uint max_day_len = 0;
    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

5349

unknown's avatar
unknown committed
5350 5351 5352
#ifdef __WIN__
int win_main(int argc, char **argv)
#else
5353
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5354 5355
#endif
{
Marc Alff's avatar
Marc Alff committed
5356 5357 5358 5359 5360
  /*
    Perform basic thread library and malloc initialization,
    to be able to read defaults files and parse options.
  */
  my_progname= argv[0];
5361
  sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early
5362 5363
  mysqld_server_started= mysqld_server_initialized= 0;

5364 5365 5366
#ifdef HAVE_NPTL
  ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
#endif
5367 5368 5369
#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
5370
  {
5371
    fprintf(stderr, "my_init() failed.");
Marc Alff's avatar
Marc Alff committed
5372 5373
    return 1;
  }
5374
#endif
5375

Marc Alff's avatar
Marc Alff committed
5376 5377
  orig_argc= argc;
  orig_argv= argv;
5378
  my_getopt_use_args_separator= TRUE;
Marc Alff's avatar
Marc Alff committed
5379 5380
  if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
    return 1;
5381
  my_getopt_use_args_separator= FALSE;
Marc Alff's avatar
Marc Alff committed
5382 5383 5384 5385 5386 5387 5388 5389
  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;

5390
  init_sql_statement_names();
Marc Alff's avatar
Marc Alff committed
5391 5392
  sys_var_init();

5393
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5394
  /*
5395
    Initialize the array of performance schema instrument configurations.
Marc Alff's avatar
Marc Alff committed
5396
  */
5397 5398
  init_pfs_instrument_array();
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
Marc Alff's avatar
Marc Alff committed
5399 5400 5401 5402 5403 5404
  /*
    Logs generated while parsing the command line
    options are buffered and printed later.
  */
  buffered_logs.init();
  my_getopt_error_reporter= buffered_option_error_reporter;
5405
  my_charset_error_reporter= buffered_option_error_reporter;
5406
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5407
  pfs_param.m_pfs_instrument= const_cast<char*>("");
5408
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5409

5410
  int ho_error __attribute__((unused))= handle_early_options();
Marc Alff's avatar
Marc Alff committed
5411

5412
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5413 5414
  if (ho_error == 0)
  {
5415
    if (pfs_param.m_enabled  && !opt_help && !opt_bootstrap)
Marc Alff's avatar
Marc Alff committed
5416
    {
5417
      /* Add sizing hints from the server sizing parameters. */
5418 5419
      pfs_param.m_hints.m_table_definition_cache= tdc_size;
      pfs_param.m_hints.m_table_open_cache= tc_size;
5420 5421
      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
5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449
      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)
  {
5450 5451 5452 5453
    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
5454

5455 5456 5457 5458 5459 5460 5461
      /*
        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 */
5462 5463
      PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_main, NULL, 0);
      PSI_THREAD_CALL(set_thread)(psi);
5464 5465 5466 5467 5468 5469 5470 5471

      /*
        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
5472 5473 5474 5475
  }
#endif /* HAVE_PSI_INTERFACE */

  init_error_log_mutex();
5476

5477 5478 5479
  /* Initialize audit interface globals. Audit plugins are inited later. */
  mysql_audit_initialize();

5480 5481 5482 5483 5484 5485
  /*
    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
5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507
#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
5508
#ifdef _CUSTOMSTARTUPCONFIG_
unknown's avatar
unknown committed
5509 5510 5511
  if (_cust_check_startup())
  {
    / * _cust_check_startup will report startup failure error * /
unknown's avatar
Merge  
unknown committed
5512
    exit(1);
unknown's avatar
unknown committed
5513 5514
  }
#endif
unknown's avatar
unknown committed
5515

Marc Alff's avatar
Marc Alff committed
5516
  if (init_common_variables())
5517
    unireg_abort(1);				// Will do exit
unknown's avatar
unknown committed
5518 5519

  init_signals();
5520 5521 5522

  my_thread_stack_size= my_setstacksize(&connection_attrib,
                                        my_thread_stack_size);
unknown's avatar
unknown committed
5523

5524
  (void) thr_setconcurrency(concurrency);	// 10 by default
unknown's avatar
unknown committed
5525

5526 5527
  select_thread=pthread_self();
  select_thread_in_use=1;
unknown's avatar
unknown committed
5528 5529 5530 5531 5532 5533

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

5534 5535
#ifndef DBUG_OFF
  test_lc_time_sz();
5536
  srand((uint) time(NULL)); 
5537 5538
#endif

unknown's avatar
unknown committed
5539 5540 5541
  /*
    We have enough space for fiddling with the argv, continue
  */
unknown's avatar
unknown committed
5542
  check_data_home(mysql_real_data_home);
5543
  if (my_setwd(mysql_real_data_home, opt_abort ? 0 : MYF(MY_WME)) && !opt_abort)
unknown's avatar
unknown committed
5544
    unireg_abort(1);				/* purecov: inspected */
unknown's avatar
unknown committed
5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555

  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);
  }

5556
  if (opt_bin_log && !global_system_variables.server_id)
unknown's avatar
unknown committed
5557
  {
5558
    global_system_variables.server_id= ::server_id= 1;
unknown's avatar
unknown committed
5559
#ifdef EXTRA_DEBUG
5560 5561 5562 5563
    sql_print_warning("You have enabled the binary log, but you haven't set "
                      "server-id to a non-zero value: we force server id to 1; "
                      "updates will be logged to the binary log, but "
                      "connections from slaves will not be accepted.");
5564
#endif
unknown's avatar
unknown committed
5565 5566
  }

5567 5568 5569 5570 5571 5572 5573 5574
  /* 
   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
5575
  if (init_server_components())
unknown's avatar
unknown committed
5576
    unireg_abort(1);
unknown's avatar
unknown committed
5577

5578
  init_ssl();
unknown's avatar
unknown committed
5579 5580
  network_init();

unknown's avatar
unknown committed
5581 5582 5583
#ifdef __WIN__
  if (!opt_console)
  {
5584 5585
    if (reopen_fstreams(log_error_file, stdout, stderr))
      unireg_abort(1);
5586
    setbuf(stderr, NULL);
unknown's avatar
unknown committed
5587
    FreeConsole();				// Remove window
5588
  }
unknown's avatar
unknown committed
5589 5590
#endif

5591 5592 5593 5594 5595 5596 5597
  if (WSREP_ON && wsrep_recovery)
  {
    select_thread_in_use= 0;
    wsrep_recover();
    unireg_abort(0);
  }

unknown's avatar
unknown committed
5598 5599 5600 5601 5602
  /*
    init signals & alarm
    After this we can't quit by a simple unireg_abort
  */
  start_signal_handler();				// Creates pidfile
5603

5604
  if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
5605
      my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
unknown's avatar
unknown committed
5606 5607 5608
  {
    abort_loop=1;
    select_thread_in_use=0;
5609

unknown's avatar
unknown committed
5610
    (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
5611

5612
    delete_pid_file(MYF(MY_WME));
5613

5614
    if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
5615
      unlink(mysqld_unix_port);
unknown's avatar
unknown committed
5616 5617
    exit(1);
  }
5618

unknown's avatar
unknown committed
5619
  if (!opt_noacl)
5620
    (void) grant_init();
unknown's avatar
unknown committed
5621 5622

  if (!opt_noacl)
5623 5624
  {
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
5625 5626
    udf_init();
#endif
5627
  }
5628

5629
  init_status_vars();
unknown's avatar
unknown committed
5630 5631
  if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
    opt_skip_slave_start= 1;
5632 5633

  binlog_unsafe_map_init();
5634

Marc Alff's avatar
Marc Alff committed
5635 5636 5637 5638 5639 5640
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  initialize_performance_schema_acl(opt_bootstrap);
#endif

  initialize_information_schema_acl();

5641 5642 5643 5644 5645
  execute_ddl_log_recovery();

  if (Events::init(opt_noacl || opt_bootstrap))
    unireg_abort(1);

5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671
  if (WSREP_ON)
  {
    if (opt_bootstrap)
    {
      /*! bootstrap wsrep init was taken care of above */
    }
    else
    {
      wsrep_SE_initialized();

      if (wsrep_before_SE())
      {
        /*! in case of no SST wsrep waits in view handler callback */
        wsrep_SE_init_grab();
        wsrep_SE_init_done();
        /*! in case of SST wsrep waits for wsrep->sst_received */
        wsrep_sst_continue();
      }
      else
      {
        wsrep_init_startup (false);
      }

      wsrep_create_appliers(wsrep_slave_threads - 1);
    }
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
5672 5673
  else
    wsrep_init_startup (false);
5674

5675
 if (opt_bootstrap)
unknown's avatar
unknown committed
5676
  {
5677
    select_thread_in_use= 0;                    // Allow 'kill' to work
Marc Alff's avatar
Marc Alff committed
5678
    bootstrap(mysql_stdin);
5679 5680 5681 5682 5683 5684 5685
    if (!kill_in_progress)
      unireg_abort(bootstrap_error ? 1 : 0);
    else
    {
      sleep(2);                                 // Wait for kill
      exit(0);
    }
unknown's avatar
unknown committed
5686
  }
5687

5688 5689 5690
  /* It's now safe to use thread specific memory */
  mysqld_server_initialized= 1;

5691 5692 5693
  create_shutdown_thread();
  start_handle_manager();

5694 5695 5696
  /* Copy default global rpl_filter to global_rpl_filter */
  copy_filter_setting(global_rpl_filter, get_or_create_rpl_filter("", 0));

5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707
  /*
    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);
  }

5708
  if (opt_init_file && *opt_init_file)
unknown's avatar
unknown committed
5709 5710 5711 5712
  {
    if (read_init_file(opt_init_file))
      unireg_abort(1);
  }
unknown's avatar
unknown committed
5713

5714
  sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version,
5715 5716
                        ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
                         (char*) "" : mysqld_unix_port),
unknown's avatar
unknown committed
5717
                         mysqld_port,
unknown's avatar
Merge  
unknown committed
5718
                         MYSQL_COMPILATION_COMMENT);
5719 5720 5721
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetRunning();
#endif
unknown's avatar
unknown committed
5722

unknown's avatar
unknown committed
5723
  /* Signal threads waiting for server to be started */
Marc Alff's avatar
Marc Alff committed
5724
  mysql_mutex_lock(&LOCK_server_started);
unknown's avatar
unknown committed
5725
  mysqld_server_started= 1;
Marc Alff's avatar
Marc Alff committed
5726 5727
  mysql_cond_signal(&COND_server_started);
  mysql_mutex_unlock(&LOCK_server_started);
unknown's avatar
unknown committed
5728

5729
#if defined(_WIN32) || defined(HAVE_SMEM)
5730
  handle_connections_methods();
unknown's avatar
unknown committed
5731
#else
5732 5733
  handle_connections_sockets();
#endif /* _WIN32 || HAVE_SMEM */
unknown's avatar
unknown committed
5734 5735

  /* (void) pthread_attr_destroy(&connection_attrib); */
5736

unknown's avatar
unknown committed
5737 5738 5739
  DBUG_PRINT("quit",("Exiting main thread"));

#ifndef __WIN__
unknown's avatar
unknown committed
5740
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
5741 5742
  sql_print_error("Before Lock_thread_count");
#endif
5743
  WSREP_DEBUG("Before Lock_thread_count");
Marc Alff's avatar
Marc Alff committed
5744
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
5745
  DBUG_PRINT("quit", ("Got thread_count mutex"));
unknown's avatar
unknown committed
5746
  select_thread_in_use=0;			// For close_connections
Marc Alff's avatar
Marc Alff committed
5747 5748
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
5749
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
5750 5751
  sql_print_error("After lock_thread_count");
#endif
unknown's avatar
merge  
unknown committed
5752
#endif /* __WIN__ */
5753

5754
#ifdef HAVE_PSI_THREAD_INTERFACE
5755 5756 5757 5758
  /*
    Disable the main thread instrumentation,
    to avoid recording events during the shutdown.
  */
5759
  PSI_THREAD_CALL(delete_current_thread)();
5760 5761
#endif

unknown's avatar
unknown committed
5762
  /* Wait until cleanup is done */
Marc Alff's avatar
Marc Alff committed
5763
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
5764
  while (!ready_to_exit)
Marc Alff's avatar
Marc Alff committed
5765 5766
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
merge  
unknown committed
5767 5768

#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
merge  
unknown committed
5769 5770 5771 5772
  if (Service.IsNT() && start_mode)
    Service.Stop();
  else
  {
unknown's avatar
unknown committed
5773
    Service.SetShutdownEvent(0);
unknown's avatar
merge  
unknown committed
5774 5775 5776
    if (hEventShutdown)
      CloseHandle(hEventShutdown);
  }
unknown's avatar
unknown committed
5777
#endif
5778
  mysqld_exit(0);
5779
  return 0;
unknown's avatar
unknown committed
5780 5781
}

5782
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
5783

unknown's avatar
SCRUM  
unknown committed
5784

5785 5786 5787 5788 5789
/****************************************************************************
  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
5790
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
5791 5792
int mysql_service(void *p)
{
5793 5794 5795
  if (my_thread_init())
    return 1;
  
5796 5797 5798 5799
  if (use_opt_args)
    win_main(opt_argc, opt_argv);
  else
    win_main(Service.my_argc, Service.my_argv);
5800 5801

  my_thread_end();
unknown's avatar
unknown committed
5802 5803 5804
  return 0;
}

5805 5806 5807 5808 5809 5810 5811 5812

/* 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
5813 5814
    return strmake(to, from, length-1);
  return strxnmov(to, length-1, "\"", from, "\"", NullS);
5815 5816 5817
}


unknown's avatar
unknown committed
5818 5819
/**
  Handle basic handling of services, like installation and removal.
5820

unknown's avatar
unknown committed
5821 5822 5823 5824 5825 5826
  @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

5827 5828
  @retval 0	option handled
  @retval 1	Could not handle option
unknown's avatar
unknown committed
5829
*/
5830

5831 5832 5833 5834 5835
static bool
default_service_handling(char **argv,
			 const char *servicename,
			 const char *displayname,
			 const char *file_path,
unknown's avatar
Merge  
unknown committed
5836 5837
			 const char *extra_opt,
			 const char *account_name)
5838
{
5839
  char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
5840
  const char *opt_delim;
5841
  end= path_and_service + sizeof(path_and_service)-3;
5842 5843 5844

  /* We have to quote filename if it contains spaces */
  pos= add_quoted_string(path_and_service, file_path, end);
5845
  if (extra_opt && *extra_opt)
5846
  {
5847 5848 5849 5850 5851
    /* 
     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.  
    */
5852
    *pos++= ' ';
5853 5854 5855
    if (opt_delim= strchr(extra_opt, '='))
    {
      size_t length= ++opt_delim - extra_opt;
5856
      pos= strnmov(pos, extra_opt, length);
5857 5858 5859 5860 5861
    }
    else
      opt_delim= extra_opt;
    
    pos= add_quoted_string(pos, opt_delim, end);
5862
  }
5863 5864
  /* We must have servicename last */
  *pos++= ' ';
unknown's avatar
unknown committed
5865
  (void) add_quoted_string(pos, servicename, end);
5866

5867 5868
  if (Service.got_service_option(argv, "install"))
  {
unknown's avatar
Merge  
unknown committed
5869 5870
    Service.Install(1, servicename, displayname, path_and_service,
                    account_name);
5871 5872 5873 5874
    return 0;
  }
  if (Service.got_service_option(argv, "install-manual"))
  {
unknown's avatar
Merge  
unknown committed
5875 5876
    Service.Install(0, servicename, displayname, path_and_service,
                    account_name);
5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887
    return 0;
  }
  if (Service.got_service_option(argv, "remove"))
  {
    Service.Remove(servicename);
    return 0;
  }
  return 1;
}


5888
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5889
{
5890 5891
  my_progname= argv[0];

unknown's avatar
unknown committed
5892 5893 5894 5895
  /*
    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
5896
  */
5897
  int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
unknown's avatar
Merge  
unknown committed
5898 5899
                                                  "MySQLShutdown"), 10);

5900 5901 5902
  /* Must be initialized early for comparison of service name */
  system_charset_info= &my_charset_utf8_general_ci;

5903 5904 5905 5906 5907 5908
  if (my_init())
  {
    fprintf(stderr, "my_init() failed.");
    return 1;
  }

unknown's avatar
unknown committed
5909
  if (Service.GetOS())	/* true NT family */
unknown's avatar
unknown committed
5910
  {
unknown's avatar
unknown committed
5911
    char file_path[FN_REFLEN];
5912
    my_path(file_path, argv[0], "");		      /* Find name in path */
unknown's avatar
unknown committed
5913 5914
    fn_format(file_path,argv[0],file_path,"",
	      MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
unknown's avatar
unknown committed
5915

unknown's avatar
unknown committed
5916
    if (argc == 2)
5917
    {
5918
      if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
unknown's avatar
Merge  
unknown committed
5919
				   file_path, "", NULL))
5920
	return 0;
unknown's avatar
unknown committed
5921
      if (Service.IsService(argv[1]))        /* Start an optional service */
unknown's avatar
unknown committed
5922
      {
unknown's avatar
unknown committed
5923 5924 5925 5926 5927 5928
	/*
	  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.
	*/
5929
	if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
5930
	  load_default_groups[load_default_groups_sz-2]= argv[1];
unknown's avatar
unknown committed
5931
        start_mode= 1;
5932
        Service.Init(argv[1], mysql_service);
unknown's avatar
unknown committed
5933 5934 5935 5936
        return 0;
      }
    }
    else if (argc == 3) /* install or remove any optional service */
unknown's avatar
unknown committed
5937
    {
unknown's avatar
Merge  
unknown committed
5938 5939
      if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
                                    NULL))
5940 5941
	return 0;
      if (Service.IsService(argv[2]))
unknown's avatar
unknown committed
5942
      {
5943 5944 5945 5946
	/*
	  mysqld was started as
	  mysqld --defaults-file=my_path\my.ini service-name
	*/
5947
	use_opt_args=1;
5948
	opt_argc= 2;				// Skip service-name
5949 5950
	opt_argv=argv;
	start_mode= 1;
5951
	if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
5952
	  load_default_groups[load_default_groups_sz-2]= argv[2];
5953
	Service.Init(argv[2], mysql_service);
5954
	return 0;
unknown's avatar
unknown committed
5955 5956
      }
    }
unknown's avatar
Merge  
unknown committed
5957
    else if (argc == 4 || argc == 5)
5958 5959
    {
      /*
unknown's avatar
Merge  
unknown committed
5960 5961 5962 5963 5964
        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.)
5965
      */
unknown's avatar
Merge  
unknown committed
5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980
      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;
5981
    }
unknown's avatar
unknown committed
5982
    else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
unknown's avatar
unknown committed
5983
    {
unknown's avatar
unknown committed
5984 5985 5986
      /* start the default service */
      start_mode= 1;
      Service.Init(MYSQL_SERVICENAME, mysql_service);
unknown's avatar
unknown committed
5987 5988 5989
      return 0;
    }
  }
unknown's avatar
unknown committed
5990
  /* Start as standalone server */
unknown's avatar
unknown committed
5991 5992 5993 5994 5995 5996 5997 5998
  Service.my_argc=argc;
  Service.my_argv=argv;
  mysql_service(NULL);
  return 0;
}
#endif


unknown's avatar
unknown committed
5999
/**
6000 6001 6002
  Execute all commands from a file. Used by the mysql_install_db script to
  create MySQL privilege tables without having to start a full MySQL server.
*/
6003

Marc Alff's avatar
Marc Alff committed
6004
static void bootstrap(MYSQL_FILE *file)
unknown's avatar
unknown committed
6005
{
6006
  DBUG_ENTER("bootstrap");
6007

6008
  THD *thd= new THD;
6009 6010 6011
#ifdef WITH_WSREP
  thd->variables.wsrep_on= 0;
#endif
unknown's avatar
unknown committed
6012
  thd->bootstrap=1;
6013
  my_net_init(&thd->net,(st_vio*) 0, MYF(0));
unknown's avatar
unknown committed
6014
  thd->max_client_packet_length= thd->net.max_packet;
6015
  thd->security_ctx->master_access= ~(ulong)0;
unknown's avatar
unknown committed
6016
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
Michael Widenius's avatar
Michael Widenius committed
6017
  thread_count++;                        // Safe as only one thread running
6018
  in_bootstrap= TRUE;
6019 6020

  bootstrap_file=file;
unknown's avatar
unknown committed
6021
#ifndef EMBEDDED_LIBRARY			// TODO:  Enable this
6022 6023 6024 6025 6026
  int error;
  if ((error= mysql_thread_create(key_thread_bootstrap,
                                  &thd->real_id, &connection_attrib,
                                  handle_bootstrap,
                                  (void*) thd)))
6027
  {
6028 6029
    sql_print_warning("Can't create thread to handle bootstrap (errno= %d)",
                      error);
unknown's avatar
Merge  
unknown committed
6030 6031
    bootstrap_error=-1;
    DBUG_VOID_RETURN;
6032 6033
  }
  /* Wait for thread to die */
Marc Alff's avatar
Marc Alff committed
6034
  mysql_mutex_lock(&LOCK_thread_count);
6035
  while (in_bootstrap)
6036
  {
Marc Alff's avatar
Marc Alff committed
6037
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
6038 6039
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
6040
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
6041 6042
#else
  thd->mysql= 0;
Marc Alff's avatar
Marc Alff committed
6043
  do_handle_bootstrap(thd);
unknown's avatar
unknown committed
6044 6045
#endif

unknown's avatar
Merge  
unknown committed
6046
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
6047 6048
}

6049

unknown's avatar
unknown committed
6050 6051
static bool read_init_file(char *file_name)
{
Marc Alff's avatar
Marc Alff committed
6052
  MYSQL_FILE *file;
unknown's avatar
unknown committed
6053 6054
  DBUG_ENTER("read_init_file");
  DBUG_PRINT("enter",("name: %s",file_name));
Marc Alff's avatar
Marc Alff committed
6055 6056
  if (!(file= mysql_file_fopen(key_file_init, file_name,
                               O_RDONLY, MYF(MY_WME))))
6057
    DBUG_RETURN(TRUE);
unknown's avatar
Merge  
unknown committed
6058
  bootstrap(file);
Marc Alff's avatar
Marc Alff committed
6059
  mysql_file_fclose(file, MYF(MY_WME));
6060
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
6061 6062 6063
}


Mikael Ronström's avatar
Mikael Ronström committed
6064 6065 6066 6067 6068 6069 6070 6071
/**
  Increment number of created threads
*/
void inc_thread_created(void)
{
  thread_created++;
}

6072
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
6073 6074 6075 6076 6077 6078 6079 6080 6081 6082

/*
   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

     When we enter this function, LOCK_thread_count is hold!
*/
6083

unknown's avatar
unknown committed
6084 6085
void handle_connection_in_main_thread(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
6086
  mysql_mutex_assert_owner(&LOCK_thread_count);
unknown's avatar
unknown committed
6087 6088
  thread_cache_size=0;			// Safety
  threads.append(thd);
Marc Alff's avatar
Marc Alff committed
6089
  mysql_mutex_unlock(&LOCK_thread_count);
6090
  thd->start_utime= microsecond_interval_timer();
Marc Alff's avatar
Marc Alff committed
6091
  do_handle_one_connection(thd);
unknown's avatar
unknown committed
6092 6093 6094 6095 6096 6097 6098 6099 6100
}


/*
  Scheduler that uses one thread per connection
*/

void create_thread_to_handle_connection(THD *thd)
{
Michael Widenius's avatar
Michael Widenius committed
6101 6102 6103 6104
  DBUG_ENTER("create_thread_to_handle_connection");
  mysql_mutex_assert_owner(&LOCK_thread_count);

  /* Check if we can get thread from the cache */
unknown's avatar
unknown committed
6105 6106
  if (cached_thread_count > wake_thread)
  {
Michael Widenius's avatar
Michael Widenius committed
6107 6108 6109
    mysql_mutex_lock(&LOCK_thread_cache);
    /* Recheck condition when we have the lock */
    if (cached_thread_count > wake_thread)
unknown's avatar
unknown committed
6110
    {
Marc Alff's avatar
Marc Alff committed
6111
      mysql_mutex_unlock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
6112 6113 6114 6115 6116 6117 6118 6119 6120 6121
      /* Get thread from cache */
      thread_cache.push_back(thd);
      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);
  }
6122

Michael Widenius's avatar
Michael Widenius committed
6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140
  char error_message_buff[MYSQL_ERRMSG_SIZE];
  /* Create new thread to handle connection */
  int error;
  thread_created++;
  threads.append(thd);
  DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
  thd->prior_thr_create_utime= microsecond_interval_timer();
  if ((error= mysql_thread_create(key_thread_one_connection,
                                  &thd->real_id, &connection_attrib,
                                  handle_one_connection,
                                  (void*) thd)))
  {
    /* purecov: begin inspected */
    DBUG_PRINT("error",
               ("Can't create thread to handle request (error %d)",
                error));
    thd->killed= KILL_CONNECTION;             // Safety
    mysql_mutex_unlock(&LOCK_thread_count);
6141

Michael Widenius's avatar
Michael Widenius committed
6142 6143 6144
    mysql_mutex_lock(&LOCK_connection_count);
    (*thd->scheduler->connection_count)--;
    mysql_mutex_unlock(&LOCK_connection_count);
6145

Michael Widenius's avatar
Michael Widenius committed
6146
    statistic_increment(aborted_connects,&LOCK_status);
Sergei Golubchik's avatar
Sergei Golubchik committed
6147
    statistic_increment(connection_errors_internal, &LOCK_status);
Michael Widenius's avatar
Michael Widenius committed
6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160
    /* Can't use my_error() since store_globals has not been called. */
    my_snprintf(error_message_buff, sizeof(error_message_buff),
                ER_THD(thd, ER_CANT_CREATE_THREAD), error);
    net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
    close_connection(thd, ER_OUT_OF_RESOURCES);

    mysql_mutex_lock(&LOCK_thread_count);
    thd->unlink();
    mysql_mutex_unlock(&LOCK_thread_count);
    delete thd;
    thread_safe_decrement32(&thread_count, &thread_count_lock);
    return;
    /* purecov: end */
unknown's avatar
unknown committed
6161
  }
Marc Alff's avatar
Marc Alff committed
6162
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
6163
  DBUG_PRINT("info",("Thread created"));
Michael Widenius's avatar
Michael Widenius committed
6164
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
6165 6166 6167
}


unknown's avatar
unknown committed
6168
/**
6169 6170 6171 6172 6173 6174
  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
6175
    In single-threaded mode (\#define ONE_THREAD) connection will be
6176 6177
    handled inside this function.

unknown's avatar
unknown committed
6178
  @param[in,out] thd    Thread handle of future thread.
6179 6180
*/

unknown's avatar
unknown committed
6181 6182 6183 6184
static void create_new_thread(THD *thd)
{
  DBUG_ENTER("create_new_thread");

6185 6186 6187 6188 6189
  /*
    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
6190
  mysql_mutex_lock(&LOCK_connection_count);
6191

6192 6193
  if (*thd->scheduler->connection_count >=
      *thd->scheduler->max_connections + 1|| abort_loop)
unknown's avatar
unknown committed
6194
  {
Marc Alff's avatar
Marc Alff committed
6195
    mysql_mutex_unlock(&LOCK_connection_count);
6196

unknown's avatar
unknown committed
6197
    DBUG_PRINT("error",("Too many connections"));
6198
    close_connection(thd, ER_CON_COUNT_ERROR);
6199
    statistic_increment(denied_connections, &LOCK_status);
unknown's avatar
unknown committed
6200
    delete thd;
unknown's avatar
unknown committed
6201
    statistic_increment(connection_errors_max_connection, &LOCK_status);
unknown's avatar
unknown committed
6202 6203
    DBUG_VOID_RETURN;
  }
6204

6205
  ++*thd->scheduler->connection_count;
6206

6207 6208
  if (connection_count + extra_connection_count > max_used_connections)
    max_used_connections= connection_count + extra_connection_count;
6209

Marc Alff's avatar
Marc Alff committed
6210
  mysql_mutex_unlock(&LOCK_connection_count);
6211

Michael Widenius's avatar
Michael Widenius committed
6212
  thread_safe_increment32(&thread_count, &thread_count_lock);
6213

Michael Widenius's avatar
Michael Widenius committed
6214
  /* Start a new thread to handle connection. */
Marc Alff's avatar
Marc Alff committed
6215
  mysql_mutex_lock(&LOCK_thread_count);
6216 6217 6218 6219 6220
  /*
    The initialization of thread_id is done in create_embedded_thd() for
    the embedded library.
    TODO: refactor this to avoid code duplication there
  */
unknown's avatar
unknown committed
6221
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
unknown's avatar
unknown committed
6222

Sergei Golubchik's avatar
Sergei Golubchik committed
6223
  MYSQL_CALLBACK(thd->scheduler, add_connection, (thd));
6224

unknown's avatar
unknown committed
6225 6226
  DBUG_VOID_RETURN;
}
6227 6228
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
6229

unknown's avatar
unknown committed
6230 6231 6232 6233
#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
{
  /* hack to get around signals ignored in syscalls for problem OS's */
6234 6235 6236
  if (mysql_socket_getfd(unix_sock) == INVALID_SOCKET ||
      (!opt_disable_networking &&
       mysql_socket_getfd(base_ip_sock) == INVALID_SOCKET))
unknown's avatar
unknown committed
6237 6238
  {
    select_thread_in_use = 0;
unknown's avatar
unknown committed
6239
    /* The following call will never return */
6240
    DBUG_PRINT("general", ("killing server because socket is closed"));
6241
    kill_server((void*) MYSQL_KILL_SIGNAL);
unknown's avatar
unknown committed
6242 6243 6244 6245 6246 6247
  }
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
#else
#define MAYBE_BROKEN_SYSCALL
#endif
unknown's avatar
unknown committed
6248 6249 6250

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

6251
#ifndef EMBEDDED_LIBRARY
6252

6253
void handle_connections_sockets()
unknown's avatar
unknown committed
6254
{
6255 6256
  MYSQL_SOCKET sock= mysql_socket_invalid();
  MYSQL_SOCKET new_sock= mysql_socket_invalid();
unknown's avatar
unknown committed
6257 6258
  uint error_count=0;
  THD *thd;
6259
  struct sockaddr_storage cAddr;
Michael Widenius's avatar
Michael Widenius committed
6260 6261 6262 6263
  int ip_flags __attribute__((unused))=0;
  int socket_flags __attribute__((unused))= 0;
  int extra_ip_flags __attribute__((unused))=0;
  int flags=0,retval;
unknown's avatar
unknown committed
6264
  st_vio *vio_tmp;
6265
  bool is_unix_sock;
6266 6267
#ifdef HAVE_POLL
  int socket_count= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
6268
  struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock
6269
  MYSQL_SOCKET  pfs_fds[3]; // for performance schema
Sergei Golubchik's avatar
Sergei Golubchik committed
6270
#define setup_fds(X)                    \
Sergei Golubchik's avatar
Sergei Golubchik committed
6271
    mysql_socket_set_thread_owner(X);             \
6272 6273
    pfs_fds[socket_count]= (X);                   \
    fds[socket_count].fd= mysql_socket_getfd(X);  \
Sergei Golubchik's avatar
Sergei Golubchik committed
6274 6275
    fds[socket_count].events= POLLIN;   \
    socket_count++
6276
#else
6277
#define setup_fds(X)    FD_SET(mysql_socket_getfd(X),&clientFDs)
6278
  fd_set readFDs,clientFDs;
Sergei Golubchik's avatar
Sergei Golubchik committed
6279
  FD_ZERO(&clientFDs);
6280 6281
#endif

unknown's avatar
unknown committed
6282 6283
  DBUG_ENTER("handle_connections_sockets");

6284
  if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
6285
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6286
    setup_fds(base_ip_sock);
6287
    ip_flags = fcntl(mysql_socket_getfd(base_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6288
  }
6289
  if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
6290
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6291
    setup_fds(extra_ip_sock);
6292
    extra_ip_flags = fcntl(mysql_socket_getfd(extra_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6293 6294
  }
#ifdef HAVE_SYS_UN_H
Sergei Golubchik's avatar
Sergei Golubchik committed
6295
  setup_fds(unix_sock);
6296
  socket_flags=fcntl(mysql_socket_getfd(unix_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6297 6298 6299
#endif

  DBUG_PRINT("general",("Waiting for connections."));
unknown's avatar
unknown committed
6300
  MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6301 6302
  while (!abort_loop)
  {
6303 6304
#ifdef HAVE_POLL
    retval= poll(fds, socket_count, -1);
unknown's avatar
unknown committed
6305
#else
6306
    readFDs=clientFDs;
6307
    retval= select((int) 0,&readFDs,0,0,0);
6308 6309 6310
#endif

    if (retval < 0)
unknown's avatar
unknown committed
6311
    {
unknown's avatar
unknown committed
6312
      if (socket_errno != SOCKET_EINTR)
unknown's avatar
unknown committed
6313
      {
unknown's avatar
unknown committed
6314 6315 6316 6317 6318 6319
        /*
          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
6320
	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
unknown's avatar
unknown committed
6321
	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
unknown's avatar
unknown committed
6322
      }
unknown's avatar
unknown committed
6323
      MAYBE_BROKEN_SYSCALL
unknown's avatar
unknown committed
6324 6325
      continue;
    }
6326

unknown's avatar
unknown committed
6327
    if (abort_loop)
unknown's avatar
unknown committed
6328 6329
    {
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6330
      break;
unknown's avatar
unknown committed
6331
    }
unknown's avatar
unknown committed
6332

6333
    /* Is this a new connection request ? */
6334 6335 6336 6337 6338
#ifdef HAVE_POLL
    for (int i= 0; i < socket_count; ++i) 
    {
      if (fds[i].revents & POLLIN)
      {
6339 6340
        sock= pfs_fds[i];
        flags= fcntl(mysql_socket_getfd(sock), F_GETFL, 0);
6341 6342 6343 6344
        break;
      }
    }
#else  // HAVE_POLL
6345
    if (FD_ISSET(mysql_socket_getfd(base_ip_sock),&readFDs))
unknown's avatar
unknown committed
6346
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6347 6348
      sock=  base_ip_sock;
      flags= ip_flags;
unknown's avatar
unknown committed
6349 6350
    }
    else
6351
    if (FD_ISSET(mysql_socket_getfd(extra_ip_sock),&readFDs))
unknown's avatar
unknown committed
6352
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6353 6354 6355 6356 6357 6358 6359
      sock=  extra_ip_sock;
      flags= extra_ip_flags;
    }
    else
    {
      sock = unix_sock;
      flags= socket_flags;
unknown's avatar
unknown committed
6360
    }
6361
#endif // HAVE_POLL
unknown's avatar
unknown committed
6362 6363 6364 6365 6366

#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
    {
#if defined(O_NONBLOCK)
6367
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NONBLOCK);
unknown's avatar
unknown committed
6368
#elif defined(O_NDELAY)
6369
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NDELAY);
unknown's avatar
unknown committed
6370 6371 6372 6373 6374
#endif
    }
#endif /* NO_FCNTL_NONBLOCK */
    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
    {
6375
      size_socket length= sizeof(struct sockaddr_storage);
6376 6377 6378 6379
      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
6380
	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
unknown's avatar
unknown committed
6381
	break;
unknown's avatar
unknown committed
6382
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6383 6384 6385 6386
#if !defined(NO_FCNTL_NONBLOCK)
      if (!(test_flags & TEST_BLOCKING))
      {
	if (retry == MAX_ACCEPT_RETRY - 1)
6387 6388 6389 6390
        {
          // Try without O_NONBLOCK
	  fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
        }
unknown's avatar
unknown committed
6391 6392 6393 6394 6395
      }
#endif
    }
#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
6396
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
unknown's avatar
unknown committed
6397
#endif
6398
    if (mysql_socket_getfd(new_sock) == INVALID_SOCKET)
unknown's avatar
unknown committed
6399
    {
unknown's avatar
unknown committed
6400 6401 6402 6403 6404 6405
      /*
        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
6406 6407
      if ((error_count++ & 255) == 0)		// This can happen often
	sql_perror("Error in accept");
unknown's avatar
unknown committed
6408
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6409
      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
unknown's avatar
unknown committed
6410 6411 6412
	sleep(1);				// Give other threads some time
      continue;
    }
6413
#ifdef FD_CLOEXEC
6414
    (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC);
6415
#endif
unknown's avatar
unknown committed
6416 6417 6418

#ifdef HAVE_LIBWRAP
    {
6419 6420
      if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) ||
          mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
unknown's avatar
unknown committed
6421 6422 6423
      {
	struct request_info req;
	signal(SIGCHLD, SIG_DFL);
6424 6425
	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE,
                     mysql_socket_getfd(new_sock), NULL);
6426 6427
	my_fromhost(&req);
	if (!my_hosts_access(&req))
unknown's avatar
unknown committed
6428
	{
unknown's avatar
unknown committed
6429 6430 6431 6432 6433
	  /*
	    This may be stupid but refuse() includes an exit(0)
	    which we surely don't want...
	    clean_exit() - same stupid thing ...
	  */
6434
	  syslog(deny_severity, "refused connect from %s",
6435
		 my_eval_client(&req));
unknown's avatar
unknown committed
6436

unknown's avatar
unknown committed
6437 6438 6439 6440 6441 6442
	  /*
	    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...
	  */
unknown's avatar
unknown committed
6443 6444 6445
	  if (req.sink)
	    ((void (*)(int))req.sink)(req.fd);

6446
	  (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6447
	  (void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6448 6449 6450 6451
          /*
            The connection was refused by TCP wrappers.
            There are no details (by client IP) available to update the host_cache.
          */
6452
          statistic_increment(connection_errors_tcpwrap, &LOCK_status);
unknown's avatar
unknown committed
6453 6454 6455 6456 6457 6458 6459 6460 6461 6462
	  continue;
	}
      }
    }
#endif /* HAVE_LIBWRAP */

    /*
    ** Don't allow too many connections
    */

6463
    DBUG_PRINT("info", ("Creating THD for new connection"));
unknown's avatar
unknown committed
6464 6465
    if (!(thd= new THD))
    {
6466
      (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6467
      (void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6468
      statistic_increment(connection_errors_internal, &LOCK_status);
unknown's avatar
unknown committed
6469 6470
      continue;
    }
6471 6472
    /* Set to get io buffers to be part of THD */
    set_current_thd(thd);
Sergei Golubchik's avatar
Sergei Golubchik committed
6473

6474 6475 6476 6477 6478 6479 6480
    is_unix_sock= (mysql_socket_getfd(sock) ==
                   mysql_socket_getfd(unix_sock));

    if (!(vio_tmp=
          mysql_socket_vio_new(new_sock,
                               is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
                               is_unix_sock ? VIO_LOCALHOST: 0)) ||
6481
	my_net_init(&thd->net, vio_tmp, MYF(MY_THREAD_SPECIFIC)))
unknown's avatar
unknown committed
6482
    {
6483 6484 6485 6486 6487 6488 6489
      /*
        Only delete the temporary vio if we didn't already attach it to the
        NET object. The destructor in THD will delete any initialized net
        structure.
      */
      if (vio_tmp && thd->net.vio != vio_tmp)
        vio_delete(vio_tmp);
unknown's avatar
unknown committed
6490 6491
      else
      {
6492
	(void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6493
	(void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6494 6495
      }
      delete thd;
6496
      set_current_thd(0);
unknown's avatar
unknown committed
6497
      statistic_increment(connection_errors_internal, &LOCK_status);
unknown's avatar
unknown committed
6498 6499
      continue;
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
6500 6501

    init_net_server_extension(thd);
6502
    if (is_unix_sock)
6503
      thd->security_ctx->host=(char*) my_localhost;
6504

6505
    if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
6506 6507
    {
      thd->extra_port= 1;
Sergei Golubchik's avatar
Sergei Golubchik committed
6508
      thd->scheduler= extra_thread_scheduler;
6509
    }
unknown's avatar
unknown committed
6510
    create_new_thread(thd);
6511
    set_current_thd(0);
unknown's avatar
unknown committed
6512
  }
6513 6514 6515
  DBUG_VOID_RETURN;
}

unknown's avatar
unknown committed
6516

6517 6518 6519 6520 6521
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg)
{
  my_thread_init();
  handle_connections_sockets();
6522
  decrement_handler_count();
6523
  return 0;
unknown's avatar
unknown committed
6524 6525
}

6526
pthread_handler_t handle_connections_namedpipes(void *arg)
unknown's avatar
unknown committed
6527 6528
{
  HANDLE hConnectedPipe;
6529
  OVERLAPPED connectOverlapped= {0};
unknown's avatar
unknown committed
6530 6531 6532
  THD *thd;
  my_thread_init();
  DBUG_ENTER("handle_connections_namedpipes");
6533 6534 6535 6536 6537 6538
  connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
  if (!connectOverlapped.hEvent)
  {
    sql_print_error("Can't create event, last error=%u", GetLastError());
    unireg_abort(1);
  }
unknown's avatar
unknown committed
6539 6540 6541 6542
  DBUG_PRINT("general",("Waiting for named pipe connections."));
  while (!abort_loop)
  {
    /* wait for named pipe connection */
6543 6544 6545 6546 6547 6548 6549 6550 6551 6552
    BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped);
    if (!fConnected && (GetLastError() == ERROR_IO_PENDING))
    {
        /*
          ERROR_IO_PENDING says async IO has started but not yet finished.
          GetOverlappedResult will wait for completion.
        */
        DWORD bytes;
        fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE);
    }
unknown's avatar
unknown committed
6553 6554
    if (abort_loop)
      break;
unknown's avatar
unknown committed
6555
    if (!fConnected)
unknown's avatar
unknown committed
6556
      fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
unknown's avatar
unknown committed
6557
    if (!fConnected)
unknown's avatar
unknown committed
6558
    {
unknown's avatar
Merge  
unknown committed
6559 6560
      CloseHandle(hPipe);
      if ((hPipe= CreateNamedPipe(pipe_name,
6561 6562
                                  PIPE_ACCESS_DUPLEX |
                                  FILE_FLAG_OVERLAPPED,
unknown's avatar
Merge  
unknown committed
6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573
                                  PIPE_TYPE_BYTE |
                                  PIPE_READMODE_BYTE |
                                  PIPE_WAIT,
                                  PIPE_UNLIMITED_INSTANCES,
                                  (int) global_system_variables.
                                  net_buffer_length,
                                  (int) global_system_variables.
                                  net_buffer_length,
                                  NMPWAIT_USE_DEFAULT_WAIT,
                                  &saPipeSecurity)) ==
	  INVALID_HANDLE_VALUE)
unknown's avatar
unknown committed
6574 6575 6576 6577 6578 6579 6580
      {
	sql_perror("Can't create new named pipe!");
	break;					// Abort
      }
    }
    hConnectedPipe = hPipe;
    /* create new pipe for new connection */
6581
    if ((hPipe = CreateNamedPipe(pipe_name,
6582 6583
                 PIPE_ACCESS_DUPLEX |
                 FILE_FLAG_OVERLAPPED,
unknown's avatar
unknown committed
6584 6585 6586 6587
				 PIPE_TYPE_BYTE |
				 PIPE_READMODE_BYTE |
				 PIPE_WAIT,
				 PIPE_UNLIMITED_INSTANCES,
6588 6589
				 (int) global_system_variables.net_buffer_length,
				 (int) global_system_variables.net_buffer_length,
unknown's avatar
unknown committed
6590 6591 6592 6593 6594 6595 6596 6597 6598
				 NMPWAIT_USE_DEFAULT_WAIT,
				 &saPipeSecurity)) ==
	INVALID_HANDLE_VALUE)
    {
      sql_perror("Can't create new named pipe!");
      hPipe=hConnectedPipe;
      continue;					// We have to try again
    }

unknown's avatar
unknown committed
6599
    if (!(thd = new THD))
unknown's avatar
unknown committed
6600
    {
unknown's avatar
Merge  
unknown committed
6601 6602
      DisconnectNamedPipe(hConnectedPipe);
      CloseHandle(hConnectedPipe);
unknown's avatar
unknown committed
6603 6604
      continue;
    }
6605
    set_current_thd(thd);
6606
    if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
6607
	my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
unknown's avatar
unknown committed
6608
    {
6609
      close_connection(thd, ER_OUT_OF_RESOURCES);
unknown's avatar
unknown committed
6610
      delete thd;
6611
      set_current_thd(0);
unknown's avatar
unknown committed
6612 6613
      continue;
    }
6614 6615
    /* Host is unknown */
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
unknown's avatar
unknown committed
6616
    create_new_thread(thd);
6617
    set_current_thd(0);
unknown's avatar
unknown committed
6618
  }
6619
  CloseHandle(connectOverlapped.hEvent);
6620
  DBUG_LEAVE;
6621
  decrement_handler_count();
6622
  return 0;
unknown's avatar
unknown committed
6623
}
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
6624
#endif /* _WIN32 */
unknown's avatar
unknown committed
6625

6626

unknown's avatar
unknown committed
6627
#ifdef HAVE_SMEM
6628

unknown's avatar
unknown committed
6629 6630
/**
  Thread of shared memory's service.
6631

unknown's avatar
unknown committed
6632 6633
  @param arg                              Arguments of thread
*/
6634
pthread_handler_t handle_connections_shared_memory(void *arg)
6635
{
6636 6637
  /* file-mapping object, use for create shared memory */
  HANDLE handle_connect_file_map= 0;
6638
  char  *handle_connect_map= 0;                 // pointer on shared memory
6639 6640 6641
  HANDLE event_connect_answer= 0;
  ulong smem_buffer_length= shared_memory_buffer_length + 4;
  ulong connect_number= 1;
6642
  char *tmp= NULL;
6643 6644
  char *suffix_pos;
  char connect_number_char[22], *p;
6645
  const char *errmsg= 0;
6646
  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
6647 6648 6649 6650
  my_thread_init();
  DBUG_ENTER("handle_connections_shared_memorys");
  DBUG_PRINT("general",("Waiting for allocated shared memory."));

6651 6652 6653 6654 6655 6656
  /*
     get enough space base-name + '_' + longest suffix we might ever send
   */
  if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
    goto error;

6657 6658 6659 6660 6661 6662 6663 6664
  if (my_security_attr_create(&sa_event, &errmsg,
                              GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
    goto error;

  if (my_security_attr_create(&sa_mapping, &errmsg,
                             GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
    goto error;

6665 6666 6667 6668 6669 6670 6671
  /*
    The name of event and file-mapping events create agree next rule:
      shared_memory_base_name+unique_part
    Where:
      shared_memory_base_name is unique value for each server
      unique_part is unique value for each object (events and file-mapping)
  */
6672
  suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
6673
  strmov(suffix_pos, "CONNECT_REQUEST");
6674 6675
  if ((smem_event_connect_request= CreateEvent(sa_event,
                                               FALSE, FALSE, tmp)) == 0)
6676
  {
6677
    errmsg= "Could not create request event";
6678 6679
    goto error;
  }
6680
  strmov(suffix_pos, "CONNECT_ANSWER");
6681
  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6682
  {
6683
    errmsg="Could not create answer event";
6684 6685
    goto error;
  }
6686
  strmov(suffix_pos, "CONNECT_DATA");
6687 6688 6689
  if ((handle_connect_file_map=
       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
6690
  {
6691
    errmsg= "Could not create file mapping";
6692 6693
    goto error;
  }
6694 6695 6696
  if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
						  FILE_MAP_WRITE,0,0,
						  sizeof(DWORD))) == 0)
6697
  {
6698
    errmsg= "Could not create shared memory service";
6699 6700 6701 6702 6703
    goto error;
  }

  while (!abort_loop)
  {
6704
    /* Wait a request from client */
6705
    WaitForSingleObject(smem_event_connect_request,INFINITE);
6706

unknown's avatar
unknown committed
6707 6708 6709
    /*
       it can be after shutdown command
    */
unknown's avatar
Merge  
unknown committed
6710
    if (abort_loop)
unknown's avatar
unknown committed
6711
      goto error;
6712

6713 6714 6715 6716 6717 6718
    HANDLE handle_client_file_map= 0;
    char  *handle_client_map= 0;
    HANDLE event_client_wrote= 0;
    HANDLE event_client_read= 0;    // for transfer data server <-> client
    HANDLE event_server_wrote= 0;
    HANDLE event_server_read= 0;
unknown's avatar
unknown committed
6719
    HANDLE event_conn_closed= 0;
6720
    THD *thd= 0;
6721

6722
    p= int10_to_str(connect_number, connect_number_char, 10);
6723 6724 6725 6726 6727 6728 6729 6730 6731 6732
    /*
      The name of event and file-mapping events create agree next rule:
        shared_memory_base_name+unique_part+number_of_connection
        Where:
	  shared_memory_base_name is uniquel value for each server
	  unique_part is unique value for each object (events and file-mapping)
	  number_of_connection is connection-number between server and client
    */
    suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
			 "_",NullS);
6733
    strmov(suffix_pos, "DATA");
6734 6735 6736
    if ((handle_client_file_map=
         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
6737
    {
6738
      errmsg= "Could not create file mapping";
6739 6740
      goto errorconn;
    }
6741 6742 6743
    if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
						  FILE_MAP_WRITE,0,0,
						  smem_buffer_length)) == 0)
6744
    {
6745
      errmsg= "Could not create memory map";
6746 6747 6748
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_WROTE");
6749
    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6750
    {
6751
      errmsg= "Could not create client write event";
6752 6753 6754
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_READ");
6755
    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6756
    {
6757
      errmsg= "Could not create client read event";
6758 6759 6760
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_READ");
6761
    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6762
    {
6763
      errmsg= "Could not create server read event";
6764 6765 6766
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_WROTE");
6767 6768
    if ((event_server_wrote= CreateEvent(sa_event,
                                         FALSE, FALSE, tmp)) == 0)
6769
    {
6770
      errmsg= "Could not create server write event";
6771 6772
      goto errorconn;
    }
unknown's avatar
unknown committed
6773
    strmov(suffix_pos, "CONNECTION_CLOSED");
6774 6775
    if ((event_conn_closed= CreateEvent(sa_event,
                                        TRUE, FALSE, tmp)) == 0)
unknown's avatar
unknown committed
6776 6777 6778 6779
    {
      errmsg= "Could not create closed connection event";
      goto errorconn;
    }
6780
    if (abort_loop)
6781
      goto errorconn;
6782 6783 6784
    if (!(thd= new THD))
      goto errorconn;
    /* Send number of connection to client */
6785
    int4store(handle_connect_map, connect_number);
6786
    if (!SetEvent(event_connect_answer))
6787
    {
6788
      errmsg= "Could not send answer event";
6789 6790
      goto errorconn;
    }
6791
    /* Set event that client should receive data */
6792 6793
    if (!SetEvent(event_client_read))
    {
6794
      errmsg= "Could not set client to read mode";
6795 6796
      goto errorconn;
    }
6797
    set_current_thd(thd);
6798
    if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
unknown's avatar
unknown committed
6799 6800 6801 6802 6803
                                                   handle_client_map,
                                                   event_client_wrote,
                                                   event_client_read,
                                                   event_server_wrote,
                                                   event_server_read,
unknown's avatar
unknown committed
6804
                                                   event_conn_closed)) ||
6805
        my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
6806
    {
6807
      close_connection(thd, ER_OUT_OF_RESOURCES);
6808 6809
      errmsg= 0;
      goto errorconn;
6810
    }
6811
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
6812
    create_new_thread(thd);
6813
    connect_number++;
6814
    set_current_thd(thd);
6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825
    continue;

errorconn:
    /* Could not form connection;  Free used handlers/memort and retry */
    if (errmsg)
    {
      char buff[180];
      strxmov(buff, "Can't create shared memory connection: ", errmsg, ".",
	      NullS);
      sql_perror(buff);
    }
6826
    if (handle_client_file_map)
unknown's avatar
unknown committed
6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839
      CloseHandle(handle_client_file_map);
    if (handle_client_map)
      UnmapViewOfFile(handle_client_map);
    if (event_server_wrote)
      CloseHandle(event_server_wrote);
    if (event_server_read)
      CloseHandle(event_server_read);
    if (event_client_wrote)
      CloseHandle(event_client_wrote);
    if (event_client_read)
      CloseHandle(event_client_read);
    if (event_conn_closed)
      CloseHandle(event_conn_closed);
6840
    delete thd;
6841
  }
6842
  set_current_thd(0);
6843 6844

  /* End shared memory handling */
6845
error:
6846
  if (tmp)
6847
    my_free(tmp);
6848

6849 6850 6851 6852 6853 6854
  if (errmsg)
  {
    char buff[180];
    strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
    sql_perror(buff);
  }
6855 6856
  my_security_attr_free(sa_event);
  my_security_attr_free(sa_mapping);
6857 6858 6859
  if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
  if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
  if (event_connect_answer)	CloseHandle(event_connect_answer);
6860
  if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
6861
  DBUG_LEAVE;
6862
  decrement_handler_count();
6863
  return 0;
6864 6865
}
#endif /* HAVE_SMEM */
6866
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
6867

6868 6869 6870

/****************************************************************************
  Handle start options
unknown's avatar
unknown committed
6871 6872
******************************************************************************/

6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917

/**
  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;
}


6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930
#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 }


6931 6932 6933 6934 6935
/**
  System variables are automatically command-line options (few
  exceptions are documented in sys_var.h), so don't need
  to be listed here.
*/
6936

Marc Alff's avatar
Marc Alff committed
6937
struct my_option my_long_options[]=
6938
{
unknown's avatar
unknown committed
6939
  {"help", '?', "Display this help and exit.", 
6940
   &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
unknown's avatar
unknown committed
6941
   0, 0},
6942
  {"allow-suspicious-udfs", 0,
unknown's avatar
unknown committed
6943 6944
   "Allows use of UDFs consisting of only one symbol xxx() "
   "without corresponding xxx_init() or xxx_deinit(). That also means "
6945 6946
   "that one can load any function from any library, for example exit() "
   "from libc.so",
6947
   &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
6948
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6949 6950
  {"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
6951
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6952 6953 6954 6955
  /*
    Because Sys_var_bit does not support command-line options, we need to
    explicitely add one for --autocommit
  */
6956 6957 6958
  {"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},
unknown's avatar
unknown committed
6959
  {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
6960
   &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR,
unknown's avatar
unknown committed
6961
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6962
  {"binlog-do-db", OPT_BINLOG_DO_DB,
6963 6964
   "Tells the master it should log updates for the specified database, "
   "and exclude all others not explicitly mentioned.",
6965
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6966
  {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
Staale Smedseng's avatar
Staale Smedseng committed
6967
   "Tells the master that updates to the given database should not be logged to the binary log.",
6968
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6969
  {"binlog-row-event-max-size", 0,
6970 6971 6972
   "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.",
6973 6974
   &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
   0, GET_ULONG, REQUIRED_ARG,
6975 6976 6977 6978
   /* def_value */ 1024, /* min_value */  256, /* max_value */ ULONG_MAX, 
   /* sub_size */     0, /* block_size */ 256, 
   /* app_type */ 0
  },
6979
#ifndef DISABLE_GRANT_OPTIONS
6980
  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
6981
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6982
#endif
6983
  {"character-set-client-handshake", 0,
unknown's avatar
unknown committed
6984
   "Don't ignore client side character set value sent during handshake.",
6985 6986
   &opt_character_set_client_handshake,
   &opt_character_set_client_handshake,
6987
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
6988
  {"character-set-filesystem", 0,
unknown's avatar
unknown committed
6989
   "Set the filesystem character set.",
6990 6991
   &character_set_filesystem_name,
   &character_set_filesystem_name,
unknown's avatar
unknown committed
6992
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6993
  {"character-set-server", 'C', "Set the default character set.",
6994
   &default_character_set_name, &default_character_set_name,
unknown's avatar
unknown committed
6995
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6996
  {"chroot", 'r', "Chroot mysqld daemon during startup.",
6997
   &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6998
   0, 0, 0, 0, 0, 0},
6999
  {"collation-server", 0, "Set the default collation.",
7000
   &default_collation_name, &default_collation_name,
unknown's avatar
unknown committed
7001
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Staale Smedseng's avatar
Staale Smedseng committed
7002
  {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
7003
   &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
7004
   0, 0, 0},
7005
  {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
7006
   NO_ARG, 0, 0, 0, 0, 0, 0},
Michael Widenius's avatar
Michael Widenius committed
7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054
#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 */
#ifdef SAFE_MUTEX
  {"debug-mutex-deadlock-detector", 0,
   "Enable checking of wrong mutex usage.",
   &safe_mutex_deadlock_detector,
   &safe_mutex_deadlock_detector,
   0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#endif
  {"debug-no-sync", 0,
   "Disables system sync calls. Only for running tests or debugging!",
7055
   &my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
Michael Widenius's avatar
Michael Widenius committed
7056 7057 7058 7059 7060 7061 7062
#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 */
7063 7064 7065
  /* 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. */
7066
  {"default-storage-engine", 0, "The default storage engine for new tables",
7067
   &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
7068
   0, 0, 0, 0, 0, 0 },
7069 7070 7071 7072
  {"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 },
7073
  {"default-time-zone", 0, "Set the default time zone.",
7074
   &default_tz_name, &default_tz_name,
7075
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Michael Widenius's avatar
Michael Widenius committed
7076 7077 7078 7079 7080 7081 7082 7083
#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
7084
#ifdef HAVE_OPENSSL
7085
  {"des-key-file", 0,
unknown's avatar
unknown committed
7086
   "Load keys for des_encrypt() and des_encrypt from given file.",
7087
   &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
7088 7089
   0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
Michael Widenius's avatar
Michael Widenius committed
7090
#ifdef HAVE_STACKTRACE
Sergei Golubchik's avatar
Sergei Golubchik committed
7091
  {"stack-trace", 0 , "Print a symbolic stack trace on failure",
Michael Widenius's avatar
Michael Widenius committed
7092 7093
   &opt_stack_trace, &opt_stack_trace, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_STACKTRACE */
7094 7095 7096 7097
  {"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
7098
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7099 7100
  /* We must always support the next option to make scripts like mysqltest
     easier to do */
7101
  {"gdb", 0,
Sergei Golubchik's avatar
Sergei Golubchik committed
7102 7103 7104
   "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},
7105
#ifdef HAVE_LARGE_PAGE_OPTION
7106
  {"super-large-pages", 0, "Enable support for super large pages.",
7107
   &opt_super_large_pages, &opt_super_large_pages, 0,
7108
   GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
unknown's avatar
Merge  
unknown committed
7109
#endif
7110
  {"language", 'L',
7111 7112
   "Client error messages in given language. May be given as a full path. "
   "Deprecated. Use --lc-messages-dir instead.",
7113
   0, 0, 0,
7114
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7115
  {"lc-messages", 0,
7116
   "Set the language used for the error messages.",
7117
   &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
7118
   0, 0, 0, 0, 0, 0 },
7119
  {"lc-time-names", 0,
7120
   "Set the language used for the month names and the days of the week.",
7121
   &lc_time_names_name, &lc_time_names_name,
7122
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7123 7124 7125
  {"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
7126
   "for specifying log files. Sets names for --log-bin, --log-bin-index, "
7127
   "--relay-log, --relay-log-index, --general-log-file, "
Sergei Golubchik's avatar
Sergei Golubchik committed
7128
   "--log-slow-query-log-file, --log-error-file, and --pid-file",
7129 7130
   &opt_log_basename, &opt_log_basename, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0},
7131
  {"log-bin", OPT_BIN_LOG,
7132 7133
   "Log update queries in binary format. Optional argument should be name for "
   "binary log. If not given "
7134
   "'datadir'/'log-basename'-bin or 'datadir'/mysql-bin will be used (the later if "
Sergei Golubchik's avatar
Sergei Golubchik committed
7135
   "--log-basename is not specified). We strongly recommend to use either "
7136
   "--log-basename or specify a filename to ensure that replication doesn't "
7137
   "stop if the real hostname of the computer changes.",
7138
   &opt_bin_logname, &opt_bin_logname, 0, GET_STR,
unknown's avatar
unknown committed
7139
   OPT_ARG, 0, 0, 0, 0, 0, 0},
7140
  {"log-bin-index", 0,
7141
   "File that holds the names for last binary log files.",
7142
   &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
7143
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7144
  {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
7145
   &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
7146
   OPT_ARG, 0, 0, 0, 0, 0, 0},
7147
  {"log-short-format", 0,
unknown's avatar
unknown committed
7148
   "Don't log extra information to update and slow-query logs.",
7149
   &opt_short_log_format, &opt_short_log_format,
unknown's avatar
unknown committed
7150
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7151
  {"log-slow-admin-statements", 0,
7152 7153
   "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to "
   "the slow log if it is open.", &opt_log_slow_admin_statements,
7154
   &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7155
 {"log-slow-slave-statements", 0,
7156
  "Log slow statements executed by slave thread to the slow log if it is open.",
7157
  &opt_log_slow_slave_statements, &opt_log_slow_slave_statements,
7158
  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7159
  {"log-tc", 0,
unknown's avatar
Merge  
unknown committed
7160
   "Path to transaction coordinator log (used for transactions that affect "
Staale Smedseng's avatar
Staale Smedseng committed
7161
   "more than one storage engine, when binary log is disabled).",
7162
   &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
unknown's avatar
Merge  
unknown committed
7163
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7164
#ifdef HAVE_MMAP
7165
  {"log-tc-size", 0, "Size of transaction coordinator log.",
7166
   &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
unknown's avatar
unknown committed
7167
   REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0,
7168
   TC_LOG_PAGE_SIZE, 0},
7169
#endif
7170
  {"master-info-file", 0,
7171
   "The location and name of the file that remembers the master and where "
7172
   "the I/O replication thread is in the master's binlogs. Defaults to "
Sergei Golubchik's avatar
Sergei Golubchik committed
7173
   "master.info",
7174
   &master_info_file, &master_info_file, 0, GET_STR,
unknown's avatar
unknown committed
7175
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7176
  {"master-retry-count", 0,
7177
   "The number of tries the slave will make to connect to the master before giving up.",
7178
   &master_retry_count, &master_retry_count, 0, GET_ULONG,
7179
   REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
7180
#ifdef HAVE_REPLICATION
7181
  {"init-rpl-role", 0, "Set the replication role",
7182
   &rpl_status, &rpl_status, &rpl_role_typelib,
7183
   GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
7184
#endif /* HAVE_REPLICATION */
7185
  {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
7186
   &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7187
  {"old-style-user-limits", 0,
Staale Smedseng's avatar
Staale Smedseng committed
7188 7189
   "Enable old-style user limits (before 5.0.3, user resources were counted "
   "per each user+host vs. per account).",
7190
   &opt_old_style_user_limits, &opt_old_style_user_limits,
unknown's avatar
Merge  
unknown committed
7191
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7192
  {"port-open-timeout", 0,
7193
   "Maximum time in seconds to wait for the port to become free. "
7194 7195
   "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7196
  {"replicate-do-db", OPT_REPLICATE_DO_DB,
7197 7198 7199 7200 7201 7202 7203
   "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.%.",
7204
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7205
  {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
7206 7207 7208
   "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 "
7209
   "to replicate-do-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7210
  {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
7211 7212 7213 7214 7215
   "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-"
7216
   "table=db_name.%. ", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7217
  {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
7218 7219 7220
   "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 "
7221
   "replicate-ignore-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7222
  {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
7223 7224
   "Updates to a database with a different name than the original. Example: "
   "replicate-rewrite-db=master_db_name->slave_db_name.",
7225
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
7226
#ifdef HAVE_REPLICATION
7227
  {"replicate-same-server-id", 0,
7228 7229 7230 7231
   "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,
7232
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
7233
#endif
unknown's avatar
unknown committed
7234
  {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
7235 7236 7237 7238 7239 7240
   "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.",
7241
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
7242
  {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
7243 7244 7245 7246 7247 7248
   "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.",
7249
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7250
  {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing). Deprecated.",
7251
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
7252
  {"safe-user-create", 0,
7253
   "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
7254
   &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
7255
   NO_ARG, 0, 0, 0, 0, 0, 0},
7256
  {"show-slave-auth-info", 0,
Staale Smedseng's avatar
Staale Smedseng committed
7257
   "Show user and password in SHOW SLAVE HOSTS on this master.",
7258
   &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
7259
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7260 7261 7262
  {"skip-bdb", OPT_DEPRECATED_OPTION,
   "Deprecated option; Exist only for compatiblity with old my.cnf files",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
7263
#ifndef DISABLE_GRANT_OPTIONS
7264
  {"skip-grant-tables", 0,
Staale Smedseng's avatar
Staale Smedseng committed
7265
   "Start without grant tables. This gives all users FULL ACCESS to all tables.",
7266
   &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
7267
   0},
7268
#endif
unknown's avatar
unknown committed
7269 7270
  {"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},
7271
  {"skip-slave-start", 0,
7272 7273
   "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},
7274 7275 7276 7277 7278 7279 7280
#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
7281
#ifdef HAVE_OPENSSL
7282
  {"ssl", 0,
7283
   "Enable SSL for connection (automatically enabled if an ssl option is used).",
7284
   &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
7285
   0, 0, 0},
7286
#endif
unknown's avatar
unknown committed
7287
#ifdef __WIN__
7288
  {"standalone", 0,
unknown's avatar
unknown committed
7289 7290 7291 7292
  "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.",
7293
   &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
7294 7295 7296 7297
   /*
     The system call realpath() produces warnings under valgrind and
     purify. These are not suppressed: instead we disable symlinks
     option if compiled with valgrind support.
7298 7299
     Also disable by default on Windows, due to high overhead for checking .sym 
     files.
7300
   */
7301
   IF_VALGRIND(0,IF_WIN(0,1)), 0, 0, 0, 0, 0},
7302
  {"sysdate-is-now", 0,
7303 7304 7305 7306
   "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
7307
   0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
7308
  {"tc-heuristic-recover", 0,
7309 7310
   "Decision to use in heuristic recover process",
   &tc_heuristic_recover, &tc_heuristic_recover,
7311 7312
   &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"temp-pool", 0,
7313
#if (ENABLE_TEMP_POOL)
7314 7315
   "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.",
7316 7317 7318
#else
   "This option is ignored on this OS.",
#endif
7319
   &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
unknown's avatar
unknown committed
7320
   0, 0, 0, 0, 0},
7321
  {"transaction-isolation", 0,
7322
   "Default transaction isolation level",
7323 7324
   &global_system_variables.tx_isolation,
   &global_system_variables.tx_isolation, &tx_isolation_typelib,
7325
   GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
7326 7327 7328 7329 7330 7331
  {"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},
7332
  {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
7333
   0, 0, 0, 0, 0, 0},
Staale Smedseng's avatar
Staale Smedseng committed
7334
  {"verbose", 'v', "Used with --help option for detailed help.",
7335
   &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7336
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
7337
   NO_ARG, 0, 0, 0, 0, 0, 0},
7338
  {"plugin-load", OPT_PLUGIN_LOAD,
7339 7340 7341
   "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.",
7342
   0, 0, 0,
unknown's avatar
unknown committed
7343
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7344 7345
  {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
   "Optional semicolon-separated list of plugins to load. This option adds "
7346
   "to the list specified by --plugin-load in an incremental way. "
7347 7348 7349
   "It can be specified many times, adding more plugins every time.",
   0, 0, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7350
  {"table_cache", 0, "Deprecated; use --table-open-cache instead.",
7351
   &tc_size, &tc_size, 0, GET_ULONG,
7352
   REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
Monty's avatar
Monty committed
7353 7354 7355 7356 7357 7358 7359
#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
7360 7361 7362 7363

  /* The following options exist in 5.6 but not in 10.0 */
  MYSQL_TO_BE_IMPLEMENTED_OPTION("default-tmp-storage-engine"),
  MYSQL_COMPATIBILITY_OPTION("log-raw"),
7364
  MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"),
7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403
  MYSQL_TO_BE_IMPLEMENTED_OPTION("default-authentication-plugin"),
  MYSQL_COMPATIBILITY_OPTION("binlog-max-flush-queue-time"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("binlog-row-image"),
  MYSQL_TO_BE_IMPLEMENTED_OPTION("explicit-defaults-for-timestamp"),
  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_COMPATIBILITY_OPTION("table-open-cache-instances"),
  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-parallel-workers", "--slave-parallel-threads"),       // HAVE_REPLICATION
  MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"),  // HAVE_REPLICATION
  MYSQL_TO_BE_IMPLEMENTED_OPTION("disconnect-on-expired-password"),
  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"),

  /* 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
7404
};
unknown's avatar
unknown committed
7405

7406
static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
7407
{
7408
  var->type= SHOW_LONGLONG;
7409 7410 7411 7412
  var->value= (char *)&thd->query_id;
  return 0;
}

7413

7414
static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
7415
{
7416
  var->type= SHOW_MY_BOOL;
7417 7418 7419 7420
  var->value= (char *)&thd->net.compress;
  return 0;
}

7421
static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
7422
{
7423
  var->type= SHOW_LONG;
7424
  var->value= buff;
unknown's avatar
unknown committed
7425
  *((long *)buff)= (long) (thd->query_start() - server_start_time);
7426 7427 7428
  return 0;
}

7429
#ifdef ENABLED_PROFILING
7430 7431 7432 7433 7434 7435 7436
static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
{
  var->type= SHOW_LONG;
  var->value= buff;
  *((long *)buff)= (long) (thd->query_start() - flush_status_time);
  return 0;
}
7437
#endif
7438

7439
#ifdef HAVE_REPLICATION
7440
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
7441
{
7442
  var->type= SHOW_CHAR;
7443 7444 7445 7446
  var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
  return 0;
}

7447
static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
7448
{
7449
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7450
  bool tmp;
unknown's avatar
unknown committed
7451
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7452

7453 7454
  var->type= SHOW_MY_BOOL;
  var->value= buff;
unknown's avatar
unknown committed
7455
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7456
  mysql_mutex_lock(&LOCK_active_mi);
7457 7458 7459 7460 7461 7462 7463 7464 7465
  if (master_info_index) 
  {
    mi= master_info_index->
      get_master_info(&thd->variables.default_master_connection,
                      Sql_condition::WARN_LEVEL_NOTE);
    if (mi)
      tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
                      mi->rli.slave_running);
  }
unknown's avatar
unknown committed
7466 7467 7468 7469
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
    *((my_bool *)buff)= tmp;
7470
  else
7471
    var->type= SHOW_UNDEF;
7472 7473
  return 0;
}
Andrei Elkin's avatar
Andrei Elkin committed
7474

7475

Andrei Elkin's avatar
Andrei Elkin committed
7476 7477
static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
{
7478
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7479
  longlong tmp;
unknown's avatar
unknown committed
7480
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7481

7482 7483
  var->type= SHOW_LONGLONG;
  var->value= buff;
unknown's avatar
unknown committed
7484
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7485
  mysql_mutex_lock(&LOCK_active_mi);
7486 7487 7488 7489 7490 7491 7492 7493
  if (master_info_index) 
  {
    mi= master_info_index->
      get_master_info(&thd->variables.default_master_connection,
                      Sql_condition::WARN_LEVEL_NOTE);
    if (mi)
      tmp= mi->received_heartbeats;
  }
unknown's avatar
unknown committed
7494 7495 7496 7497
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
    *((longlong *)buff)= tmp;
Andrei Elkin's avatar
Andrei Elkin committed
7498 7499 7500 7501 7502
  else
    var->type= SHOW_UNDEF;
  return 0;
}

7503

Andrei Elkin's avatar
Andrei Elkin committed
7504 7505
static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
{
7506
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7507 7508
  float tmp;
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7509

7510 7511
  var->type= SHOW_CHAR;
  var->value= buff;
unknown's avatar
unknown committed
7512
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7513
  mysql_mutex_lock(&LOCK_active_mi);
7514 7515 7516 7517
  if (master_info_index) 
  {
    mi= master_info_index->
      get_master_info(&thd->variables.default_master_connection,
7518
                    Sql_condition::WARN_LEVEL_NOTE);
7519 7520 7521
    if (mi)
      tmp= mi->heartbeat_period;
  }
unknown's avatar
unknown committed
7522 7523 7524
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
unknown's avatar
unknown committed
7525
    sprintf(buff, "%.3f", tmp);
Andrei Elkin's avatar
Andrei Elkin committed
7526 7527 7528 7529 7530 7531
  else
    var->type= SHOW_UNDEF;
  return 0;
}


7532 7533
#endif /* HAVE_REPLICATION */

7534
static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
7535
{
7536
  var->type= SHOW_LONG;
7537
  var->value= buff;
7538
  *((long *) buff)= (long) tc_records();
7539 7540 7541
  return 0;
}

unknown's avatar
unknown committed
7542 7543 7544 7545
static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff)
{
  var->type= SHOW_LONG;
  var->value= buff;
Marc Alff's avatar
Marc Alff committed
7546
  mysql_mutex_lock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7547
  *((long *)buff)= (long)prepared_stmt_count;
Marc Alff's avatar
Marc Alff committed
7548
  mysql_mutex_unlock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7549 7550 7551
  return 0;
}

7552
static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
7553
{
7554
  var->type= SHOW_LONG;
7555
  var->value= buff;
7556
  *((long *) buff)= (long) tdc_records();
7557 7558 7559
  return 0;
}

7560 7561 7562 7563 7564 7565 7566 7567 7568 7569

static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff)
{
  var->type= SHOW_LONG;
  var->value= buff;
  *((long *) buff)= (long) tdc_refresh_version();
  return 0;
}


Konstantin Osipov's avatar
Konstantin Osipov committed
7570
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
7571
/* Functions relying on CTX */
7572
static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
7573
{
7574
  var->type= SHOW_LONG;
7575 7576 7577 7578 7579 7580
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
  return 0;
}

7581
static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
7582
{
7583
  var->type= SHOW_LONG;
7584 7585 7586 7587 7588 7589
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

7590
static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
7591
{
7592
  var->type= SHOW_LONG;
7593 7594 7595 7596 7597 7598
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

7599
static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7600
{
7601
  var->type= SHOW_LONG;
7602 7603 7604 7605 7606 7607
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

7608
static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7609
{
7610
  var->type= SHOW_LONG;
7611 7612 7613 7614 7615 7616
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

7617
static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
7618
{
7619
  var->type= SHOW_LONG;
7620 7621 7622 7623 7624 7625
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

7626
static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
7627
{
7628
  var->type= SHOW_LONG;
7629 7630 7631 7632 7633 7634
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

7635
static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
7636
{
7637
  var->type= SHOW_LONG;
7638 7639 7640 7641 7642 7643
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
  return 0;
}

7644
static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
7645
{
7646
  var->type= SHOW_LONG;
7647 7648 7649 7650 7651 7652
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
  return 0;
}

7653
static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
7654
{
7655
  var->type= SHOW_LONG;
7656 7657 7658 7659 7660 7661
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
  return 0;
}

7662
static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
7663
{
7664
  var->type= SHOW_LONG;
7665 7666 7667 7668 7669 7670
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
  return 0;
}

7671
static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
7672
{
7673
  var->type= SHOW_LONG;
7674 7675 7676 7677 7678 7679
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
  return 0;
}

7680
static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
7681
{
7682
  var->type= SHOW_LONG;
7683 7684 7685 7686 7687 7688
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
  return 0;
}

7689
static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7690
{
7691
  var->type= SHOW_LONG;
7692 7693 7694 7695 7696 7697
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
  return 0;
}

7698
static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7699
{
7700
  var->type= SHOW_LONG;
7701 7702 7703 7704 7705 7706
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
  return 0;
}

7707
static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
7708
{
7709
  var->type= SHOW_CHAR;
7710
  if (!ssl_acceptor_fd)
unknown's avatar
unknown committed
7711
    var->value= const_cast<char*>("NONE");
7712 7713 7714 7715
  else
    switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
    {
    case SSL_SESS_CACHE_OFF:
unknown's avatar
unknown committed
7716
      var->value= const_cast<char*>("OFF"); break;
7717
    case SSL_SESS_CACHE_CLIENT:
unknown's avatar
unknown committed
7718
      var->value= const_cast<char*>("CLIENT"); break;
7719
    case SSL_SESS_CACHE_SERVER:
unknown's avatar
unknown committed
7720
      var->value= const_cast<char*>("SERVER"); break;
7721
    case SSL_SESS_CACHE_BOTH:
unknown's avatar
unknown committed
7722
      var->value= const_cast<char*>("BOTH"); break;
7723
    case SSL_SESS_CACHE_NO_AUTO_CLEAR:
unknown's avatar
unknown committed
7724
      var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
7725
    case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
unknown's avatar
unknown committed
7726
      var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
7727
    default:
unknown's avatar
unknown committed
7728
      var->value= const_cast<char*>("Unknown"); break;
7729 7730 7731 7732
    }
  return 0;
}

7733
/*
7734
   Functions relying on SSL
7735 7736 7737 7738 7739
   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.
 */
7740
static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
7741
{
7742
  var->type= SHOW_CHAR;
7743 7744 7745
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
  else
7746
    var->value= (char *)"";
7747 7748 7749
  return 0;
}

7750
static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
7751
{
7752
  var->type= SHOW_LONG;
7753
  var->value= buff;
7754 7755 7756 7757
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    *((long *)buff)= (long)SSL_session_reused((SSL*) thd->net.vio->ssl_arg);
  else
    *((long *)buff)= 0;
unknown's avatar
unknown committed
7758
  return 0;
7759 7760
}

7761
static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
7762
{
7763
  var->type= SHOW_LONG;
7764
  var->value= buff;
7765 7766 7767 7768
  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;
7769 7770 7771
  return 0;
}

7772
static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7773
{
7774
  var->type= SHOW_LONG;
7775
  var->value= buff;
7776 7777 7778 7779
  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;
7780 7781 7782
  return 0;
}

7783
static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7784
{
7785
  var->type= SHOW_LONG;
7786
  var->value= buff;
7787 7788 7789 7790
  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;
7791 7792 7793
  return 0;
}

7794
static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
7795
{
7796
  var->type= SHOW_CHAR;
7797 7798 7799
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
  else
7800
    var->value= (char *)"";
7801 7802 7803
  return 0;
}

7804
static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
7805
{
7806
  var->type= SHOW_CHAR;
7807
  var->value= buff;
7808
  if (thd->vio_ok() && thd->net.vio->ssl_arg)
7809 7810 7811
  {
    int i;
    const char *p;
7812 7813 7814
    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++)
7815
    {
7816
      buff= strnmov(buff, p, end-buff-1);
7817 7818 7819 7820 7821 7822 7823 7824 7825
      *buff++= ':';
    }
    if (i)
      buff--;
  }
  *buff=0;
  return 0;
}

7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929

#ifdef HAVE_YASSL

static char *
my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len)
{
  return yaSSL_ASN1_TIME_to_string(time, buf, len);
}

#else /* openssl */

static char *
my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len)
{
  int n_read;
  char *res= NULL;
  BIO *bio= BIO_new(BIO_s_mem());

  if (bio == NULL)
    return NULL;

  if (!ASN1_TIME_print(bio, time))
    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
show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff)
{
  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);
    ASN1_TIME *not_before= X509_get_notBefore(cert);

    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
show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff)
{
  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);
    ASN1_TIME *not_after= X509_get_notAfter(cert);

    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
7930
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
7931

7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956
static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff)
{
  struct st_data {
    KEY_CACHE_STATISTICS stats;
    SHOW_VAR var[8];
  } *data;
  SHOW_VAR *v;

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

  var->type= SHOW_ARRAY;
  var->value= (char*)v;

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

#define set_one_keycache_var(X,Y)       \
  v->name= X;                           \
  v->type= SHOW_LONGLONG;               \
  v->value= (char*)&data->stats.Y;      \
  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
7957
  set_one_keycache_var("blocks_warm",        blocks_warm);
7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971
  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;
}

7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007
#ifndef DBUG_OFF
static int debug_status_func(THD *thd, SHOW_VAR *var, char *buff)
{
#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[]= {
      {"global",  (char*) &role_global_merges,  SHOW_ULONG},
      {"db",      (char*) &role_db_merges,      SHOW_ULONG},
      {"table",   (char*) &role_table_merges,   SHOW_ULONG},
      {"column",  (char*) &role_column_merges,  SHOW_ULONG},
      {"routine", (char*) &role_routine_merges, SHOW_ULONG},
      {NullS, NullS, SHOW_LONG}
    };

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

  v->name= 0;

#undef add_var

  return 0;
}
#endif

8008 8009 8010 8011 8012 8013 8014 8015 8016
#ifdef HAVE_POOL_OF_THREADS
int show_threadpool_idle_threads(THD *thd, SHOW_VAR *var, char *buff)
{
  var->type= SHOW_INT;
  var->value= buff;
  *(int *)buff= tp_get_idle_thread_count(); 
  return 0;
}
#endif
8017

8018 8019 8020 8021
/*
  Variables shown by SHOW STATUS in alphabetical order
*/

8022
SHOW_VAR status_vars[]= {
8023 8024
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
8025
  {"Access_denied_errors",     (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
8026
  {"Binlog_bytes_written",     (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
8027 8028
  {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
  {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
8029 8030
  {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,  SHOW_LONG},
  {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,       SHOW_LONG},
8031
  {"Busy_time",                (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
8032 8033
  {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
  {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
unknown's avatar
unknown committed
8034
  {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
8035
  {"Compression",              (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
8036
  {"Connections",              (char*) &thread_id,              SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
8037 8038 8039 8040 8041 8042
  {"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},
8043
  {"Cpu_time",                 (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
8044
  {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables_), SHOW_LONG_STATUS},
8045
  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
Sergei Golubchik's avatar
Sergei Golubchik committed
8046
  {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables_), SHOW_LONG_STATUS},
8047 8048 8049
#ifndef DBUG_OFF
  {"Debug",                    (char*) &debug_status_func,  SHOW_FUNC},
#endif
8050
  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
8051
  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
8052
  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
8053
  {"Empty_queries",            (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS},
8054 8055 8056 8057 8058 8059 8060 8061
  {"Executed_events",          (char*) &executed_events, SHOW_LONG_NOFLUSH },
  {"Executed_triggers",        (char*) offsetof(STATUS_VAR, executed_triggers), SHOW_LONG_STATUS},
  {"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},
  {"Feature_locale",           (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
  {"Feature_subquery",         (char*) offsetof(STATUS_VAR, feature_subquery), SHOW_LONG_STATUS},
  {"Feature_timezone",         (char*) offsetof(STATUS_VAR, feature_timezone), SHOW_LONG_STATUS},
8062 8063
  {"Feature_trigger",          (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS},
  {"Feature_xml",              (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS},
8064
  {"Flush_commands",           (char*) &show_flush_commands, SHOW_SIMPLE_FUNC},
unknown's avatar
Merge  
unknown committed
8065 8066 8067
  {"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},
8068
  {"Handler_external_lock",    (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS},
8069
  {"Handler_icp_attempts",     (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
8070 8071
  {"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},
8072 8073
  {"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
8074 8075 8076
  {"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},
8077
  {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
8078 8079 8080
  {"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},
  {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
8081
  {"Handler_read_rnd_deleted", (char*) offsetof(STATUS_VAR, ha_read_rnd_deleted_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
8082 8083 8084 8085
  {"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},
8086 8087
  {"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},
8088 8089
  {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
  {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
8090
  {"Key",                      (char*) &show_default_keycache, SHOW_FUNC},
8091
  {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
8092
  {"Max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS},
8093
  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
8094
  {"Memory_used",              (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS},
8095 8096 8097
  {"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},
8098 8099
  {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_SIMPLE_FUNC},
  {"Open_tables",              (char*) &show_open_tables,       SHOW_SIMPLE_FUNC},
8100
  {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
8101
  {"Opened_plugin_libraries",  (char*) &dlopen_count, SHOW_LONG},
8102
  {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
8103
  {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
8104
  {"Opened_views",             (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
8105
  {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC},
Sergei Golubchik's avatar
Sergei Golubchik committed
8106
  {"Rows_sent",                (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
8107
  {"Rows_read",                (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
8108
  {"Rows_tmp_read",            (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
unknown's avatar
unknown committed
8109
#ifdef HAVE_QUERY_CACHE
8110 8111
  {"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
8112
  {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
8113
  {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
8114
  {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
unknown's avatar
unknown committed
8115
  {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
8116 8117
  {"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
8118
#endif /*HAVE_QUERY_CACHE*/
8119
  {"Queries",                  (char*) &show_queries,            SHOW_SIMPLE_FUNC},
8120
  {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
8121
#ifdef HAVE_REPLICATION
8122
  {"Rpl_status",               (char*) &show_rpl_status,          SHOW_SIMPLE_FUNC},
8123
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
8124 8125 8126 8127 8128
  {"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
8129
  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_INT},
8130
#ifdef HAVE_REPLICATION
8131 8132
  {"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
8133
  {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
8134
  {"Slave_running",            (char*) &show_slave_running,     SHOW_SIMPLE_FUNC},
8135
#endif
8136
  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
unknown's avatar
Merge  
unknown committed
8137
  {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
8138 8139 8140 8141
  {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes_), SHOW_LONG_STATUS},
  {"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
8142
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
8143
#ifndef EMBEDDED_LIBRARY
8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155
  {"Ssl_accept_renegotiates",  (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_SIMPLE_FUNC},
  {"Ssl_accepts",              (char*) &show_ssl_ctx_sess_accept, SHOW_SIMPLE_FUNC},
  {"Ssl_callback_cache_hits",  (char*) &show_ssl_ctx_sess_cb_hits, SHOW_SIMPLE_FUNC},
  {"Ssl_cipher",               (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC},
  {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC},
  {"Ssl_client_connects",      (char*) &show_ssl_ctx_sess_connect, SHOW_SIMPLE_FUNC},
  {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_SIMPLE_FUNC},
  {"Ssl_ctx_verify_depth",     (char*) &show_ssl_ctx_get_verify_depth, SHOW_SIMPLE_FUNC},
  {"Ssl_ctx_verify_mode",      (char*) &show_ssl_ctx_get_verify_mode, SHOW_SIMPLE_FUNC},
  {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC},
  {"Ssl_finished_accepts",     (char*) &show_ssl_ctx_sess_accept_good, SHOW_SIMPLE_FUNC},
  {"Ssl_finished_connects",    (char*) &show_ssl_ctx_sess_connect_good, SHOW_SIMPLE_FUNC},
Sergei Golubchik's avatar
Sergei Golubchik committed
8156 8157
  {"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},
8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168
  {"Ssl_session_cache_hits",   (char*) &show_ssl_ctx_sess_hits, SHOW_SIMPLE_FUNC},
  {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_SIMPLE_FUNC},
  {"Ssl_session_cache_mode",   (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_SIMPLE_FUNC},
  {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_SIMPLE_FUNC},
  {"Ssl_session_cache_size",   (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_SIMPLE_FUNC},
  {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_SIMPLE_FUNC},
  {"Ssl_sessions_reused",      (char*) &show_ssl_session_reused, SHOW_SIMPLE_FUNC},
  {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_SIMPLE_FUNC},
  {"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
8169
#endif
unknown's avatar
unknown committed
8170
#endif /* HAVE_OPENSSL */
8171
  {"Syncs",                    (char*) &my_sync_count,          SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
8172 8173 8174 8175
  /*
    Expression cache used only for caching subqueries now, so its statistic
    variables we call subquery_cache*.
  */
8176 8177
  {"Subquery_cache_hit",       (char*) &subquery_cache_hit,     SHOW_LONG},
  {"Subquery_cache_miss",      (char*) &subquery_cache_miss,    SHOW_LONG},
unknown's avatar
unknown committed
8178 8179
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
8180
#ifdef HAVE_MMAP
unknown's avatar
Merge  
unknown committed
8181
  {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
8182
  {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
8183
  {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
8184
#endif
8185
#ifdef HAVE_POOL_OF_THREADS
8186
  {"Threadpool_idle_threads",  (char *) &show_threadpool_idle_threads, SHOW_SIMPLE_FUNC},
8187
  {"Threadpool_threads",       (char *) &tp_stats.num_worker_threads, SHOW_INT},
8188
#endif
8189
  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_NOFLUSH},
Konstantin Osipov's avatar
Konstantin Osipov committed
8190
  {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
8191 8192
  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
  {"Threads_running",          (char*) &thread_running,         SHOW_INT},
8193
  {"Uptime",                   (char*) &show_starttime,         SHOW_SIMPLE_FUNC},
8194
#ifdef ENABLED_PROFILING
8195
  {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_SIMPLE_FUNC},
8196 8197 8198
#endif
#ifdef WITH_WSREP
  {"wsrep",                    (char*) &wsrep_show_status,       SHOW_FUNC},
8199
#endif
8200
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
8201 8202
};

8203
static bool add_terminator(DYNAMIC_ARRAY *options)
8204 8205
{
  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
8206
  return insert_dynamic(options, (uchar *)&empty_element);
8207 8208
}

8209 8210 8211 8212 8213 8214 8215 8216 8217
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;
}

8218
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
8219 8220
static void print_version(void)
{
8221
  set_server_version();
8222

8223 8224
  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
8225 8226
}

8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254
/** 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;
8255
  init_alloc_root(&mem_root, 4096, 4096, MYF(0));
8256 8257

  pop_dynamic(&all_options);
8258 8259
  add_many_options(&all_options, pfs_early_options,
                  array_elements(pfs_early_options));
Marc Alff's avatar
Marc Alff committed
8260
  sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
8261 8262
  add_plugin_options(&all_options, &mem_root);
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
8263
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
Marc Alff's avatar
Marc Alff committed
8264
  add_terminator(&all_options);
8265 8266

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

8268
  /* Add variables that must be shown but not changed, like version numbers */
8269
  pop_dynamic(&all_options);
8270
  sys_var_add_options(&all_options, sys_var::GETOPT_ONLY_HELP);
8271 8272
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
  add_terminator(&all_options);
8273 8274 8275 8276 8277
  my_print_variables((my_option*) all_options.buffer);

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

unknown's avatar
unknown committed
8278 8279
static void usage(void)
{
8280
  DBUG_ENTER("usage");
8281
  if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
unknown's avatar
unknown committed
8282 8283 8284 8285 8286
					           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
8287
  print_version();
8288
  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
Sergei Golubchik's avatar
Sergei Golubchik committed
8289
  puts("Starts the MariaDB database server.\n");
unknown's avatar
unknown committed
8290
  printf("Usage: %s [OPTIONS]\n", my_progname);
8291
  if (!opt_verbose)
Staale Smedseng's avatar
Staale Smedseng committed
8292
    puts("\nFor more help options (several pages), use mysqld --verbose --help.");
8293 8294
  else
  {
unknown's avatar
unknown committed
8295 8296
#ifdef __WIN__
  puts("NT and Win32 specific options:\n\
Staale Smedseng's avatar
Staale Smedseng committed
8297 8298 8299 8300 8301 8302 8303 8304
  --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).\
unknown's avatar
unknown committed
8305
");
8306
  puts("");
unknown's avatar
unknown committed
8307
#endif
8308
  print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
unknown's avatar
unknown committed
8309 8310
  puts("");
  set_ports();
8311

unknown's avatar
unknown committed
8312
  /* Print out all the options including plugin supplied options */
8313
  print_help();
8314

8315 8316 8317 8318 8319 8320 8321
  if (! plugins_are_initialized)
  {
    puts("\n\
Plugins have parameters that are not reflected in this list\n\
because execution stopped before plugins were initialized.");
  }

unknown's avatar
unknown committed
8322
  puts("\n\
unknown's avatar
unknown committed
8323
To see what values a running MySQL server is using, type\n\
8324
'mysqladmin variables' instead of 'mysqld --verbose --help'.");
8325
  }
8326
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
8327
}
8328
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
8329

unknown's avatar
unknown committed
8330
/**
8331
  Initialize MySQL global variables to default values.
unknown's avatar
unknown committed
8332

unknown's avatar
unknown committed
8333
  @note
unknown's avatar
unknown committed
8334 8335 8336 8337
    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
8338

8339
    We don't need to set variables refered to in my_long_options
unknown's avatar
unknown committed
8340 8341
    as these are initialized by my_getopt.
*/
unknown's avatar
unknown committed
8342

8343
static int mysql_init_variables(void)
unknown's avatar
unknown committed
8344 8345 8346 8347
{
  /* Things reset to zero */
  opt_skip_slave_start= opt_reckless_slave = 0;
  mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
8348
#if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH)
8349
  /*  We can only test for sub paths if my_symlink.c is using realpath */
8350
  myisam_test_invalid_symlink= test_if_data_home_dir;
8351
#endif
Monty's avatar
Monty committed
8352
  opt_log= 0;
8353
  opt_bin_log= opt_bin_log_used= 0;
unknown's avatar
unknown committed
8354
  opt_disable_networking= opt_skip_show_db=0;
8355
  opt_skip_name_resolve= 0;
8356
  opt_ignore_builtin_innodb= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
8357
  opt_logname= opt_binlog_index_name= opt_slow_logname= 0;
8358
  opt_log_basename= 0;
unknown's avatar
Merge  
unknown committed
8359
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
8360 8361
  opt_secure_auth= 0;
  opt_bootstrap= opt_myisam_log= 0;
unknown's avatar
unknown committed
8362
  mqh_used= 0;
8363
  kill_in_progress= 0;
unknown's avatar
unknown committed
8364 8365 8366 8367 8368 8369 8370
  cleanup_done= 0;
  server_id_supplied= 0;
  test_flags= select_errors= dropping_tables= ha_open_options=0;
  thread_count= thread_running= kill_cached_threads= wake_thread=0;
  slave_open_temp_tables= 0;
  cached_thread_count= 0;
  opt_endinfo= using_udf_functions= 0;
8371
  opt_using_transactions= 0;
unknown's avatar
unknown committed
8372 8373
  abort_loop= select_thread_in_use= signal_thread_in_use= 0;
  ready_to_exit= shutdown_in_progress= grant_option= 0;
unknown's avatar
Merge  
unknown committed
8374
  aborted_threads= aborted_connects= 0;
unknown's avatar
unknown committed
8375
  subquery_cache_miss= subquery_cache_hit= 0;
unknown's avatar
unknown committed
8376 8377
  delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
  delayed_insert_errors= thread_created= 0;
unknown's avatar
Merge  
unknown committed
8378
  specialflag= 0;
8379
  binlog_cache_use=  binlog_cache_disk_use= 0;
unknown's avatar
unknown committed
8380 8381
  max_used_connections= slow_launch_threads = 0;
  mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
8382
  prepared_stmt_count= 0;
8383
  mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
8384
  bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
unknown's avatar
Merge  
unknown committed
8385
  bzero((char *) &global_status_var, sizeof(global_status_var));
8386
  opt_large_pages= 0;
8387
  opt_super_large_pages= 0;
8388 8389 8390
#if defined(ENABLED_DEBUG_SYNC)
  opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
8391
  key_map_full.set_all();
unknown's avatar
unknown committed
8392

8393 8394 8395 8396 8397
  /* 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
8398
  character_set_filesystem= &my_charset_bin;
8399

unknown's avatar
unknown committed
8400
  opt_specialflag= SPECIAL_ENGLISH;
8401
  unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
8402 8403 8404 8405 8406
  mysql_home_ptr= mysql_home;
  pidfile_name_ptr= pidfile_name;
  log_error_file_ptr= log_error_file;
  protocol_version= PROTOCOL_VERSION;
  what_to_log= ~ (1L << (uint) COM_TIME);
8407
  denied_connections= 0;
8408
  executed_events= 0;
8409
  global_query_id= thread_id= 1L;
8410
  my_atomic_rwlock_init(&global_query_id_lock);
8411
  my_atomic_rwlock_init(&thread_running_lock);
Michael Widenius's avatar
Michael Widenius committed
8412
  my_atomic_rwlock_init(&thread_count_lock);
8413
  my_atomic_rwlock_init(&statistics_lock);
8414
  my_atomic_rwlock_init(&slave_executed_entries_lock);
unknown's avatar
unknown committed
8415 8416 8417
  strmov(server_version, MYSQL_SERVER_VERSION);
  threads.empty();
  thread_cache.empty();
8418
  key_caches.empty();
unknown's avatar
unknown committed
8419
  if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
8420
                                                default_key_cache_base.length)))
8421 8422 8423 8424
  {
    sql_print_error("Cannot allocate the keycache");
    return 1;
  }
8425

8426 8427
  /* set key_cache_hash.default_value = dflt_key_cache */
  multi_keycache_init();
unknown's avatar
unknown committed
8428 8429

  /* Set directory paths */
8430
  mysql_real_data_home_len=
8431 8432
    strmake_buf(mysql_real_data_home,
                get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home;
unknown's avatar
unknown committed
8433 8434
  /* Replication parameters */
  master_info_file= (char*) "master.info",
unknown's avatar
unknown committed
8435
    relay_log_info_file= (char*) "relay-log.info";
unknown's avatar
unknown committed
8436 8437
  report_user= report_password = report_host= 0;	/* TO BE DELETED */
  opt_relay_logname= opt_relaylog_index_name= 0;
8438
  slave_retried_transactions= 0;
unknown's avatar
unknown committed
8439 8440 8441

  /* Variables in libraries */
  charsets_dir= 0;
8442
  default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
8443
  default_collation_name= compiled_default_collation_name;
unknown's avatar
unknown committed
8444
  character_set_filesystem_name= (char*) "binary";
8445
  lc_messages= (char*) "en_US";
8446
  lc_time_names_name= (char*) "en_US";
8447
  
unknown's avatar
unknown committed
8448 8449 8450 8451
  /* 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");
8452
  current_dbug_option= default_dbug_option;
unknown's avatar
unknown committed
8453 8454
#endif
  opt_error_log= IF_WIN(1,0);
8455 8456
#ifdef ENABLED_PROFILING
    have_profiling = SHOW_OPTION_YES;
8457
#else
8458
    have_profiling = SHOW_OPTION_NO;
8459
#endif
8460

unknown's avatar
unknown committed
8461
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8462
  have_ssl=SHOW_OPTION_YES;
8463 8464
#if HAVE_YASSL
  have_openssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8465
#else
8466 8467 8468 8469
  have_openssl= SHOW_OPTION_YES;
#endif
#else
  have_openssl= have_ssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8470
#endif
unknown's avatar
unknown committed
8471
#ifdef HAVE_BROKEN_REALPATH
unknown's avatar
unknown committed
8472 8473 8474 8475
  have_symlink=SHOW_OPTION_NO;
#else
  have_symlink=SHOW_OPTION_YES;
#endif
8476 8477 8478 8479 8480
#ifdef HAVE_DLOPEN
  have_dlopen=SHOW_OPTION_YES;
#else
  have_dlopen=SHOW_OPTION_NO;
#endif
unknown's avatar
unknown committed
8481 8482 8483 8484 8485
#ifdef HAVE_QUERY_CACHE
  have_query_cache=SHOW_OPTION_YES;
#else
  have_query_cache=SHOW_OPTION_NO;
#endif
8486 8487 8488 8489 8490 8491 8492 8493 8494 8495
#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
8496 8497 8498 8499 8500 8501
#ifdef HAVE_CRYPT
  have_crypt=SHOW_OPTION_YES;
#else
  have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
8502
  have_compress= SHOW_OPTION_YES;
unknown's avatar
unknown committed
8503
#else
8504
  have_compress= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8505 8506 8507 8508 8509 8510
#endif
#ifdef HAVE_LIBWRAP
  libwrapName= NullS;
#endif
#ifdef HAVE_OPENSSL
  des_key_file = 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8511
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
8512
  ssl_acceptor_fd= 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8513 8514
#endif /* ! EMBEDDED_LIBRARY */
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
8515 8516 8517 8518
#ifdef HAVE_SMEM
  shared_memory_base_name= default_shared_memory_base_name;
#endif

8519 8520
#if defined(__WIN__)
  /* Allow Win32 users to move MySQL anywhere */
unknown's avatar
unknown committed
8521 8522
  {
    char prg_dev[LIBLEN];
8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533
    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
8534 8535 8536 8537 8538
    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
    cleanup_dirname(mysql_home,prg_dev);
  }
#else
  const char *tmpenv;
unknown's avatar
unknown committed
8539
  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
unknown's avatar
unknown committed
8540
    tmpenv = DEFAULT_MYSQL_HOME;
8541
  strmake_buf(mysql_home, tmpenv);
8542
#endif
8543

Sergei Golubchik's avatar
Sergei Golubchik committed
8544
  if (wsrep_init_vars())
8545
    return 1;
8546

8547
  return 0;
unknown's avatar
unknown committed
8548 8549
}

8550 8551 8552 8553
my_bool
mysqld_get_one_option(int optid,
                      const struct my_option *opt __attribute__((unused)),
                      char *argument)
unknown's avatar
unknown committed
8554
{
8555 8556
  switch(optid) {
  case '#':
8557
#ifndef DBUG_OFF
8558 8559 8560
    if (!argument)
      argument= (char*) default_dbug_option;
    if (argument[0] == '0' && !argument[1])
unknown's avatar
unknown committed
8561 8562 8563 8564
    {
      DEBUGGER_OFF;
      break;
    }
8565
    DEBUGGER_ON;
8566
    if (argument[0] == '1' && !argument[1])
unknown's avatar
unknown committed
8567
      break;
8568
    DBUG_SET_INITIAL(argument);
8569
    opt_endinfo=1;				/* unireg: memory allocation */
8570 8571
#else
    sql_print_warning("'%s' is disabled in this build", opt->name);
8572
#endif
8573
    break;
8574
  case OPT_DEPRECATED_OPTION:
Sergei Golubchik's avatar
Sergei Golubchik committed
8575 8576
    sql_print_warning("'%s' is deprecated. It does nothing and exists only "
                      "for compatiblity with old my.cnf files.",
8577 8578
                      opt->name);
    break;
8579 8580 8581 8582 8583 8584 8585 8586
  case OPT_MYSQL_COMPATIBILITY:
    sql_print_warning("'%s' is MySQL 5.6 compatible option. Not used or needed "
                      "in MariaDB.", opt->name);
    break;
  case OPT_MYSQL_TO_BE_IMPLEMENTED:
    sql_print_warning("'%s' is MySQL 5.6 compatible option. To be implemented "
                      "in later versions.", opt->name);
    break;
8587
  case 'a':
8588
    global_system_variables.sql_mode= MODE_ANSI;
unknown's avatar
unknown committed
8589
    global_system_variables.tx_isolation= ISO_SERIALIZABLE;
8590 8591
    break;
  case 'b':
8592
    strmake_buf(mysql_home, argument);
8593
    break;
8594
  case 'C':
8595 8596
    if (default_collation_name == compiled_default_collation_name)
      default_collation_name= 0;
8597
    break;
8598
  case 'h':
8599
    strmake_buf(mysql_real_data_home, argument);
8600
    /* Correct pointer set by my_getopt (for embedded library) */
8601
    mysql_real_data_home_ptr= mysql_real_data_home;
8602
    break;
8603
  case 'u':
8604
    if (!mysqld_user || !strcmp(mysqld_user, argument))
unknown's avatar
unknown committed
8605
      mysqld_user= argument;
8606
    else
8607
      sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
8608
    break;
8609
  case 'L':
8610
    strmake_buf(lc_messages_dir, argument);
8611
    break;
8612 8613
  case OPT_BINLOG_FORMAT:
    binlog_format_used= true;
8614
    break;
8615
#include <sslopt-case.h>
8616
#ifndef EMBEDDED_LIBRARY
8617 8618
  case 'V':
    print_version();
8619 8620
    opt_abort= 1;                    // Abort after parsing all options
    break;
8621
#endif /*EMBEDDED_LIBRARY*/
8622 8623 8624 8625 8626 8627 8628 8629
  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;
8630 8631 8632 8633 8634 8635 8636 8637
  case 'T':
    test_flags= argument ? (uint) atoi(argument) : 0;
    opt_endinfo=1;
    break;
  case (int) OPT_ISAM_LOG:
    opt_myisam_log=1;
    break;
  case (int) OPT_BIN_LOG:
8638
    opt_bin_log= MY_TEST(argument != disabled_my_option);
8639
    opt_bin_log_used= 1;
8640
    break;
8641 8642 8643 8644 8645 8646 8647 8648
  case (int) OPT_LOG_BASENAME:
  {
    if (opt_log_basename[0] == 0 || strchr(opt_log_basename, FN_EXTCHAR) ||
        strchr(opt_log_basename,FN_LIBCHAR))
    {
      sql_print_error("Wrong argument for --log-basename. It can't be empty or contain '.' or '" FN_DIRSEP "'");
      return 1;
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
8649 8650
    if (log_error_file_ptr != disabled_my_option)
      log_error_file_ptr= opt_log_basename;
8651

Sergei Golubchik's avatar
Sergei Golubchik committed
8652 8653 8654 8655 8656 8657
    make_default_log_name(&opt_logname, ".log", false);
    make_default_log_name(&opt_slow_logname, "-slow.log", false);
    make_default_log_name(&opt_bin_logname, "-bin", true);
    make_default_log_name(&opt_binlog_index_name, "-bin.index", true);
    make_default_log_name(&opt_relay_logname, "-relay-bin", true);
    make_default_log_name(&opt_relaylog_index_name, "-relay-bin.index", true);
8658 8659 8660 8661 8662 8663 8664

    pidfile_name_ptr= pidfile_name;
    strmake(pidfile_name, argument, sizeof(pidfile_name)-5);
    strmov(fn_ext(pidfile_name),".pid");

    /* check for errors */
    if (!opt_bin_logname || !opt_relaylog_index_name || ! opt_logname ||
Sergei Golubchik's avatar
Sergei Golubchik committed
8665
        ! opt_slow_logname || !pidfile_name_ptr)
8666 8667 8668
      return 1;                                 // out of memory error
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8669
#ifdef HAVE_REPLICATION
8670
  case (int)OPT_REPLICATE_IGNORE_DB:
8671
  {
8672
    cur_rpl_filter->add_ignore_db(argument);
8673 8674 8675 8676
    break;
  }
  case (int)OPT_REPLICATE_DO_DB:
  {
8677
    cur_rpl_filter->add_do_db(argument);
8678 8679 8680 8681
    break;
  }
  case (int)OPT_REPLICATE_REWRITE_DB:
  {
8682
    /* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */
8683
    char* key = argument,*p, *val;
8684

8685
    if (!(p= strstr(argument, "->")))
8686
    {
8687 8688
      sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
      return 1;
8689
    }
8690
    val= p--;
unknown's avatar
unknown committed
8691
    while (my_isspace(mysqld_charset, *p) && p > argument)
8692 8693
      *p-- = 0;
    if (p == argument)
8694
    {
8695 8696
      sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
      return 1;
8697
    }
8698 8699
    *val= 0;
    val+= 2;
unknown's avatar
unknown committed
8700
    while (*val && my_isspace(mysqld_charset, *val))
8701
      val++;
8702
    if (!*val)
8703
    {
8704 8705
      sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
      return 1;
8706 8707
    }

8708
    cur_rpl_filter->add_db_rewrite(key, val);
8709 8710 8711
    break;
  }

8712
  case (int)OPT_BINLOG_IGNORE_DB:
8713
  {
8714
    binlog_filter->add_ignore_db(argument);
8715 8716
    break;
  }
8717
  case (int)OPT_BINLOG_DO_DB:
8718
  {
8719
    binlog_filter->add_do_db(argument);
8720 8721
    break;
  }
8722
  case (int)OPT_REPLICATE_DO_TABLE:
8723
  {
8724
    if (cur_rpl_filter->add_do_table(argument))
8725
    {
8726 8727
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
8728
    }
8729 8730
    break;
  }
8731
  case (int)OPT_REPLICATE_WILD_DO_TABLE:
8732
  {
8733
    if (cur_rpl_filter->add_wild_do_table(argument))
8734
    {
8735 8736
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
8737
    }
8738 8739
    break;
  }
8740
  case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
8741
  {
8742
    if (cur_rpl_filter->add_wild_ignore_table(argument))
8743
    {
8744 8745
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
8746
    }
8747 8748
    break;
  }
8749
  case (int)OPT_REPLICATE_IGNORE_TABLE:
8750
  {
8751
    if (cur_rpl_filter->add_ignore_table(argument))
8752
    {
8753 8754
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
8755
    }
8756 8757
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8758
#endif /* HAVE_REPLICATION */
8759
  case (int) OPT_SAFE:
8760
    opt_specialflag|= SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC;
8761
    delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
8762 8763
    myisam_recover_options= HA_RECOVER_DEFAULT;
    ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
unknown's avatar
unknown committed
8764
#ifdef HAVE_QUERY_CACHE
8765 8766
    query_cache_size=0;
#endif
8767 8768
    sql_print_warning("The syntax '--safe-mode' is deprecated and will be "
                      "removed in a future release.");
8769 8770 8771 8772 8773
    break;
  case (int) OPT_SKIP_HOST_CACHE:
    opt_specialflag|= SPECIAL_NO_HOST_CACHE;
    break;
  case (int) OPT_SKIP_RESOLVE:
8774
    opt_skip_name_resolve= 1;
8775 8776 8777 8778 8779
    opt_specialflag|=SPECIAL_NO_RESOLVE;
    break;
  case (int) OPT_WANT_CORE:
    test_flags |= TEST_CORE_ON_SIGNAL;
    break;
8780 8781 8782 8783
  case OPT_CONSOLE:
    if (opt_console)
      opt_error_log= 0;			// Force logs to stdout
    break;
8784 8785 8786 8787 8788
  case OPT_BOOTSTRAP:
    opt_noacl=opt_bootstrap=1;
    break;
  case OPT_SERVER_ID:
    server_id_supplied = 1;
8789
    ::server_id= global_system_variables.server_id;
8790
    break;
unknown's avatar
unknown committed
8791
  case OPT_LOWER_CASE_TABLE_NAMES:
8792
    lower_case_table_names_used= 1;
unknown's avatar
unknown committed
8793
    break;
8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809
#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) */
8810 8811 8812 8813 8814 8815 8816 8817
  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;
8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831
  case OPT_IGNORE_DB_DIRECTORY:
    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;
8832 8833 8834 8835 8836 8837 8838

  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;
8839 8840 8841
  case OPT_MAX_LONG_DATA_SIZE:
    max_long_data_size_used= true;
    break;
8842 8843
  case OPT_PFS_INSTRUMENT:
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
8844
#ifndef EMBEDDED_LIBRARY
8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907
    /* 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;
    }
8908
#endif /* EMBEDDED_LIBRARY */
8909 8910
#endif
    break;
unknown's avatar
unknown committed
8911
  }
8912 8913
  return 0;
}
8914

8915

unknown's avatar
unknown committed
8916
/** Handle arguments for multiple key caches. */
8917

8918
C_MODE_START
8919

8920
static void*
8921
mysql_getopt_value(const char *name, uint length,
8922
		   const struct my_option *option, int *error)
8923
{
8924 8925
  if (error)
    *error= 0;
8926 8927
  switch (option->id) {
  case OPT_KEY_BUFFER_SIZE:
unknown's avatar
unknown committed
8928
  case OPT_KEY_CACHE_BLOCK_SIZE:
8929 8930
  case OPT_KEY_CACHE_DIVISION_LIMIT:
  case OPT_KEY_CACHE_AGE_THRESHOLD:
8931
  case OPT_KEY_CACHE_PARTITIONS:
8932
  {
unknown's avatar
unknown committed
8933
    KEY_CACHE *key_cache;
8934
    if (!(key_cache= get_or_create_key_cache(name, length)))
8935 8936 8937 8938 8939
    {
      if (error)
        *error= EXIT_OUT_OF_MEMORY;
      return 0;
    }
8940 8941
    switch (option->id) {
    case OPT_KEY_BUFFER_SIZE:
8942
      return &key_cache->param_buff_size;
8943
    case OPT_KEY_CACHE_BLOCK_SIZE:
8944
      return &key_cache->param_block_size;
8945
    case OPT_KEY_CACHE_DIVISION_LIMIT:
8946
      return &key_cache->param_division_limit;
8947
    case OPT_KEY_CACHE_AGE_THRESHOLD:
8948
      return &key_cache->param_age_threshold;
8949 8950
    case OPT_KEY_CACHE_PARTITIONS:
      return (uchar**) &key_cache->param_partitions;
8951
    }
8952
  }
8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968
  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:
  {
    /* 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;
    }
    return 0;
  }
8969
  }
8970
  return option->value;
8971 8972
}

8973
static void option_error_reporter(enum loglevel level, const char *format, ...)
unknown's avatar
unknown committed
8974
{
8975
  va_list args;
unknown's avatar
unknown committed
8976
  va_start(args, format);
8977 8978 8979 8980 8981 8982 8983

  /* 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
8984
  va_end(args);
unknown's avatar
unknown committed
8985
}
8986

8987
C_MODE_END
unknown's avatar
unknown committed
8988

unknown's avatar
unknown committed
8989
/**
Marc Alff's avatar
Marc Alff committed
8990 8991 8992 8993 8994 8995
  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
8996 8997 8998
  @todo
  - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
*/
Marc Alff's avatar
Marc Alff committed
8999
static int get_options(int *argc_ptr, char ***argv_ptr)
9000 9001 9002
{
  int ho_error;

9003
  my_getopt_register_get_addr(mysql_getopt_value);
9004
  my_getopt_error_reporter= option_error_reporter;
unknown's avatar
unknown committed
9005

Marc Alff's avatar
Marc Alff committed
9006 9007 9008
  /* prepare all_options array */
  my_init_dynamic_array(&all_options, sizeof(my_option),
                        array_elements(my_long_options),
9009
                        array_elements(my_long_options)/4, MYF(0));
9010
  add_many_options(&all_options, my_long_options, array_elements(my_long_options));
9011
  sys_var_add_options(&all_options, 0);
Marc Alff's avatar
Marc Alff committed
9012
  add_terminator(&all_options);
9013

unknown's avatar
unknown committed
9014 9015 9016
  /* Skip unknown options so that they may be processed later by plugins */
  my_getopt_skip_unknown= TRUE;

Marc Alff's avatar
Marc Alff committed
9017
  if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer),
9018
                                mysqld_get_one_option)))
9019
    return ho_error;
9020 9021 9022

  if (!opt_help)
    delete_dynamic(&all_options);
9023 9024
  else
    opt_abort= 1;
9025

Marc Alff's avatar
Marc Alff committed
9026 9027 9028
  /* Add back the program name handle_options removes */
  (*argc_ptr)++;
  (*argv_ptr)--;
9029

9030 9031 9032 9033 9034 9035
  /*
    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.
  */
9036

9037 9038
  if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
       opt_log_slow_slave_statements) &&
Monty's avatar
Monty committed
9039
      !global_system_variables.sql_log_slow)
9040
    sql_print_warning("options --log-slow-admin-statements, --log-queries-not-using-indexes and --log-slow-slave-statements have no effect if --log_slow_queries is not set");
9041 9042 9043 9044 9045 9046 9047 9048
  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);
  }
9049

9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068
  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))
  {
    sql_print_error("Invalid ft-boolean-syntax string: %s\n",
                    ft_boolean_syntax);
    return 1;
  }

  if (opt_disable_networking)
Sergei Golubchik's avatar
Sergei Golubchik committed
9069
    mysqld_port= mysqld_extra_port= 0;
9070

9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086
  if (opt_skip_show_db)
    opt_specialflag|= SPECIAL_SKIP_SHOW_DB;

  if (myisam_flush)
    flush_time= 0;

#ifdef HAVE_REPLICATION
  if (opt_slave_skip_errors)
    init_slave_skip_errors(opt_slave_skip_errors);
#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;

9087 9088 9089 9090 9091 9092
  // 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;
9093 9094 9095

  global_system_variables.sql_mode=
    expand_sql_mode(global_system_variables.sql_mode);
Sergei Golubchik's avatar
Sergei Golubchik committed
9096
#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH)
9097 9098 9099 9100 9101 9102 9103 9104 9105 9106
  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
9107 9108 9109
  if (opt_debugging)
  {
    /* Allow break with SIGINT, no core or stack trace */
Michael Widenius's avatar
Michael Widenius committed
9110 9111
    test_flags|= TEST_SIGINT;
    opt_stack_trace= 1;
9112 9113
    test_flags&= ~TEST_CORE_ON_SIGNAL;
  }
9114
  /* Set global MyISAM variables from delay_key_write_options */
9115
  fix_delay_key_write(0, 0, OPT_GLOBAL);
9116

9117
#ifndef EMBEDDED_LIBRARY
9118 9119
  if (mysqld_chroot)
    set_root(mysqld_chroot);
9120
#else
9121
  thread_handling = SCHEDULER_NO_THREADS;
9122 9123
  max_allowed_packet= global_system_variables.max_allowed_packet;
  net_buffer_length= global_system_variables.net_buffer_length;
9124
#endif
9125 9126
  if (fix_paths())
    return 1;
unknown's avatar
unknown committed
9127

unknown's avatar
unknown committed
9128 9129 9130 9131
  /*
    Set some global variables from the global_system_variables
    In most cases the global variables will not be used
  */
9132
  my_disable_locking= myisam_single_user= MY_TEST(opt_external_locking == 0);
unknown's avatar
unknown committed
9133
  my_default_record_cache_size=global_system_variables.read_buff_size;
unknown's avatar
unknown committed
9134

9135
  /*
9136 9137 9138
    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.
9139 9140 9141 9142 9143 9144
  */
  if (global_system_variables.log_warnings >= 10)
    my_global_flags= MY_WME | ME_JUST_INFO;
  /* Log all errors not handled by thd->handle_error() to my_message_sql() */
  if (global_system_variables.log_warnings >= 11)
    my_global_flags|= ME_NOREFRESH;
9145 9146
  if (my_assert_on_error)
    debug_assert_if_crashed_table= 1;
9147

9148
  global_system_variables.long_query_time= (ulonglong)
Monty's avatar
Monty committed
9149 9150 9151
    (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);
9152

9153 9154
  if (opt_short_log_format)
    opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
9155

9156
  if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
9157
                                  &global_date_format) ||
9158
      init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
9159
                                  &global_time_format) ||
9160
      init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
9161
                                  &global_datetime_format))
9162
    return 1;
9163

unknown's avatar
unknown committed
9164
#ifdef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
9165 9166
  one_thread_scheduler(thread_scheduler);
  one_thread_scheduler(extra_thread_scheduler);
unknown's avatar
unknown committed
9167
#else
9168 9169 9170 9171 9172 9173 9174 9175

#ifdef _WIN32
  /* workaround: disable thread pool on XP */
  if (GetProcAddress(GetModuleHandle("kernel32"),"CreateThreadpool") == 0 &&
      thread_handling > SCHEDULER_NO_THREADS)
    thread_handling = SCHEDULER_ONE_THREAD_PER_CONNECTION;
#endif

9176
  if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
Sergei Golubchik's avatar
Sergei Golubchik committed
9177
    one_thread_per_connection_scheduler(thread_scheduler, &max_connections,
9178
                                        &connection_count);
9179
  else if (thread_handling == SCHEDULER_NO_THREADS)
Sergei Golubchik's avatar
Sergei Golubchik committed
9180
    one_thread_scheduler(thread_scheduler);
unknown's avatar
unknown committed
9181
  else
9182 9183 9184
    pool_of_threads_scheduler(thread_scheduler,  &max_connections,
                                        &connection_count); 

Sergei Golubchik's avatar
Sergei Golubchik committed
9185
  one_thread_per_connection_scheduler(extra_thread_scheduler,
9186 9187
                                      &extra_max_connections,
                                      &extra_connection_count);
unknown's avatar
unknown committed
9188
#endif
9189

9190 9191
  opt_readonly= read_only;

9192 9193 9194 9195 9196 9197 9198
  /*
    If max_long_data_size is not specified explicitly use
    value of max_allowed_packet.
  */
  if (!max_long_data_size_used)
    max_long_data_size= global_system_variables.max_allowed_packet;

9199
  /* Remember if max_user_connections was 0 at startup */
Sergei Golubchik's avatar
Sergei Golubchik committed
9200
  max_user_connections_checking= global_system_variables.max_user_connections != 0;
9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212

  {
    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)
      global_system_variables.max_relay_log_size= max_binlog_size;

    /*
      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
9213 9214
    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
9215 9216 9217 9218 9219 9220 9221
    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;
    }
9222
  }
9223 9224 9225 9226 9227 9228 9229

  /* Ensure that some variables are not set higher than needed */
  if (back_log > max_connections)
    back_log= max_connections;
  if (thread_cache_size > max_connections)
    thread_cache_size= max_connections;
  
9230
  return 0;
unknown's avatar
unknown committed
9231 9232 9233
}


9234 9235 9236 9237 9238 9239 9240
/*
  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)
*/

Michael Widenius's avatar
Michael Widenius committed
9241
void set_server_version(void)
9242 9243
{
  char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
9244
                     MYSQL_SERVER_SUFFIX_STR, NullS);
9245 9246 9247
#ifdef EMBEDDED_LIBRARY
  end= strmov(end, "-embedded");
#endif
9248 9249 9250
#ifdef WITH_WSREP
  end= strmov(end, "-wsrep");
#endif
9251
#ifndef DBUG_OFF
9252
  if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
9253 9254
    end= strmov(end, "-debug");
#endif
Monty's avatar
Monty committed
9255
  if (opt_log || global_system_variables.sql_log_slow || opt_bin_log)
9256 9257 9258 9259
    strmov(end, "-log");                        // This may slow down system
}


unknown's avatar
unknown committed
9260 9261 9262
static char *get_relative_path(const char *path)
{
  if (test_if_hard_path(path) &&
9263
      is_prefix(path,DEFAULT_MYSQL_HOME) &&
unknown's avatar
unknown committed
9264 9265
      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
  {
unknown's avatar
unknown committed
9266
    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
9267
    while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
unknown's avatar
unknown committed
9268 9269 9270 9271 9272 9273
      path++;
  }
  return (char*) path;
}


unknown's avatar
unknown committed
9274
/**
9275 9276
  Fix filename and replace extension where 'dir' is relative to
  mysql_real_data_home.
unknown's avatar
unknown committed
9277 9278
  @return
    1 if len(path) > FN_REFLEN
9279 9280 9281
*/

bool
9282
fn_format_relative_to_data_home(char * to, const char *name,
9283 9284 9285 9286 9287 9288 9289 9290 9291 9292
				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,
9293
		    MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
9294 9295 9296
}


9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310
/**
  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];
9311
  size_t opt_secure_file_priv_len;
9312 9313 9314 9315 9316 9317
  /*
    All paths are secure if opt_secure_file_path is 0
  */
  if (!opt_secure_file_priv)
    return TRUE;

9318 9319
  opt_secure_file_priv_len= strlen(opt_secure_file_priv);

Georgi Kodinov's avatar
Georgi Kodinov committed
9320 9321 9322
  if (strlen(path) >= FN_REFLEN)
    return FALSE;

9323 9324 9325 9326 9327
  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
9328
    size_t length= dirname_length(path);        // Guaranteed to be < FN_REFLEN
9329 9330 9331 9332 9333 9334
    memcpy(buff2, path, length);
    buff2[length]= '\0';
    if (length == 0 || my_realpath(buff1, buff2, 0))
      return FALSE;
  }
  convert_dirname(buff2, buff1, NullS);
9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348
  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;
  }
9349 9350 9351
  return TRUE;
}

Michael Widenius's avatar
Michael Widenius committed
9352

9353
static int fix_paths(void)
unknown's avatar
unknown committed
9354
{
9355
  char buff[FN_REFLEN],*pos;
9356 9357
  DBUG_ENTER("fix_paths");

9358
  convert_dirname(mysql_home,mysql_home,NullS);
9359
  /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
9360
  my_realpath(mysql_home,mysql_home,MYF(0));
9361 9362 9363 9364 9365 9366 9367
  /* Ensure that mysql_home ends in FN_LIBCHAR */
  pos=strend(mysql_home);
  if (pos[-1] != FN_LIBCHAR)
  {
    pos[0]= FN_LIBCHAR;
    pos[1]= 0;
  }
9368
  convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
9369
  convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
unknown's avatar
unknown committed
9370 9371
  (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);
9372
  (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
Marc Alff's avatar
Marc Alff committed
9373

Sergei Golubchik's avatar
Sergei Golubchik committed
9374 9375 9376
  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);
9377
  opt_plugin_dir_ptr= opt_plugin_dir;
Sergei Golubchik's avatar
Sergei Golubchik committed
9378
  pidfile_name_ptr= pidfile_name;
unknown's avatar
unknown committed
9379

9380 9381 9382 9383 9384 9385
  my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
  mysql_unpacked_real_data_home_len= 
    (int) strlen(mysql_unpacked_real_data_home);
  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
9386
  char *sharedir=get_relative_path(SHAREDIR);
unknown's avatar
unknown committed
9387
  if (test_if_hard_path(sharedir))
9388
    strmake_buf(buff, sharedir);		/* purecov: tested */
unknown's avatar
unknown committed
9389
  else
unknown's avatar
unknown committed
9390
    strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
9391
  convert_dirname(buff,buff,NullS);
9392
  (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
unknown's avatar
unknown committed
9393 9394

  /* If --character-sets-dir isn't given, use shared library dir */
9395
  if (charsets_dir)
9396
    strmake_buf(mysql_charsets_dir, charsets_dir);
9397
  else
unknown's avatar
unknown committed
9398 9399
    strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
	     CHARSET_DIR, NullS);
unknown's avatar
unknown committed
9400
  (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
9401
  convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
unknown's avatar
unknown committed
9402
  charsets_dir=mysql_charsets_dir;
unknown's avatar
unknown committed
9403

unknown's avatar
unknown committed
9404
  if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
9405
    DBUG_RETURN(1);
9406 9407
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir= mysql_tmpdir;
unknown's avatar
SCRUM  
unknown committed
9408
#ifdef HAVE_REPLICATION
9409
  if (!slave_load_tmpdir)
9410
    slave_load_tmpdir= mysql_tmpdir;
9411
#endif /* HAVE_REPLICATION */
9412 9413 9414
  /*
    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
9415
  */
9416 9417
  if (opt_secure_file_priv)
  {
9418 9419
    if (*opt_secure_file_priv == 0)
    {
9420
      my_free(opt_secure_file_priv);
9421 9422 9423 9424
      opt_secure_file_priv= 0;
    }
    else
    {
9425 9426
      if (strlen(opt_secure_file_priv) >= FN_REFLEN)
        opt_secure_file_priv[FN_REFLEN-1]= '\0';
9427
      if (my_realpath(buff, opt_secure_file_priv, 0))
9428 9429
      {
        sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
9430
        DBUG_RETURN(1);
9431
      }
9432
      char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
9433
      convert_dirname(secure_file_real_path, buff, NullS);
9434
      my_free(opt_secure_file_priv);
9435 9436
      opt_secure_file_priv= secure_file_real_path;
    }
9437
  }
9438
  DBUG_RETURN(0);
unknown's avatar
unknown committed
9439 9440
}

unknown's avatar
unknown committed
9441 9442
/**
  Check if file system used for databases is case insensitive.
9443

unknown's avatar
unknown committed
9444
  @param dir_name			Directory to test
9445

9446 9447 9448
  @retval -1  Don't know (Test failed)
  @retval  0   File system is case sensitive
  @retval  1   File system is case insensitive
9449 9450 9451 9452 9453 9454 9455 9456
*/

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;
9457
  DBUG_ENTER("test_if_case_insensitive");
9458 9459 9460 9461 9462

  fn_format(buff, glob_hostname, dir_name, ".lower-test",
	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
  fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
Marc Alff's avatar
Marc Alff committed
9463 9464 9465
  mysql_file_delete(key_file_casetest, buff2, MYF(0));
  if ((file= mysql_file_create(key_file_casetest,
                               buff, 0666, O_RDWR, MYF(0))) < 0)
9466
  {
9467
    if (!opt_abort)
9468
      sql_print_warning("Can't create test file %s", buff);
9469
    DBUG_RETURN(-1);
9470
  }
Marc Alff's avatar
Marc Alff committed
9471 9472
  mysql_file_close(file, MYF(0));
  if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
9473
    result= 1;					// Can access file
Marc Alff's avatar
Marc Alff committed
9474
  mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
9475 9476
  DBUG_PRINT("exit", ("result: %d", result));
  DBUG_RETURN(result);
9477 9478 9479
}


9480 9481
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
9482 9483 9484
/**
  Create file to store pid number.
*/
9485 9486 9487
static void create_pid_file()
{
  File file;
Marc Alff's avatar
Marc Alff committed
9488 9489
  if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
                               O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
9490
  {
9491
    char buff[MAX_BIGINT_WIDTH + 1], *end;
9492
    end= int10_to_str((long) getpid(), buff, 10);
unknown's avatar
unknown committed
9493
    *end++= '\n';
Marc Alff's avatar
Marc Alff committed
9494 9495
    if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
                          MYF(MY_WME | MY_NABP)))
9496
    {
Marc Alff's avatar
Marc Alff committed
9497
      mysql_file_close(file, MYF(0));
9498
      pid_file_created= true;
9499 9500
      return;
    }
Marc Alff's avatar
Marc Alff committed
9501
    mysql_file_close(file, MYF(0));
9502
  }
9503
  sql_perror("Can't start server: can't create PID file");
unknown's avatar
foo1  
unknown committed
9504
  exit(1);
9505
}
9506
#endif /* EMBEDDED_LIBRARY */
9507

Marc Alff's avatar
Marc Alff committed
9508

9509 9510 9511 9512 9513
/**
  Remove the process' pid file.
  
  @param  flags  file operation flags
*/
Marc Alff's avatar
Marc Alff committed
9514

9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525
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
9526 9527


unknown's avatar
unknown committed
9528
/** Clear most status variables. */
9529 9530
void refresh_status(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
9531
  mysql_mutex_lock(&LOCK_status);
9532

9533
  /* Add thread's status variabes to global status */
9534
  add_to_status(&global_status_var, &thd->status_var);
9535 9536

  /* Reset thread's status variables */
9537
  thd->set_status_var_init();
9538 9539
  bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); 
  thd->start_bytes_received= 0;
9540

9541
  /* Reset some global variables */
unknown's avatar
unknown committed
9542
  reset_status_vars();
9543 9544 9545 9546
#ifdef WITH_WSREP
  if (WSREP_ON)
    wsrep->stats_reset(wsrep);
#endif /* WITH_WSREP */
9547

9548
  /* Reset the counters of all key caches (default and named). */
9549
  process_key_caches(reset_key_cache_counters, 0);
9550
  flush_status_time= time((time_t*) 0);
Marc Alff's avatar
Marc Alff committed
9551
  mysql_mutex_unlock(&LOCK_status);
9552 9553 9554

  /*
    Set max_used_connections to the number of currently open
Michael Widenius's avatar
Michael Widenius committed
9555
    connections.  This is not perfect, but status data is not exact anyway.
9556 9557
  */
  max_used_connections= thread_count-delayed_insert_threads;
9558 9559
}

Sergei Golubchik's avatar
Sergei Golubchik committed
9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592
#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
9593 9594
  { &key_file_init, "init", 0},
  { &key_file_binlog_state, "binlog_state", 0}
Sergei Golubchik's avatar
Sergei Golubchik committed
9595 9596 9597
};
#endif /* HAVE_PSI_INTERFACE */

9598
PSI_stage_info stage_after_apply_event= { 0, "after apply log event", 0};
9599
PSI_stage_info stage_after_create= { 0, "After create", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9600 9601
PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0};
PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0};
9602
PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
9603 9604 9605
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};
9606
PSI_stage_info stage_apply_event= { 0, "apply log event", 0};
9607 9608 9609 9610 9611 9612 9613 9614
PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
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, "cleaning up", 0};
PSI_stage_info stage_closing_tables= { 0, "closing tables", 0};
PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9615
PSI_stage_info stage_converting_heap_to_myisam= { 0, "converting HEAP to " TMP_ENGINE_NAME, 0};
9616 9617 9618 9619 9620 9621 9622 9623 9624 9625
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};
PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", 0};
PSI_stage_info stage_creating_delayed_handler= { 0, "Creating delayed handler", 0};
PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0};
PSI_stage_info stage_creating_table= { 0, "creating table", 0};
PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0};
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};
Sergei Golubchik's avatar
Sergei Golubchik committed
9626
PSI_stage_info stage_enabling_keys= { 0, "enabling keys", 0};
9627 9628 9629 9630
PSI_stage_info stage_end= { 0, "end", 0};
PSI_stage_info stage_executing= { 0, "executing", 0};
PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0};
PSI_stage_info stage_explaining= { 0, "explaining", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9631
PSI_stage_info stage_finding_key_cache= { 0, "Finding key cache", 0};
9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655
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};
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_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};
PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0};
PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0};
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};
PSI_stage_info stage_manage_keys= { 0, "manage keys", 0};
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};
PSI_stage_info stage_optimizing= { 0, "optimizing", 0};
PSI_stage_info stage_preparing= { 0, "preparing", 0};
PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0};
PSI_stage_info stage_query_end= { 0, "query end", 0};
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};
Sergei Golubchik's avatar
Sergei Golubchik committed
9656
PSI_stage_info stage_recreating_table= { 0, "recreating table", 0};
9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668
PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0};
PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0};
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};
PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0};
PSI_stage_info stage_reschedule= { 0, "reschedule", 0};
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};
PSI_stage_info stage_sending_cached_result_to_client= { 0, "sending cached result to client", 0};
PSI_stage_info stage_sending_data= { 0, "Sending data", 0};
PSI_stage_info stage_setup= { 0, "setup", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9669
PSI_stage_info stage_show_explain= { 0, "show explain", 0};
9670
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
9671
PSI_stage_info stage_sorting= { 0, "Sorting", 0};
9672 9673 9674 9675 9676 9677 9678 9679
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};
PSI_stage_info stage_statistics= { 0, "statistics", 0};
PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0 };
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};
PSI_stage_info stage_system_lock= { 0, "System lock", 0};
9680
PSI_stage_info stage_unlocking_tables= { 0, "Unlocking tables", 0};
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 9706 9707 9708 9709 9710
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};
PSI_stage_info stage_user_lock= { 0, "User lock", 0};
PSI_stage_info stage_user_sleep= { 0, "User sleep", 0};
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};
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};
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};
PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0};
PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0};
PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0};
PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0};
PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0};
9711 9712 9713
PSI_stage_info stage_binlog_waiting_background_tasks= { 0, "Waiting for background binlog tasks", 0};
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};
9714
PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0};
9715
PSI_stage_info stage_waiting_for_prior_transaction_to_commit= { 0, "Waiting for prior transaction to start commit before starting next transaction", 0};
Sergei Golubchik's avatar
Sergei Golubchik committed
9716
PSI_stage_info stage_waiting_for_room_in_worker_thread= { 0, "Waiting for room in worker thread event queue", 0};
unknown's avatar
unknown committed
9717 9718
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};
9719
PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master connection to process GTID received on multiple master connections", 0};
9720

9721
#ifdef HAVE_PSI_INTERFACE
9722

9723 9724
PSI_stage_info *all_server_stages[]=
{
9725
  & stage_after_apply_event,
9726
  & stage_after_create,
Sergei Golubchik's avatar
Sergei Golubchik committed
9727 9728
  & stage_after_opening_tables,
  & stage_after_table_lock,
9729
  & stage_allocating_local_table,
Sergei Golubchik's avatar
Sergei Golubchik committed
9730 9731 9732
  & stage_alter_inplace,
  & stage_alter_inplace_commit,
  & stage_alter_inplace_prepare,
9733
  & stage_apply_event,
Sergei Golubchik's avatar
Sergei Golubchik committed
9734 9735 9736
  & stage_binlog_processing_checkpoint_notify,
  & stage_binlog_stopping_background_thread,
  & stage_binlog_waiting_background_tasks,
9737 9738 9739 9740 9741 9742 9743 9744 9745
  & 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,
  & stage_connecting_to_master,
  & stage_converting_heap_to_myisam,
Sergei Golubchik's avatar
Sergei Golubchik committed
9746
  & stage_copy_to_tmp_table,
9747 9748 9749 9750 9751 9752 9753 9754 9755
  & 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
9756
  & stage_enabling_keys,
9757 9758 9759 9760
  & stage_end,
  & stage_executing,
  & stage_execution_of_init_command,
  & stage_explaining,
Sergei Golubchik's avatar
Sergei Golubchik committed
9761
  & stage_finding_key_cache,
9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785
  & 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,
  & 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,
  & 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
9786
  & stage_recreating_table,
9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798
  & stage_registering_slave_on_master,
  & stage_removing_duplicates,
  & stage_removing_tmp_table,
  & stage_rename,
  & stage_rename_result_table,
  & stage_requesting_binlog_dump,
  & stage_reschedule,
  & 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
9799
  & stage_show_explain,
Sergei Golubchik's avatar
Sergei Golubchik committed
9800 9801 9802 9803 9804 9805
  & stage_slave_has_read_all_relay_log,
  & stage_slave_waiting_event_from_coordinator,
  & stage_slave_waiting_worker_queue,
  & stage_slave_waiting_worker_to_free_events,
  & stage_slave_waiting_worker_to_release_partition,
  & stage_slave_waiting_workers_to_exit,
Sergei Golubchik's avatar
Sergei Golubchik committed
9806
  & stage_sorting,
9807 9808 9809 9810 9811 9812 9813 9814
  & 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,
9815
  & stage_unlocking_tables,
9816 9817 9818 9819 9820 9821 9822 9823 9824
  & 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
9825
  & stage_waiting_for_gtid_to_be_written_to_binary_log,
9826 9827 9828 9829 9830 9831
  & 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
9832 9833 9834 9835
  & stage_waiting_for_prior_transaction_to_commit,
  & stage_waiting_for_query_cache_lock,
  & stage_waiting_for_relay_log_space,
  & stage_waiting_for_room_in_worker_thread,
9836 9837 9838 9839 9840
  & 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
9841
  & stage_waiting_for_work_from_sql_thread,
9842
  & stage_waiting_to_finalize_termination,
unknown's avatar
unknown committed
9843 9844
  & stage_waiting_to_get_readlock,
  & stage_master_gtid_wait_primary,
9845 9846
  & stage_master_gtid_wait,
  & stage_gtid_wait_other_connection
9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865
};

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
9866

9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894
  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
9895 9896 9897 9898 9899

  /*
    Register [0 .. COM_QUERY - 1] as "statement/com/..."
  */
  count= (int) COM_QUERY;
9900 9901
  mysql_statement_register(category, com_statement_info, count);

Sergei Golubchik's avatar
Sergei Golubchik committed
9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913
  /*
    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);

9914 9915
  /*
    When a new packet is received,
Sergei Golubchik's avatar
Sergei Golubchik committed
9916
    it is instrumented as "statement/abstract/new_packet".
9917 9918
    Based on the packet type found, it later mutates to the
    proper narrow type, for example
Sergei Golubchik's avatar
Sergei Golubchik committed
9919 9920
    "statement/abstract/query" or "statement/com/ping".
    In cases of "statement/abstract/query", SQL queries are given to
9921 9922 9923 9924
    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
9925
  stmt_info_new_packet.m_name= "new_packet";
9926
  stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE;
Sergei Golubchik's avatar
Sergei Golubchik committed
9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937
  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
9938
#endif
9939
}
Marc Alff's avatar
Marc Alff committed
9940

9941
#endif /* HAVE_PSI_INTERFACE */