mysqld.cc 324 KB
Newer Older
Sergei Golubchik's avatar
Sergei Golubchik committed
1 2
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
   Copyright (c) 2008, 2012, Monty Program 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
#include "sql_callback.h"
75
#include "threadpool.h"
76

Marc Alff's avatar
Marc Alff committed
77 78 79
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
#include "../storage/perfschema/pfs_server.h"
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
80 81 82 83
#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
84

85
#include "keycaches.h"
86
#include "../storage/myisam/ha_myisam.h"
87
#include "set_var.h"
88

89 90
#include "rpl_injector.h"

He Zhenxing's avatar
He Zhenxing committed
91 92
#include "rpl_handler.h"

93 94
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
95 96
#endif

unknown's avatar
unknown committed
97 98
#include <thr_alarm.h>
#include <ft_global.h>
99
#include <errmsg.h>
unknown's avatar
Merge  
unknown committed
100 101
#include "sp_rcontext.h"
#include "sp_cache.h"
102
#include "sql_reload.h"  // reload_acl_and_cache
unknown's avatar
unknown committed
103

104 105
#ifdef HAVE_POLL_H
#include <poll.h>
106 107
#endif

unknown's avatar
unknown committed
108
#define mysqld_charset &my_charset_latin1
109

110
/* We have HAVE_valgrind below as this speeds up the shutdown of MySQL */
111

112
#if defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_valgrind) && defined(__linux__)
unknown's avatar
unknown committed
113
#define HAVE_CLOSE_SERVER_SOCK 1
114
#endif
unknown's avatar
unknown committed
115

unknown's avatar
unknown committed
116 117 118 119
extern "C" {					// Because of SCO 3.2V4.2
#include <errno.h>
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
120
#define __GNU_LIBRARY__				// Skip warnings in getopt.h
unknown's avatar
unknown committed
121
#endif
122
#include <my_getopt.h>
unknown's avatar
unknown committed
123 124 125 126 127 128 129 130 131
#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
132
#include <my_net.h>
unknown's avatar
unknown committed
133

134
#if !defined(__WIN__)
unknown's avatar
unknown committed
135 136
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
137
#include <sys/un.h>
unknown's avatar
unknown committed
138 139
#endif
#ifdef HAVE_SELECT_H
140
#include <select.h>
unknown's avatar
unknown committed
141 142 143 144 145
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/utsname.h>
unknown's avatar
unknown committed
146
#endif /* __WIN__ */
unknown's avatar
unknown committed
147

148
#include <my_libwrap.h>
unknown's avatar
unknown committed
149

150 151 152 153
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

154 155 156 157
#ifdef __WIN__ 
#include <crtdbg.h>
#endif

158 159 160 161 162 163 164 165 166 167
#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
168
#ifdef _AIX41
unknown's avatar
unknown committed
169
int initgroups(const char *,unsigned int);
unknown's avatar
unknown committed
170 171
#endif

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

Sergei Golubchik's avatar
Sergei Golubchik committed
198 199 200 201
#ifndef HAVE_FCNTL
#define fcntl(X,Y,Z) 0
#endif

202 203 204
extern "C" my_bool reopen_fstreams(const char *filename,
                                   FILE *outstream, FILE *errstream);

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

#ifdef HAVE_FEDISABLEEXCEPT
  fedisableexcept(FE_ALL_EXCEPT);
#endif
225

226 227 228 229
#ifdef HAVE_FESETROUND
    /* Set FPU rounding mode to "round-to-nearest" */
  fesetround(FE_TONEAREST);
#endif /* HAVE_FESETROUND */
230 231

  /*
232 233 234 235
    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.
236
  */
237
#if defined(__i386__) && !defined(__SSE2_MATH__)
238 239 240 241 242 243 244 245 246 247 248 249
#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__ */

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

unknown's avatar
unknown committed
259 260
} /* cplusplus */

unknown's avatar
unknown committed
261
#define MYSQL_KILL_SIGNAL SIGTERM
unknown's avatar
unknown committed
262 263 264 265 266 267 268

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

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

269
extern "C" sig_handler handle_fatal_signal(int sig);
270

271 272 273
#if defined(__linux__)
#define ENABLE_TEMP_POOL 1
#else
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
274
#define ENABLE_TEMP_POOL 0
275 276
#endif

unknown's avatar
unknown committed
277
/* Constants */
278

279 280
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE

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

unknown's avatar
unknown committed
283 284 285 286 287 288 289 290 291
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
292

unknown's avatar
unknown committed
293
const char *first_keyword= "first", *binary_keyword= "BINARY";
unknown's avatar
unknown committed
294
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
295

unknown's avatar
unknown committed
296
bool opt_large_files= sizeof(my_off_t) > 4;
297
static my_bool opt_autocommit; ///< for --autocommit command-line option
298 299 300 301

/*
  Used with --help for detailed option
*/
302
static my_bool opt_verbose= 0;
303

304
arg_cmp_func Arg_comparator::comparator_matrix[6][2] =
305 306 307
{{&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
308
 {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
309 310
 {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal},
 {&Arg_comparator::compare_datetime,   &Arg_comparator::compare_e_datetime}};
unknown's avatar
unknown committed
311

unknown's avatar
unknown committed
312 313
/* static variables */

Marc Alff's avatar
Marc Alff committed
314 315 316
#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
317
static PSI_cond_key key_COND_handler_count;
Marc Alff's avatar
Marc Alff committed
318 319 320 321 322 323 324 325 326 327 328 329 330
#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__ */
331 332 333 334

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

337 338 339 340
#ifdef HAVE_NPTL
volatile sig_atomic_t ld_assume_kernel_is_set= 0;
#endif

341
/* the default log output is log tables */
unknown's avatar
unknown committed
342
static bool lower_case_table_names_used= 0;
343
static bool max_long_data_size_used= false;
unknown's avatar
unknown committed
344
static bool volatile select_thread_in_use, signal_thread_in_use;
345
static volatile bool ready_to_exit;
unknown's avatar
unknown committed
346 347 348
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
static uint kill_cached_threads, wake_thread;
Michael Widenius's avatar
Michael Widenius committed
349
ulong max_used_connections;
unknown's avatar
unknown committed
350
static volatile ulong cached_thread_count= 0;
351
static char *mysqld_user, *mysqld_chroot;
unknown's avatar
unknown committed
352
static char *default_character_set_name;
unknown's avatar
unknown committed
353
static char *character_set_filesystem_name;
354
static char *lc_messages;
355
static char *lc_time_names_name;
unknown's avatar
unknown committed
356
static char *my_bind_addr_str;
357 358
static char *default_collation_name;
char *default_storage_engine;
359
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
unknown's avatar
unknown committed
360
static I_List<THD> thread_cache;
361 362
static bool binlog_format_used= false;
LEX_STRING opt_init_connect, opt_init_slave;
Marc Alff's avatar
Marc Alff committed
363
static mysql_cond_t COND_thread_cache, COND_flush_thread_cache;
364
static DYNAMIC_ARRAY all_options;
unknown's avatar
unknown committed
365

unknown's avatar
unknown committed
366
/* Global variables */
unknown's avatar
unknown committed
367

368
bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0;
369
my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0, opt_abort;
370
ulonglong log_output_options;
Sergei Golubchik's avatar
Sergei Golubchik committed
371
my_bool opt_userstat_running;
372
my_bool opt_log_queries_not_using_indexes= 0;
373
bool opt_error_log= IF_WIN(1,0);
unknown's avatar
unknown committed
374
bool opt_disable_networking=0, opt_skip_show_db=0;
375
bool opt_skip_name_resolve=0;
376
my_bool opt_character_set_client_handshake= 1;
unknown's avatar
unknown committed
377
bool server_id_supplied = 0;
378
bool opt_endinfo, using_udf_functions;
379
my_bool locked_in_memory;
380
bool opt_using_transactions;
unknown's avatar
unknown committed
381
bool volatile abort_loop;
382
bool volatile shutdown_in_progress;
Sergei Golubchik's avatar
Sergei Golubchik committed
383
uint volatile global_disable_checkpoint;
384 385 386
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
ulong slow_start_timeout;
#endif
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
/*
  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;
402 403 404 405
/**
   @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.
406
   @note This flag is dropped in 5.1
407 408 409
   @see grant_init()
 */
bool volatile grant_option;
unknown's avatar
unknown committed
410

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

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

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

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

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

510 511 512 513 514
/*
  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
515

516 517 518 519
/* Limits for internal temporary tables (MyISAM or Aria) */
uint internal_tmp_table_max_key_length;
uint internal_tmp_table_max_key_segments;

520
bool max_user_connections_checking=0;
unknown's avatar
unknown committed
521
/**
522 523 524 525
  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
526
/**
527 528 529 530 531 532 533 534 535 536
  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
537
ulong thread_id=1L,current_pid;
538
ulong slow_launch_threads = 0;
539 540
uint sync_binlog_period= 0, sync_relaylog_period= 0,
     sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
unknown's avatar
unknown committed
541
ulong expire_logs_days = 0;
unknown's avatar
unknown committed
542
ulong rpl_recovery_rank=0;
543 544 545 546 547
/**
  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
548

549
ulong opt_slave_parallel_threads= 0;
550 551
ulong opt_binlog_commit_wait_count= 0;
ulong opt_binlog_commit_wait_usec= 0;
unknown's avatar
unknown committed
552
ulong opt_slave_parallel_max_queued= 131072;
553

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
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
587

588
time_t server_start_time, flush_status_time;
589

590 591
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
char *default_tz_name;
592
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN], *opt_log_basename;
unknown's avatar
unknown committed
593
char mysql_real_data_home[FN_REFLEN],
594 595
     lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
     mysql_charsets_dir[FN_REFLEN],
596
     *opt_init_file, *opt_tc_log_file;
597
char *lc_messages_dir_ptr= lc_messages_dir, *log_error_file_ptr;
598
char mysql_unpacked_real_data_home[FN_REFLEN];
599
int mysql_unpacked_real_data_home_len;
600
uint mysql_real_data_home_len, mysql_data_home_len= 1;
601
uint reg_ext_length;
602 603 604
const key_map key_map_empty(0);
key_map key_map_full(0);                        // Will be initialized later

605 606
DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
Time_zone *default_tz;
607

608
const char *mysql_real_data_home_ptr= mysql_real_data_home;
609
char server_version[SERVER_VERSION_LENGTH];
610
char *mysqld_unix_port, *opt_mysql_tmpdir;
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
611
ulong thread_handling;
612

613
/** name of reference on left expression in rewritten IN subquery */
614
const char *in_left_expr_name= "<left expr>";
unknown's avatar
unknown committed
615
/** name of additional condition */
616
const char *in_additional_cond= "<IN COND>";
617 618
const char *in_having_cond= "<IN HAVING>";

unknown's avatar
unknown committed
619 620 621 622 623 624 625 626 627 628 629 630 631
/** 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
632 633 634 635 636 637 638 639
/* 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
640
MYSQL_FILE *bootstrap_file;
unknown's avatar
Merge  
unknown committed
641
int bootstrap_error;
unknown's avatar
unknown committed
642

unknown's avatar
unknown committed
643
I_List<THD> threads;
644 645
Rpl_filter* cur_rpl_filter;
Rpl_filter* global_rpl_filter;
unknown's avatar
unknown committed
646
Rpl_filter* binlog_filter;
unknown's avatar
unknown committed
647

648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
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
663 664
struct system_variables global_system_variables;
struct system_variables max_system_variables;
unknown's avatar
Merge  
unknown committed
665
struct system_status_var global_status_var;
unknown's avatar
unknown committed
666

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

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

675
MY_LOCALE *my_default_lc_messages;
676 677
MY_LOCALE *my_default_lc_time_names;

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

/* Thread specific variables */
685

unknown's avatar
unknown committed
686
pthread_key(MEM_ROOT**,THR_MALLOC);
unknown's avatar
unknown committed
687
pthread_key(THD*, THR_THD);
Michael Widenius's avatar
Michael Widenius committed
688
mysql_mutex_t LOCK_thread_count, LOCK_thread_cache;
689
mysql_mutex_t
Sergei Golubchik's avatar
Sergei Golubchik committed
690
  LOCK_status, LOCK_error_log, LOCK_short_uuid_generator,
Marc Alff's avatar
Marc Alff committed
691 692 693 694 695
  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
696 697 698

mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats,
              LOCK_global_table_stats, LOCK_global_index_stats;
699

unknown's avatar
unknown committed
700
/**
701 702 703 704 705 706
  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
707
mysql_mutex_t LOCK_prepared_stmt_count;
708
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
709
mysql_mutex_t LOCK_des_key_file;
710
#endif
Marc Alff's avatar
Marc Alff committed
711 712
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
713
mysql_cond_t COND_thread_count;
unknown's avatar
unknown committed
714 715
pthread_t signal_thread;
pthread_attr_t connection_attrib;
Marc Alff's avatar
Marc Alff committed
716 717
mysql_mutex_t LOCK_server_started;
mysql_cond_t COND_server_started;
unknown's avatar
unknown committed
718

719
int mysqld_server_started=0, mysqld_server_initialized= 0;
720 721
File_parser_dummy_hook file_parser_dummy_hook;

unknown's avatar
unknown committed
722
/* replication parameters, if master_host is not NULL, we are a slave */
723
uint report_port= 0;
unknown's avatar
unknown committed
724
ulong master_retry_count=0;
725
char *master_info_file;
unknown's avatar
unknown committed
726
char *relay_log_info_file, *report_user, *report_password, *report_host;
unknown's avatar
unknown committed
727
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
728
char *opt_logname, *opt_slow_logname, *opt_bin_logname;
unknown's avatar
unknown committed
729 730 731

/* Static variables */

732
static volatile sig_atomic_t kill_in_progress;
Michael Widenius's avatar
Michael Widenius committed
733
my_bool opt_stack_trace;
734 735
my_bool opt_expect_abort= 0, opt_bootstrap= 0;
static my_bool opt_myisam_log;
unknown's avatar
unknown committed
736
static int cleanup_done;
737
static ulong opt_specialflag;
Sergei Golubchik's avatar
Sergei Golubchik committed
738
static char *opt_binlog_index_name;
739
char *mysql_home_ptr, *pidfile_name_ptr;
Marc Alff's avatar
Marc Alff committed
740
/** Initial command line arguments (count), after load_defaults().*/
unknown's avatar
unknown committed
741
static int defaults_argc;
Marc Alff's avatar
Marc Alff committed
742 743 744 745 746 747 748 749
/**
  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
750
static char **defaults_argv;
Marc Alff's avatar
Marc Alff committed
751 752 753 754
/** 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
755

756 757 758
int orig_argc;
char **orig_argv;

759
static struct my_option pfs_early_options[]=
760
{
761
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 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
  {"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}
826
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
827 828
};

829 830
#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
831 832
PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool,
  key_LOCK_pending_checkpoint;
833 834 835 836 837 838
#endif /* HAVE_MMAP */

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

839
PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
840
  key_BINLOG_LOCK_binlog_background_thread,
841 842 843 844 845 846 847
  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,
848
  key_LOCK_system_variables_hash, key_LOCK_thd_data,
849 850
  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
851
  key_master_info_sleep_lock,
852
  key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
Michael Widenius's avatar
Michael Widenius committed
853
  key_rpl_group_info_sleep_lock,
854
  key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
855
  key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
Michael Widenius's avatar
Michael Widenius committed
856 857
  key_LOCK_error_messages, key_LOG_INFO_lock,
  key_LOCK_thread_count, key_LOCK_thread_cache,
858 859
  key_PARTITION_LOCK_auto_inc;
PSI_mutex_key key_RELAYLOG_LOCK_index;
860
PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
861
  key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry;
862 863 864

PSI_mutex_key key_LOCK_stats,
  key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
Sergei Golubchik's avatar
Sergei Golubchik committed
865
  key_LOCK_global_index_stats,
866
  key_LOCK_wakeup_ready, key_LOCK_wait_commit;
Sergei Golubchik's avatar
Sergei Golubchik committed
867 868

PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
Sergei Golubchik's avatar
Sergei Golubchik committed
869
PSI_mutex_key key_TABLE_SHARE_LOCK_share;
870 871 872 873 874 875 876 877

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},
878
  { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pending_checkpoint", 0},
879 880 881 882 883 884 885
#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},
886
  { &key_BINLOG_LOCK_xid_list, "MYSQL_BIN_LOG::LOCK_xid_list", 0},
887
  { &key_BINLOG_LOCK_binlog_background_thread, "MYSQL_BIN_LOG::LOCK_binlog_background_thread", 0},
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
  { &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
910
  { &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
911
  { &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0},
912 913
  { &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
914
  { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
915 916 917
  { &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
918
  { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
919 920 921 922
  { &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
923
  { &key_rpl_group_info_sleep_lock, "Rpl_group_info::sleep_lock", 0},
924 925
  { &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
926
  { &key_TABLE_SHARE_LOCK_share, "TABLE_SHARE::LOCK_share", 0},
927
  { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
Sergei Golubchik's avatar
Sergei Golubchik committed
928 929
  { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL},
  { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
930 931
  { &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
932
  { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL},
933
  { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0},
unknown's avatar
unknown committed
934
  { &key_LOCK_slave_state, "LOCK_slave_state", 0},
935 936
  { &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
  { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
937 938
  { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
  { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0}
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
};

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
959
PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
960 961
#endif /* HAVE_MMAP */

962
PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
963 964
  key_BINLOG_COND_binlog_background_thread,
  key_BINLOG_COND_binlog_background_thread_end,
965 966 967 968 969
  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
970
  key_master_info_sleep_cond,
971 972
  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
973
  key_rpl_group_info_sleep_cond,
974
  key_TABLE_SHARE_cond, key_user_level_lock_cond,
975 976
  key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache,
  key_BINLOG_COND_queue_busy;
977 978
PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready,
  key_COND_wait_commit;
979 980
PSI_cond_key key_RELAYLOG_COND_queue_busy;
PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
981
PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool,
982
  key_COND_parallel_entry, key_COND_prepare_ordered;
983 984 985 986 987 988 989 990 991 992

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},
993
  { &key_TC_LOG_MMAP_COND_queue_busy, "TC_LOG_MMAP::COND_queue_busy", 0},
994
#endif /* HAVE_MMAP */
995
  { &key_BINLOG_COND_xid_list, "MYSQL_BIN_LOG::COND_xid_list", 0},
996
  { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
997 998
  { &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},
999
  { &key_BINLOG_COND_queue_busy, "MYSQL_BIN_LOG::COND_queue_busy", 0},
1000
  { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
1001
  { &key_RELAYLOG_COND_queue_busy, "MYSQL_RELAY_LOG::COND_queue_busy", 0},
Sergei Golubchik's avatar
Sergei Golubchik committed
1002
  { &key_COND_wakeup_ready, "THD::COND_wakeup_ready", 0},
1003
  { &key_COND_wait_commit, "wait_for_commit::COND_wait_commit", 0},
1004 1005 1006 1007 1008 1009 1010 1011 1012
  { &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
1013
  { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
1014 1015 1016 1017
  { &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
1018
  { &key_rpl_group_info_sleep_cond, "Rpl_group_info::sleep_cond", 0},
1019 1020 1021 1022
  { &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},
1023 1024
  { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL},
  { &key_COND_rpl_thread, "COND_rpl_thread", 0},
1025
  { &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0},
1026 1027
  { &key_COND_parallel_entry, "COND_parallel_entry", 0},
  { &key_COND_prepare_ordered, "COND_prepare_ordered", 0}
1028 1029 1030 1031
};

PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
  key_thread_handle_manager, key_thread_main,
1032
  key_thread_one_connection, key_thread_signal_hand,
1033
  key_thread_slave_init, key_rpl_parallel_thread;
1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

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},
1058
  { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL},
1059 1060
  { &key_thread_slave_init, "slave_init", PSI_FLAG_GLOBAL},
  { &key_rpl_parallel_thread, "rpl_parallel_thread", 0}
1061 1062
};

1063 1064 1065 1066
#ifdef HAVE_MMAP
PSI_file_key key_file_map;
#endif /* HAVE_MMAP */

1067 1068 1069 1070 1071 1072 1073 1074 1075
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;
1076
PSI_file_key key_file_binlog_state;
1077

1078
#endif /* HAVE_PSI_INTERFACE */
1079

1080 1081 1082 1083 1084 1085
#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 */)
1086
{
1087 1088 1089
  THD *thd;
  thd= static_cast<THD*> (user_data);
  DBUG_ASSERT(thd != NULL);
1090

1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
  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);
  }
}
1104

1105 1106 1107 1108 1109
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);
1110

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
  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);
1125

1126 1127 1128 1129
    if (! rc)
    {
      thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
                                                  stmt_info_new_packet.m_key,
1130 1131
                                                  thd->db, thd->db_length,
                                                  thd->charset());
1132

1133 1134
      THD_STAGE_INFO(thd, stage_init);
    }
1135

1136 1137 1138 1139 1140 1141
    /*
      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);
  }
1142 1143
}

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
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 */
1158

Marc Alff's avatar
Marc Alff committed
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
/**
  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:
1211 1212 1213 1214 1215 1216 1217 1218 1219
    /*
      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
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
    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()
{
1255
  init_alloc_root(&m_root, 1024, 0, MYF(0));
Marc Alff's avatar
Marc Alff committed
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 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
}

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;

1294 1295 1296
static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock;
struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD()

1297
#ifndef EMBEDDED_LIBRARY
Marc Alff's avatar
Marc Alff committed
1298 1299 1300 1301 1302
/**
  Error reporter that buffer log messages.
  @param level          log message level
  @param format         log message format string
*/
1303
C_MODE_START
1304 1305
static void buffered_option_error_reporter(enum loglevel level,
                                           const char *format, ...)
Marc Alff's avatar
Marc Alff committed
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
{
  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);
}

1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342

/**
  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
1343 1344 1345 1346
struct passwd *user_info;
static pthread_t select_thread;
#endif

unknown's avatar
unknown committed
1347 1348
/* OS specific variables */

unknown's avatar
unknown committed
1349 1350 1351
#ifdef __WIN__
#undef	 getpid
#include <process.h>
unknown's avatar
unknown committed
1352

Marc Alff's avatar
Marc Alff committed
1353
static mysql_cond_t COND_handler_count;
unknown's avatar
unknown committed
1354 1355 1356 1357 1358
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
1359
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
1360
static HANDLE hEventShutdown;
1361
static char shutdown_event_name[40];
unknown's avatar
unknown committed
1362
#include "nt_servc.h"
unknown's avatar
unknown committed
1363
static	 NTService  Service;	      ///< Service object for WinNT
unknown's avatar
unknown committed
1364 1365 1366
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */

Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1367
#ifdef _WIN32
1368
static char pipe_name[512];
unknown's avatar
unknown committed
1369 1370 1371
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
unknown's avatar
unknown committed
1372
#endif
unknown's avatar
unknown committed
1373

unknown's avatar
unknown committed
1374
#ifndef EMBEDDED_LIBRARY
1375
bool mysqld_embedded=0;
unknown's avatar
unknown committed
1376
#else
1377
bool mysqld_embedded=1;
unknown's avatar
unknown committed
1378 1379
#endif

1380 1381
static my_bool plugins_are_initialized= FALSE;

unknown's avatar
unknown committed
1382
#ifndef DBUG_OFF
1383
static const char* default_dbug_option;
unknown's avatar
unknown committed
1384
#endif
1385
static const char *current_dbug_option="disabled";
unknown's avatar
unknown committed
1386
#ifdef HAVE_LIBWRAP
1387
const char *libwrapName= NULL;
1388 1389
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
unknown's avatar
unknown committed
1390 1391 1392 1393 1394 1395 1396
#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;
1397
my_bool opt_enable_shared_memory;
1398
HANDLE smem_event_connect_request= 0;
unknown's avatar
unknown committed
1399 1400
#endif

1401 1402
my_bool opt_use_ssl  = 0;
char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
1403 1404 1405
  *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL,
  *opt_ssl_crlpath= NULL;

1406

Sergei Golubchik's avatar
Sergei Golubchik committed
1407 1408 1409
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
1410

unknown's avatar
unknown committed
1411
#ifdef HAVE_OPENSSL
1412
#include <openssl/crypto.h>
unknown's avatar
unknown committed
1413
#ifndef HAVE_YASSL
1414 1415
typedef struct CRYPTO_dynlock_value
{
Marc Alff's avatar
Marc Alff committed
1416
  mysql_rwlock_t lock;
1417 1418 1419 1420 1421 1422 1423 1424
} 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
1425
#endif
unknown's avatar
unknown committed
1426
char *des_key_file;
Konstantin Osipov's avatar
Konstantin Osipov committed
1427
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1428
struct st_VioSSLFd *ssl_acceptor_fd;
Konstantin Osipov's avatar
Konstantin Osipov committed
1429
#endif
unknown's avatar
unknown committed
1430 1431
#endif /* HAVE_OPENSSL */

1432 1433 1434 1435
/**
  Number of currently active user connections. The variable is protected by
  LOCK_connection_count.
*/
1436
uint connection_count= 0, extra_connection_count= 0;
unknown's avatar
unknown committed
1437

1438
my_bool opt_gtid_strict_mode= FALSE;
1439 1440


unknown's avatar
unknown committed
1441 1442
/* Function declarations */

1443
pthread_handler_t signal_hand(void *arg);
1444
static int mysql_init_variables(void);
Marc Alff's avatar
Marc Alff committed
1445 1446
static int get_options(int *argc_ptr, char ***argv_ptr);
static bool add_terminator(DYNAMIC_ARRAY *options);
1447
static bool add_many_options(DYNAMIC_ARRAY *, my_option *, size_t);
1448
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
1449
static int init_thread_environment();
unknown's avatar
unknown committed
1450
static char *get_relative_path(const char *path);
1451
static int fix_paths(void);
1452 1453 1454 1455
void handle_connections_sockets();
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg);
#endif
1456
pthread_handler_t kill_server_thread(void *arg);
Marc Alff's avatar
Marc Alff committed
1457
static void bootstrap(MYSQL_FILE *file);
unknown's avatar
unknown committed
1458
static bool read_init_file(char *file_name);
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1459
#ifdef _WIN32
1460
pthread_handler_t handle_connections_namedpipes(void *arg);
unknown's avatar
unknown committed
1461
#endif
1462
#ifdef HAVE_SMEM
1463
pthread_handler_t handle_connections_shared_memory(void *arg);
1464
#endif
1465
pthread_handler_t handle_slave(void *arg);
unknown's avatar
unknown committed
1466
static void clean_up(bool print_message);
1467 1468 1469
static int test_if_case_insensitive(const char *dir_name);

#ifndef EMBEDDED_LIBRARY
1470
static bool pid_file_created= false;
1471
static void usage(void);
1472 1473
static void start_signal_handler(void);
static void close_server_sock();
unknown's avatar
unknown committed
1474
static void clean_up_mutexes(void);
1475
static void wait_for_signal_thread_to_end(void);
1476
static void create_pid_file();
1477
static void mysqld_exit(int exit_code) __attribute__((noreturn));
1478
#endif
1479
static void delete_pid_file(myf flags);
Konstantin Osipov's avatar
Konstantin Osipov committed
1480
static void end_ssl();
1481

1482 1483

#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
/****************************************************************************
** 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 */
1500
#if !defined(__WIN__)
unknown's avatar
unknown committed
1501 1502
  DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
                      (ulong) select_thread));
Marc Alff's avatar
Marc Alff committed
1503
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
1504 1505 1506 1507 1508 1509

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

unknown's avatar
unknown committed
1512
#ifndef DONT_USE_THR_ALARM
1513
    if (pthread_kill(select_thread, thr_client_alarm))
unknown's avatar
unknown committed
1514 1515
      break;					// allready dead
#endif
1516
    set_timespec(abstime, 2);
1517
    for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
unknown's avatar
unknown committed
1518
    {
Marc Alff's avatar
Marc Alff committed
1519 1520
      error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
                                  &abstime);
unknown's avatar
unknown committed
1521 1522 1523 1524
      if (error != EINTR)
	break;
    }
#ifdef EXTRA_DEBUG
1525
    if (error != 0 && error != ETIMEDOUT && !count++)
Marc Alff's avatar
Marc Alff committed
1526
      sql_print_error("Got error %d from mysql_cond_timedwait", error);
unknown's avatar
unknown committed
1527
#endif
unknown's avatar
unknown committed
1528
    close_server_sock();
unknown's avatar
unknown committed
1529
  }
Marc Alff's avatar
Marc Alff committed
1530
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1531 1532 1533 1534 1535
#endif /* __WIN__ */


  /* Abort listening to new connections */
  DBUG_PRINT("quit",("Closing sockets"));
unknown's avatar
Merge  
unknown committed
1536
  if (!opt_disable_networking )
unknown's avatar
unknown committed
1537
  {
1538
    if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1539
    {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1540
      (void) mysql_socket_shutdown(base_ip_sock, SHUT_RDWR);
1541 1542
      (void) mysql_socket_close(base_ip_sock);
      base_ip_sock= MYSQL_INVALID_SOCKET;
1543
    }
1544
    if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1545
    {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1546
      (void) mysql_socket_shutdown(extra_ip_sock, SHUT_RDWR);
1547 1548
      (void) mysql_socket_close(extra_ip_sock);
      extra_ip_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1549 1550
    }
  }
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1551
#ifdef _WIN32
unknown's avatar
unknown committed
1552
  if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
unknown's avatar
unknown committed
1553
  {
unknown's avatar
merge  
unknown committed
1554
    HANDLE temp;
unknown's avatar
Merge  
unknown committed
1555
    DBUG_PRINT("quit", ("Closing named pipes") );
1556

unknown's avatar
merge  
unknown committed
1557
    /* Create connection to the handle named pipe handler to break the loop */
1558
    if ((temp = CreateFile(pipe_name,
unknown's avatar
merge  
unknown committed
1559 1560 1561 1562 1563 1564 1565
			   GENERIC_READ | GENERIC_WRITE,
			   0,
			   NULL,
			   OPEN_EXISTING,
			   0,
			   NULL )) != INVALID_HANDLE_VALUE)
    {
1566
      WaitNamedPipe(pipe_name, 1000);
unknown's avatar
merge  
unknown committed
1567 1568 1569 1570 1571 1572
      DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
      SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
      CancelIo(temp);
      DisconnectNamedPipe(temp);
      CloseHandle(temp);
    }
unknown's avatar
unknown committed
1573 1574 1575
  }
#endif
#ifdef HAVE_SYS_UN_H
1576
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1577
  {
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1578
    (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR);
1579
    (void) mysql_socket_close(unix_sock);
1580
    (void) unlink(mysqld_unix_port);
1581
    unix_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
1582 1583
  }
#endif
1584
  end_thr_alarm(0);			 // Abort old alarms.
unknown's avatar
unknown committed
1585

1586 1587 1588 1589 1590
  /*
    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
1591 1592

  THD *tmp;
Marc Alff's avatar
Marc Alff committed
1593
  mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1594 1595 1596 1597 1598 1599

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

1604
    tmp->killed= KILL_SERVER_HARD;
Sergei Golubchik's avatar
Sergei Golubchik committed
1605
    MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1606
    mysql_mutex_lock(&tmp->LOCK_thd_data);
unknown's avatar
unknown committed
1607 1608 1609
    if (tmp->mysys_var)
    {
      tmp->mysys_var->abort=1;
Marc Alff's avatar
Marc Alff committed
1610
      mysql_mutex_lock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1611
      if (tmp->mysys_var->current_cond)
unknown's avatar
unknown committed
1612
      {
1613 1614 1615
        uint i;
        for (i=0; i < 2; i++)
        {
Sergei Golubchik's avatar
Sergei Golubchik committed
1616 1617
          int ret= mysql_mutex_trylock(tmp->mysys_var->current_mutex);
          mysql_cond_broadcast(tmp->mysys_var->current_cond);
1618 1619 1620
          if (!ret)
          {
            /* Thread has surely got the signal, unlock and abort */
Sergei Golubchik's avatar
Sergei Golubchik committed
1621
            mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1622 1623 1624 1625
            break;
          }
          sleep(1);
        }
unknown's avatar
unknown committed
1626
      }
Marc Alff's avatar
Marc Alff committed
1627
      mysql_mutex_unlock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1628
    }
1629
    mysql_mutex_unlock(&tmp->LOCK_thd_data);
unknown's avatar
unknown committed
1630
  }
Marc Alff's avatar
Marc Alff committed
1631
  mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1632

1633
  Events::deinit();
1634 1635
  end_slave();

1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
  /*
    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++)
1651
    my_sleep(20000);
unknown's avatar
unknown committed
1652

1653 1654 1655 1656 1657
  /*
    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
1658 1659 1660 1661

  for (;;)
  {
    DBUG_PRINT("quit",("Locking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1662
    mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1663 1664 1665
    if (!(tmp=threads.get()))
    {
      DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1666
      mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1667 1668 1669
      break;
    }
#ifndef __bsdi__				// Bug in BSDI kernel
1670
    if (tmp->vio_ok())
unknown's avatar
unknown committed
1671
    {
1672
      if (global_system_variables.log_warnings)
1673
        sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1674
                          tmp->thread_id,
1675 1676
                          (tmp->main_security_ctx.user ?
                           tmp->main_security_ctx.user : ""));
Sergei Golubchik's avatar
Sergei Golubchik committed
1677
      close_connection(tmp,ER_SERVER_SHUTDOWN);
unknown's avatar
unknown committed
1678 1679 1680
    }
#endif
    DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1681
    mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1682 1683 1684
  }
  /* 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
1685
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
1686 1687
  while (thread_count)
  {
Marc Alff's avatar
Marc Alff committed
1688
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
unknown's avatar
unknown committed
1689 1690
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
1691
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1692 1693 1694 1695 1696

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

1697

1698
#ifdef HAVE_CLOSE_SERVER_SOCK
1699
static void close_socket(MYSQL_SOCKET sock, const char *info)
unknown's avatar
unknown committed
1700
{
1701 1702
  DBUG_ENTER("close_socket");

1703
  if (mysql_socket_getfd(sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
1704
  {
1705
    DBUG_PRINT("info", ("calling shutdown on %s socket", info));
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
1706
    (void) mysql_socket_shutdown(sock, SHUT_RDWR);
unknown's avatar
unknown committed
1707
  }
1708 1709
  DBUG_VOID_RETURN;
}
1710
#endif
1711 1712


1713
static void close_server_sock()
unknown's avatar
unknown committed
1714
{
1715
#ifdef HAVE_CLOSE_SERVER_SOCK
unknown's avatar
unknown committed
1716
  DBUG_ENTER("close_server_sock");
1717 1718 1719 1720 1721

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

1722
  if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
Konstantin Osipov's avatar
Konstantin Osipov committed
1723
    (void) unlink(mysqld_unix_port);
1724
  base_ip_sock= extra_ip_sock= unix_sock= MYSQL_INVALID_SOCKET;
Sergei Golubchik's avatar
Sergei Golubchik committed
1725

unknown's avatar
unknown committed
1726 1727
  DBUG_VOID_RETURN;
#endif
1728
}
unknown's avatar
unknown committed
1729

1730 1731
#endif /*EMBEDDED_LIBRARY*/

1732

unknown's avatar
unknown committed
1733 1734 1735 1736
void kill_mysql(void)
{
  DBUG_ENTER("kill_mysql");

1737
#if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
1738 1739
  abort_loop=1;					// Break connection loops
  close_server_sock();				// Force accept to wake up
1740
#endif
unknown's avatar
unknown committed
1741

unknown's avatar
unknown committed
1742
#if defined(__WIN__)
unknown's avatar
unknown committed
1743
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
1744 1745 1746 1747 1748
  {
    if (!SetEvent(hEventShutdown))
    {
      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
    }
1749 1750 1751 1752 1753 1754
    /*
      or:
      HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
      SetEvent(hEventShutdown);
      CloseHandle(hEvent);
    */
unknown's avatar
unknown committed
1755
  }
unknown's avatar
unknown committed
1756
#endif
unknown's avatar
unknown committed
1757
#elif defined(HAVE_PTHREAD_KILL)
1758
  if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
unknown's avatar
unknown committed
1759 1760 1761 1762
  {
    DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
  }
#elif !defined(SIGNALS_DONT_BREAK_READ)
1763
  kill(current_pid, MYSQL_KILL_SIGNAL);
unknown's avatar
unknown committed
1764
#endif
unknown's avatar
unknown committed
1765 1766 1767
  DBUG_PRINT("quit",("After pthread_kill"));
  shutdown_in_progress=1;			// Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ
1768
  if (!kill_in_progress)
unknown's avatar
unknown committed
1769 1770
  {
    pthread_t tmp;
1771
    int error;
unknown's avatar
unknown committed
1772
    abort_loop=1;
1773 1774 1775 1776
    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
1777
  }
1778
#endif
unknown's avatar
unknown committed
1779
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1780 1781
}

unknown's avatar
unknown committed
1782 1783
/**
  Force server down. Kill all connections and threads and exit.
1784

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

unknown's avatar
unknown committed
1787
  @note
1788 1789 1790 1791
    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
1792

1793
#if !defined(__WIN__)
unknown's avatar
unknown committed
1794
static void *kill_server(void *sig_ptr)
1795
#define RETURN_FROM_KILL_SERVER return 0
unknown's avatar
unknown committed
1796 1797
#else
static void __cdecl kill_server(int sig_ptr)
1798
#define RETURN_FROM_KILL_SERVER return
unknown's avatar
unknown committed
1799 1800 1801
#endif
{
  DBUG_ENTER("kill_server");
1802
#ifndef EMBEDDED_LIBRARY
unknown's avatar
Merge  
unknown committed
1803
  int sig=(int) (long) sig_ptr;			// This is passed a int
1804
  // if there is a signal during the kill in progress, ignore the other
unknown's avatar
unknown committed
1805
  if (kill_in_progress)				// Safety
1806 1807
  {
    DBUG_LEAVE;
unknown's avatar
unknown committed
1808
    RETURN_FROM_KILL_SERVER;
1809
  }
unknown's avatar
unknown committed
1810 1811
  kill_in_progress=TRUE;
  abort_loop=1;					// This should be set
1812
  if (sig != 0) // 0 is not a valid signal number
1813
    my_sigset(sig, SIG_IGN);                    /* purify inspected */
unknown's avatar
unknown committed
1814
  if (sig == MYSQL_KILL_SIGNAL || sig == 0)
1815
    sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN),my_progname);
unknown's avatar
unknown committed
1816
  else
1817
    sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
unknown's avatar
unknown committed
1818

Sergei Golubchik's avatar
Sergei Golubchik committed
1819
#ifdef HAVE_SMEM
1820
  /*
Sergei Golubchik's avatar
Sergei Golubchik committed
1821 1822
    Send event to smem_event_connect_request for aborting
  */
1823
  if (opt_enable_shared_memory)
1824
  {
1825 1826 1827 1828 1829 1830
    if (!SetEvent(smem_event_connect_request))
    {
      DBUG_PRINT("error",
                 ("Got error: %ld from SetEvent of smem_event_connect_request",
                  GetLastError()));
    }
1831 1832 1833
  }
#endif

unknown's avatar
unknown committed
1834
  close_connections();
1835 1836
  if (sig != MYSQL_KILL_SIGNAL &&
      sig != 0)
unknown's avatar
unknown committed
1837 1838
    unireg_abort(1);				/* purecov: inspected */
  else
1839
    unireg_end();
unknown's avatar
Merge  
unknown committed
1840

1841
  /* purecov: begin deadcode */
1842
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
1843
  my_thread_end();
1844 1845
  pthread_exit(0);
  /* purecov: end */
unknown's avatar
unknown committed
1846

1847 1848 1849 1850 1851
  RETURN_FROM_KILL_SERVER;                      // Avoid compiler warnings

#else /* EMBEDDED_LIBRARY*/

  DBUG_LEAVE;
unknown's avatar
unknown committed
1852
  RETURN_FROM_KILL_SERVER;
1853 1854

#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1855 1856 1857
}


1858
#if defined(USE_ONE_SIGNAL_HAND)
1859
pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
1860 1861 1862
{
  my_thread_init();				// Initialize new thread
  kill_server(0);
1863 1864 1865
  /* purecov: begin deadcode */
  my_thread_end();
  pthread_exit(0);
unknown's avatar
unknown committed
1866
  return 0;
1867
  /* purecov: end */
unknown's avatar
unknown committed
1868 1869 1870
}
#endif

1871

1872
extern "C" sig_handler print_signal_warning(int sig)
unknown's avatar
unknown committed
1873
{
unknown's avatar
unknown committed
1874
  if (global_system_variables.log_warnings)
1875
    sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
1876
#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
1877
  my_sigset(sig,print_signal_warning);		/* int. thread system calls */
unknown's avatar
unknown committed
1878
#endif
1879
#if !defined(__WIN__)
unknown's avatar
unknown committed
1880 1881 1882 1883 1884
  if (sig == SIGALRM)
    alarm(2);					/* reschedule alarm */
#endif
}

unknown's avatar
unknown committed
1885
#ifndef EMBEDDED_LIBRARY
1886

1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
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
1899 1900
/**
  cleanup all memory and end program nicely.
unknown's avatar
unknown committed
1901

1902 1903 1904
    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
1905

unknown's avatar
unknown committed
1906 1907 1908
  @note
    This function never returns.
*/
1909
void unireg_end(void)
unknown's avatar
unknown committed
1910
{
unknown's avatar
unknown committed
1911
  clean_up(1);
unknown's avatar
unknown committed
1912
  my_thread_end();
1913
#if defined(SIGNALS_DONT_BREAK_READ)
1914 1915
  exit(0);
#else
unknown's avatar
unknown committed
1916
  pthread_exit(0);				// Exit is in main thread
1917
#endif
unknown's avatar
unknown committed
1918 1919
}

1920

1921
extern "C" void unireg_abort(int exit_code)
unknown's avatar
unknown committed
1922
{
1923
  DBUG_ENTER("unireg_abort");
1924

1925 1926
  if (opt_help)
    usage();
unknown's avatar
unknown committed
1927 1928
  if (exit_code)
    sql_print_error("Aborting\n");
1929
  clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1930
  DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
1931 1932 1933 1934 1935
  mysqld_exit(exit_code);
}

static void mysqld_exit(int exit_code)
{
1936
  DBUG_ENTER("mysqld_exit");
1937 1938 1939 1940 1941
  /*
    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.
  */
1942
  rpl_deinit_gtid_slave_state();
1943
  wait_for_signal_thread_to_end();
1944
  mysql_audit_finalize();
unknown's avatar
unknown committed
1945
  clean_up_mutexes();
Marc Alff's avatar
Marc Alff committed
1946
  clean_up_error_log_mutex();
1947
  my_end((opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0));
1948
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
1949
  shutdown_performance_schema();        // we do it as late as possible
1950
#endif
1951
  DBUG_LEAVE;
unknown's avatar
unknown committed
1952 1953
  exit(exit_code); /* purecov: inspected */
}
1954

1955
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1956

1957
void clean_up(bool print_message)
unknown's avatar
unknown committed
1958 1959 1960 1961
{
  DBUG_PRINT("exit",("clean_up"));
  if (cleanup_done++)
    return; /* purecov: inspected */
unknown's avatar
unknown committed
1962

1963 1964 1965 1966 1967 1968
#ifdef HAVE_REPLICATION
  // We must call end_slave() as clean_up may have been called during startup
  end_slave();
  if (use_slave_mask)
    bitmap_free(&slave_error_mask);
#endif
1969
  stop_handle_manager();
1970 1971
  release_ddl_log();

unknown's avatar
unknown committed
1972 1973 1974 1975 1976
  /*
    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
1977 1978 1979

  logger.cleanup_base();

1980
  injector::free_instance();
unknown's avatar
unknown committed
1981 1982
  mysql_bin_log.cleanup();

1983
  my_tz_free();
1984
  my_dboptions_cache_free();
1985
  ignore_db_dirs_free();
unknown's avatar
unknown committed
1986
  servers_free(1);
1987
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
1988 1989
  acl_free(1);
  grant_free();
unknown's avatar
unknown committed
1990
#endif
unknown's avatar
unknown committed
1991
  query_cache_destroy();
unknown's avatar
unknown committed
1992
  hostname_cache_free();
1993
  item_func_sleep_free();
unknown's avatar
unknown committed
1994
  lex_free();				/* Free some memory */
1995
  item_create_cleanup();
unknown's avatar
unknown committed
1996
  if (!opt_noacl)
1997
  {
1998
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
1999
    udf_free();
2000
#endif
2001
  }
2002
  tdc_start_shutdown();
2003
  plugin_shutdown();
2004
  ha_end();
unknown's avatar
Merge  
unknown committed
2005 2006
  if (tc_log)
    tc_log->close();
He Zhenxing's avatar
He Zhenxing committed
2007
  delegates_destroy();
2008
  xid_cache_free();
2009
  tdc_deinit();
Konstantin Osipov's avatar
Konstantin Osipov committed
2010
  mdl_destroy();
2011
  key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
2012
  wt_end();
2013
  multi_keycache_free();
2014
  sp_cache_end();
2015
  free_status_vars();
2016
  end_thr_alarm(1);			/* Free allocated memory */
2017
  my_free_open_file_info();
unknown's avatar
unknown committed
2018 2019
  if (defaults_argv)
    free_defaults(defaults_argv);
unknown's avatar
unknown committed
2020
  free_tmpdir(&mysql_tmpdir_list);
unknown's avatar
unknown committed
2021
  bitmap_free(&temp_pool);
unknown's avatar
unknown committed
2022
  free_max_user_conn();
2023 2024 2025 2026
  free_global_user_stats();
  free_global_client_stats();
  free_global_table_stats();
  free_global_index_stats();
2027
  delete_dynamic(&all_options);
unknown's avatar
SCRUM  
unknown committed
2028
#ifdef HAVE_REPLICATION
2029
  end_slave_list();
2030
#endif
2031
  my_uuid_end();
unknown's avatar
unknown committed
2032
  delete binlog_filter;
2033
  delete global_rpl_filter;
2034
  end_ssl();
2035
#ifndef EMBEDDED_LIBRARY
2036
  vio_end();
2037
#endif /*!EMBEDDED_LIBRARY*/
2038 2039 2040 2041
#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
2042

2043
  delete_pid_file(MYF(0));
2044

2045
  if (print_message && my_default_lc_messages && server_start_time)
2046 2047
    sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
  cleanup_errmsgs();
Sergei Golubchik's avatar
Sergei Golubchik committed
2048
  MYSQL_CALLBACK(thread_scheduler, end, ());
2049
  mysql_library_end();
unknown's avatar
Merge  
unknown committed
2050
  finish_client_errs();
2051
  (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
2052
  DBUG_PRINT("quit", ("Error messages freed"));
unknown's avatar
unknown committed
2053
  /* Tell main we are ready */
unknown's avatar
unknown committed
2054
  logger.cleanup_end();
2055
  sys_var_end();
2056
  my_atomic_rwlock_destroy(&global_query_id_lock);
2057
  my_atomic_rwlock_destroy(&thread_running_lock);
Michael Widenius's avatar
Michael Widenius committed
2058
  my_atomic_rwlock_destroy(&thread_count_lock);
2059
  my_atomic_rwlock_destroy(&statistics_lock); 
2060
  my_atomic_rwlock_destroy(&slave_executed_entries_lock);
2061
  free_charsets();
Marc Alff's avatar
Marc Alff committed
2062
  mysql_mutex_lock(&LOCK_thread_count);
2063
  DBUG_PRINT("quit", ("got thread count lock"));
unknown's avatar
unknown committed
2064
  ready_to_exit=1;
unknown's avatar
unknown committed
2065
  /* do the broadcast inside the lock to ensure that my_end() is not called */
Marc Alff's avatar
Marc Alff committed
2066 2067
  mysql_cond_broadcast(&COND_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
2068

2069
  free_list(opt_plugin_load_list_ptr);
unknown's avatar
unknown committed
2070 2071 2072 2073
  /*
    The following lines may never be executed as the main thread may have
    killed us
  */
2074
  DBUG_PRINT("quit", ("done with cleanup"));
unknown's avatar
unknown committed
2075 2076 2077
} /* clean_up */


2078 2079
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
2080
/**
2081
  This is mainly needed when running with purify, but it's still nice to
unknown's avatar
unknown committed
2082
  know that all child threads have died when mysqld exits.
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092
*/
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++)
  {
2093
    if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) == ESRCH)
2094 2095 2096 2097
      break;
    my_sleep(100);				// Give it time to die
  }
}
2098
#endif /*EMBEDDED_LIBRARY*/
2099

unknown's avatar
unknown committed
2100 2101
static void clean_up_mutexes()
{
2102
  DBUG_ENTER("clean_up_mutexes");
Marc Alff's avatar
Marc Alff committed
2103
  mysql_rwlock_destroy(&LOCK_grant);
Marc Alff's avatar
Marc Alff committed
2104
  mysql_mutex_destroy(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2105
  mysql_mutex_destroy(&LOCK_thread_cache);
Marc Alff's avatar
Marc Alff committed
2106 2107 2108 2109
  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
2110 2111 2112
  mysql_mutex_destroy(&LOCK_crypt);
  mysql_mutex_destroy(&LOCK_user_conn);
  mysql_mutex_destroy(&LOCK_connection_count);
Sergei Golubchik's avatar
Sergei Golubchik committed
2113 2114 2115 2116
  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);
2117
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
2118
  mysql_mutex_destroy(&LOCK_des_key_file);
unknown's avatar
unknown committed
2119
#ifndef HAVE_YASSL
2120
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
2121
    mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
2122
  OPENSSL_free(openssl_stdlocks);
Michael Widenius's avatar
Michael Widenius committed
2123 2124
#endif /* HAVE_YASSL */
#endif /* HAVE_OPENSSL */
2125
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
2126
  mysql_mutex_destroy(&LOCK_rpl_status);
Michael Widenius's avatar
Michael Widenius committed
2127
#endif /* HAVE_REPLICATION */
Marc Alff's avatar
Marc Alff committed
2128 2129 2130 2131 2132
  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
2133
  mysql_mutex_destroy(&LOCK_short_uuid_generator);
Marc Alff's avatar
Marc Alff committed
2134 2135
  mysql_mutex_destroy(&LOCK_prepared_stmt_count);
  mysql_mutex_destroy(&LOCK_error_messages);
Marc Alff's avatar
Marc Alff committed
2136 2137 2138
  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
2139 2140
  mysql_mutex_destroy(&LOCK_server_started);
  mysql_cond_destroy(&COND_server_started);
Sergei Golubchik's avatar
Sergei Golubchik committed
2141
  mysql_mutex_destroy(&LOCK_prepare_ordered);
2142
  mysql_cond_destroy(&COND_prepare_ordered);
Sergei Golubchik's avatar
Sergei Golubchik committed
2143
  mysql_mutex_destroy(&LOCK_commit_ordered);
2144
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2145
}
2146 2147


unknown's avatar
unknown committed
2148 2149 2150 2151
/****************************************************************************
** Init IP and UNIX socket
****************************************************************************/

unknown's avatar
unknown committed
2152
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
2153 2154 2155
static void set_ports()
{
  char	*env;
2156
  if (!mysqld_port && !opt_disable_networking)
unknown's avatar
unknown committed
2157
  {					// Get port if not from commandline
2158
    mysqld_port= MYSQL_PORT;
2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170

    /*
      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
2171
    struct  servent *serv_ptr;
2172 2173
    if ((serv_ptr= getservbyname("mysql", "tcp")))
      mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
2174
#endif
unknown's avatar
unknown committed
2175
    if ((env = getenv("MYSQL_TCP_PORT")))
2176
      mysqld_port= (uint) atoi(env);		/* purecov: inspected */
unknown's avatar
unknown committed
2177
  }
2178
  if (!mysqld_unix_port)
unknown's avatar
unknown committed
2179 2180
  {
#ifdef __WIN__
2181
    mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
unknown's avatar
unknown committed
2182
#else
2183
    mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
unknown's avatar
unknown committed
2184 2185
#endif
    if ((env = getenv("MYSQL_UNIX_PORT")))
2186
      mysqld_unix_port= env;			/* purecov: inspected */
unknown's avatar
unknown committed
2187 2188 2189 2190 2191
  }
}

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

2192
static struct passwd *check_user(const char *user)
unknown's avatar
unknown committed
2193
{
2194
#if !defined(__WIN__)
2195
  struct passwd *tmp_user_info;
2196
  uid_t user_id= geteuid();
unknown's avatar
unknown committed
2197

2198
  // Don't bother if we aren't superuser
2199
  if (user_id)
unknown's avatar
unknown committed
2200 2201
  {
    if (user)
2202
    {
2203 2204 2205 2206
      /* 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) &&
2207
	  global_system_variables.log_warnings)
2208 2209
        sql_print_warning(
                    "One can only use the --user switch if running as root\n");
unknown's avatar
unknown committed
2210
      /* purecov: end */
2211
    }
2212
    return NULL;
unknown's avatar
unknown committed
2213
  }
2214
  if (!user)
unknown's avatar
unknown committed
2215 2216 2217
  {
    if (!opt_bootstrap)
    {
unknown's avatar
unknown committed
2218
      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
2219 2220
      unireg_abort(1);
    }
2221
    return NULL;
unknown's avatar
unknown committed
2222
  }
2223
  /* purecov: begin tested */
unknown's avatar
unknown committed
2224
  if (!strcmp(user,"root"))
unknown's avatar
unknown committed
2225
    return NULL;                        // Avoid problem with dynamic libraries
unknown's avatar
unknown committed
2226

2227
  if (!(tmp_user_info= getpwnam(user)))
unknown's avatar
unknown committed
2228
  {
2229
    // Allow a numeric uid to be used
unknown's avatar
unknown committed
2230
    const char *pos;
unknown's avatar
unknown committed
2231 2232
    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
    if (*pos)                                   // Not numeric id
2233
      goto err;
2234
    if (!(tmp_user_info= getpwuid(atoi(user))))
2235
      goto err;
unknown's avatar
unknown committed
2236
  }
2237

unknown's avatar
unknown committed
2238 2239
  return tmp_user_info;
  /* purecov: end */
2240 2241

err:
unknown's avatar
unknown committed
2242
  sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
2243
  unireg_abort(1);
2244 2245 2246
#endif
  return NULL;
}
2247

2248 2249
static inline void allow_coredumps()
{
2250 2251 2252 2253 2254 2255 2256
#ifdef PR_SET_DUMPABLE
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* inform kernel that process is dumpable */
    (void) prctl(PR_SET_DUMPABLE, 1);
  }
#endif
2257 2258
}

2259

2260
static void set_user(const char *user, struct passwd *user_info_arg)
2261
{
2262
  /* purecov: begin tested */
2263
#if !defined(__WIN__)
2264
  DBUG_ASSERT(user_info_arg != 0);
unknown's avatar
unknown committed
2265
#ifdef HAVE_INITGROUPS
2266 2267 2268 2269 2270 2271
  /*
    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.
  */
2272
  calling_initgroups= 1;
2273
  initgroups((char*) user, user_info_arg->pw_gid);
2274
  calling_initgroups= 0;
unknown's avatar
unknown committed
2275
#endif
2276
  if (setgid(user_info_arg->pw_gid) == -1)
2277 2278 2279
  {
    sql_perror("setgid");
    unireg_abort(1);
unknown's avatar
unknown committed
2280
  }
2281
  if (setuid(user_info_arg->pw_uid) == -1)
unknown's avatar
unknown committed
2282 2283 2284 2285
  {
    sql_perror("setuid");
    unireg_abort(1);
  }
2286
  allow_coredumps();
unknown's avatar
unknown committed
2287
#endif
unknown's avatar
unknown committed
2288
  /* purecov: end */
unknown's avatar
unknown committed
2289 2290
}

unknown's avatar
unknown committed
2291

2292
static void set_effective_user(struct passwd *user_info_arg)
2293
{
2294
#if !defined(__WIN__)
2295 2296
  DBUG_ASSERT(user_info_arg != 0);
  if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
2297
  {
2298
    sql_perror("setregid");
2299
    unireg_abort(1);
unknown's avatar
unknown committed
2300
  }
2301
  if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
2302
  {
2303
    sql_perror("setreuid");
2304 2305
    unireg_abort(1);
  }
2306
  allow_coredumps();
2307 2308 2309 2310
#endif
}


unknown's avatar
unknown committed
2311
/** Change root user if started with @c --chroot . */
unknown's avatar
unknown committed
2312 2313
static void set_root(const char *path)
{
2314
#if !defined(__WIN__)
unknown's avatar
unknown committed
2315 2316 2317 2318 2319
  if (chroot(path) == -1)
  {
    sql_perror("chroot");
    unireg_abort(1);
  }
2320
  my_setwd("/", MYF(0));
unknown's avatar
unknown committed
2321 2322 2323
#endif
}

2324 2325 2326
/**
   Activate usage of a tcp port
*/
2327

2328
static MYSQL_SOCKET activate_tcp_port(uint port)
unknown's avatar
unknown committed
2329
{
Sergei Golubchik's avatar
Sergei Golubchik committed
2330 2331 2332
  struct addrinfo *ai, *a;
  struct addrinfo hints;
  int error;
2333 2334
  int	arg;
  char port_buf[NI_MAXSERV];
2335
  MYSQL_SOCKET ip_sock= MYSQL_INVALID_SOCKET;
2336 2337
  DBUG_ENTER("activate_tcp_port");
  DBUG_PRINT("general",("IP Socket is %d",port));
unknown's avatar
unknown committed
2338

Sergei Golubchik's avatar
Sergei Golubchik committed
2339 2340 2341 2342
  bzero(&hints, sizeof (hints));
  hints.ai_flags= AI_PASSIVE;
  hints.ai_socktype= SOCK_STREAM;
  hints.ai_family= AF_UNSPEC;
unknown's avatar
unknown committed
2343

2344
  my_snprintf(port_buf, NI_MAXSERV, "%d", port);
Sergei Golubchik's avatar
Sergei Golubchik committed
2345 2346
  error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai);
  if (error != 0)
unknown's avatar
unknown committed
2347
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2348 2349 2350 2351
    DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error));
    sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
    unireg_abort(1);				/* purecov: tested */
  }
2352

Sergei Golubchik's avatar
Sergei Golubchik committed
2353 2354
  for (a= ai; a != NULL; a= a->ai_next)
  {
2355 2356
    ip_sock= mysql_socket_socket(key_socket_tcpip, a->ai_family,
                                 a->ai_socktype, a->ai_protocol);
2357

Sergei Golubchik's avatar
Sergei Golubchik committed
2358
    char ip_addr[INET6_ADDRSTRLEN];
2359 2360 2361 2362 2363 2364
    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
2365
    if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2366 2367 2368 2369 2370 2371 2372 2373 2374 2375
    {
      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
2376
      break;
2377
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2378
  }
2379

2380
  if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2381 2382
  {
    DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
Sergei Golubchik's avatar
Sergei Golubchik committed
2383
    sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
2384 2385
    unireg_abort(1);				/* purecov: tested */
  }
2386

2387 2388
  mysql_socket_set_thread_owner(ip_sock);

2389
#ifndef __WIN__
2390 2391 2392 2393
  /*
    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
2394
  arg= 1;
2395 2396
  (void) mysql_socket_setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
                                 sizeof(arg));
unknown's avatar
unknown committed
2397
#endif /* __WIN__ */
2398 2399

#ifdef IPV6_V6ONLY
Sergei Golubchik's avatar
Sergei Golubchik committed
2400 2401 2402 2403
   /*
     For interoperability with older clients, IPv6 socket should
     listen on both IPv6 and IPv4 wildcard addresses.
     Turn off IPV6_V6ONLY option.
2404

Sergei Golubchik's avatar
Sergei Golubchik committed
2405 2406 2407 2408 2409 2410 2411
     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;
2412 2413
    (void) mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
                                   (char*)&arg, sizeof(arg));
Sergei Golubchik's avatar
Sergei Golubchik committed
2414
  }
2415
#endif
2416 2417 2418 2419 2420 2421 2422 2423
  /*
    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=#).
  */
2424 2425
  int ret;
  uint waited, retry, this_wait;
2426 2427
  for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
  {
2428
    if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
2429 2430 2431
        (socket_errno != SOCKET_EADDRINUSE) ||
        (waited >= mysqld_port_timeout))
      break;
2432
    sql_print_information("Retrying bind on TCP/IP port %u", port);
2433 2434
    this_wait= retry * retry / 3 + 1;
    sleep(this_wait);
unknown's avatar
unknown committed
2435
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
2436
  freeaddrinfo(ai);
2437 2438
  if (ret < 0)
  {
2439 2440 2441 2442
    char buff[100];
    sprintf(buff, "Can't start server: Bind on TCP/IP port. Got error: %d",
            (int) socket_errno);
    sql_perror(buff);
2443 2444 2445 2446
    sql_print_error("Do you already have another mysqld server running on "
                    "port: %u ?", port);
    unireg_abort(1);
  }
2447
  if (mysql_socket_listen(ip_sock,(int) back_log) < 0)
2448 2449 2450 2451 2452 2453 2454 2455
  {
    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);
  }
  DBUG_RETURN(ip_sock);
}
2456

2457 2458 2459 2460
static void network_init(void)
{
#ifdef HAVE_SYS_UN_H
  struct sockaddr_un	UNIXaddr;
2461
  int	arg;
2462
#endif
unknown's avatar
unknown committed
2463
  DBUG_ENTER("network_init");
unknown's avatar
unknown committed
2464

Sergei Golubchik's avatar
Sergei Golubchik committed
2465
  if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
unknown's avatar
unknown committed
2466 2467
    unireg_abort(1);			/* purecov: inspected */

unknown's avatar
unknown committed
2468 2469
  set_ports();

Sergei Golubchik's avatar
Sergei Golubchik committed
2470
  if (report_port == 0)
unknown's avatar
unknown committed
2471
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
2472
    report_port= mysqld_port;
unknown's avatar
unknown committed
2473
  }
Sergei Golubchik's avatar
c  
Sergei Golubchik committed
2474 2475 2476
#ifndef DBUG_OFF
  if (!opt_disable_networking)
    DBUG_ASSERT(report_port != 0);
2477
#endif
2478
  if (!opt_disable_networking && !opt_bootstrap)
unknown's avatar
unknown committed
2479
  {
2480 2481 2482 2483
    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
2484
  }
2485

2486
#ifdef _WIN32
unknown's avatar
unknown committed
2487
  /* create named pipe */
2488
  if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
unknown's avatar
unknown committed
2489
      opt_enable_named_pipe)
unknown's avatar
unknown committed
2490
  {
2491

2492
    strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
2493
	     mysqld_unix_port, NullS);
2494 2495
    bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
    bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
2496
    if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
2497
				      SECURITY_DESCRIPTOR_REVISION))
unknown's avatar
unknown committed
2498 2499 2500 2501 2502 2503 2504 2505 2506
    {
      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
2507
    saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
unknown's avatar
unknown committed
2508 2509
    saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
    saPipeSecurity.bInheritHandle = FALSE;
2510
    if ((hPipe= CreateNamedPipe(pipe_name,
2511
				PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
2512 2513 2514 2515 2516 2517 2518 2519
				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
2520 2521 2522 2523 2524 2525 2526
      {
	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 );
2527
	sql_perror((char *)lpMsgBuf);
unknown's avatar
Merge  
unknown committed
2528
	LocalFree(lpMsgBuf);
unknown's avatar
unknown committed
2529 2530 2531 2532 2533
	unireg_abort(1);
      }
  }
#endif

2534
#if defined(HAVE_SYS_UN_H)
unknown's avatar
unknown committed
2535 2536 2537
  /*
  ** Create the UNIX socket
  */
2538
  if (mysqld_unix_port[0] && !opt_bootstrap)
unknown's avatar
unknown committed
2539
  {
2540
    DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
unknown's avatar
unknown committed
2541

unknown's avatar
unknown committed
2542 2543
    if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
    {
2544
      sql_print_error("The socket file path is too long (> %u): %s",
unknown's avatar
unknown committed
2545
                      (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unknown's avatar
unknown committed
2546 2547
      unireg_abort(1);
    }
2548 2549
    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
2550 2551 2552 2553
    {
      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
      unireg_abort(1);				/* purecov: inspected */
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
2554 2555 2556

    mysql_socket_set_thread_owner(unix_sock);

unknown's avatar
unknown committed
2557 2558
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
2559 2560
    strmov(UNIXaddr.sun_path, mysqld_unix_port);
    (void) unlink(mysqld_unix_port);
2561
    arg= 1;
2562 2563
    (void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,
                                   (char*)&arg, sizeof(arg));
unknown's avatar
unknown committed
2564
    umask(0);
2565 2566 2567
    if (mysql_socket_bind(unix_sock,
                          reinterpret_cast<struct sockaddr *>(&UNIXaddr),
                          sizeof(UNIXaddr)) < 0)
unknown's avatar
unknown committed
2568 2569
    {
      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
2570
      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
unknown's avatar
unknown committed
2571 2572 2573 2574
      unireg_abort(1);					/* purecov: tested */
    }
    umask(((~my_umask) & 0666));
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
2575
    (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
unknown's avatar
unknown committed
2576
#endif
2577
    if (mysql_socket_listen(unix_sock,(int) back_log) < 0)
2578
      sql_print_warning("listen() on Unix socket failed with error %d",
unknown's avatar
unknown committed
2579
		      socket_errno);
unknown's avatar
unknown committed
2580 2581 2582 2583 2584 2585
  }
#endif
  DBUG_PRINT("info",("server started"));
  DBUG_VOID_RETURN;
}

Sergei Golubchik's avatar
Sergei Golubchik committed
2586

unknown's avatar
unknown committed
2587 2588
/**
  Close a connection.
2589

2590 2591
  @param thd        Thread handle.
  @param sql_errno  The error code to send before disconnect.
2592

unknown's avatar
unknown committed
2593
  @note
2594 2595
    For the connection that is doing shutdown, this is called twice
*/
2596
void close_connection(THD *thd, uint sql_errno)
unknown's avatar
unknown committed
2597 2598
{
  DBUG_ENTER("close_connection");
2599 2600 2601 2602

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

Sergei Golubchik's avatar
Sergei Golubchik committed
2603 2604
  thd->print_aborted_warning(3, sql_errno ? ER_DEFAULT(sql_errno)
                                          : "CLOSE_CONNECTION");
2605

2606 2607 2608 2609
  thd->disconnect();

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

2610 2611 2612 2613
  if (MYSQL_CONNECTION_DONE_ENABLED())
  {
    sleep(0); /* Workaround to avoid tailcall optimisation */
  }
2614
  mysql_audit_notify_connection_disconnect(thd, sql_errno);
unknown's avatar
unknown committed
2615 2616
  DBUG_VOID_RETURN;
}
2617 2618
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
2619

2620
/** Called when mysqld is aborted with ^C */
unknown's avatar
unknown committed
2621
/* ARGSUSED */
2622
extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused)))
unknown's avatar
unknown committed
2623
{
2624
  DBUG_ENTER("end_mysqld_signal");
2625 2626
  /* Don't call kill_mysql() if signal thread is not running */
  if (signal_thread_in_use)
Sergei Golubchik's avatar
Sergei Golubchik committed
2627
    kill_mysql();                          // Take down mysqld nicely
unknown's avatar
unknown committed
2628 2629 2630 2631
  DBUG_VOID_RETURN;				/* purecov: deadcode */
}


2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644
/*
  Cleanup THD object

  SYNOPSIS
    thd_cleanup()
    thd		 Thread handler
*/

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

2645 2646 2647 2648 2649 2650 2651
/*
  Decrease number of connections

  SYNOPSIS
    dec_connection_count()
*/

Sergei Golubchik's avatar
Sergei Golubchik committed
2652
void dec_connection_count(THD *thd)
2653 2654
{
  mysql_mutex_lock(&LOCK_connection_count);
Sergei Golubchik's avatar
Sergei Golubchik committed
2655
  (*thd->scheduler->connection_count)--;
2656 2657 2658 2659
  mysql_mutex_unlock(&LOCK_connection_count);
}


Michael Widenius's avatar
Michael Widenius committed
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
/*
  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
2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693
/*
  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
2694
{
unknown's avatar
unknown committed
2695 2696
  DBUG_ENTER("unlink_thd");
  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
2697

2698
  thd_cleanup(thd);
Sergei Golubchik's avatar
Sergei Golubchik committed
2699
  dec_connection_count(thd);
2700 2701 2702 2703 2704

  mysql_mutex_lock(&LOCK_status);
  add_to_status(&global_status_var, &thd->status_var);
  mysql_mutex_unlock(&LOCK_status);

Marc Alff's avatar
Marc Alff committed
2705
  mysql_mutex_lock(&LOCK_thread_count);
2706
  thd->unlink();
2707 2708 2709 2710 2711 2712
  /*
    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););
2713 2714
  mysql_mutex_unlock(&LOCK_thread_count);

Michael Widenius's avatar
Michael Widenius committed
2715 2716 2717
  delete thd;
  thread_safe_decrement32(&thread_count, &thread_count_lock);

unknown's avatar
unknown committed
2718 2719 2720
  DBUG_VOID_RETURN;
}

2721

unknown's avatar
unknown committed
2722 2723 2724 2725 2726 2727 2728
/*
  Store thread in cache for reuse by new connections

  SYNOPSIS
    cache_thread()

  NOTES
Michael Widenius's avatar
Michael Widenius committed
2729
    LOCK_thread_cache is used to protect the cache variables
unknown's avatar
unknown committed
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739

  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
2740 2741
  DBUG_ENTER("cache_thread");

Michael Widenius's avatar
Michael Widenius committed
2742
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2743
  if (cached_thread_count < thread_cache_size &&
2744
      ! abort_loop && !kill_cached_threads)
unknown's avatar
unknown committed
2745 2746
  {
    /* Don't kill the thread, just put it in cache for reuse */
unknown's avatar
unknown committed
2747
    DBUG_PRINT("info", ("Adding thread to cache"));
unknown's avatar
unknown committed
2748
    cached_thread_count++;
2749

2750
#ifdef HAVE_PSI_THREAD_INTERFACE
2751 2752 2753 2754
    /*
      Delete the instrumentation for the job that just completed,
      before parking this pthread in the cache (blocked on COND_thread_cache).
    */
2755
    PSI_THREAD_CALL(delete_current_thread)();
2756 2757
#endif

unknown's avatar
unknown committed
2758
    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
Michael Widenius's avatar
Michael Widenius committed
2759
      mysql_cond_wait(&COND_thread_cache, &LOCK_thread_cache);
unknown's avatar
unknown committed
2760 2761
    cached_thread_count--;
    if (kill_cached_threads)
Marc Alff's avatar
Marc Alff committed
2762
      mysql_cond_signal(&COND_flush_thread_cache);
unknown's avatar
unknown committed
2763 2764
    if (wake_thread)
    {
unknown's avatar
unknown committed
2765
      THD *thd;
unknown's avatar
unknown committed
2766
      wake_thread--;
unknown's avatar
unknown committed
2767
      thd= thread_cache.get();
Michael Widenius's avatar
Michael Widenius committed
2768 2769
      mysql_mutex_unlock(&LOCK_thread_cache);

2770
      thd->thread_stack= (char*) &thd;          // For store_globals
unknown's avatar
unknown committed
2771
      (void) thd->store_globals();
2772

2773
#ifdef HAVE_PSI_THREAD_INTERFACE
2774 2775 2776 2777
      /*
        Create new instrumentation for the new THD job,
        and attach it to this running pthread.
      */
2778 2779 2780
      PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_one_connection,
                                                   thd, thd->thread_id);
      PSI_THREAD_CALL(set_thread)(psi);
2781 2782
#endif

2783 2784 2785 2786 2787 2788
      /*
        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;
2789
      thd->thr_create_utime= microsecond_interval_timer();
2790
      thd->start_utime= thd->thr_create_utime;
Michael Widenius's avatar
Michael Widenius committed
2791 2792 2793

      /* Link thd into list of all active threads (THD's) */
      mysql_mutex_lock(&LOCK_thread_count);
2794
      threads.append(thd);
Michael Widenius's avatar
Michael Widenius committed
2795
      mysql_mutex_unlock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2796
      DBUG_RETURN(1);
unknown's avatar
unknown committed
2797 2798
    }
  }
Michael Widenius's avatar
Michael Widenius committed
2799
  mysql_mutex_unlock(&LOCK_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2800
  DBUG_RETURN(0);
unknown's avatar
unknown committed
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826
}


/*
  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");
  unlink_thd(thd);
2827
  /* Mark that current_thd is not valid anymore */
2828
  set_current_thd(0);
Michael Widenius's avatar
Michael Widenius committed
2829 2830
  if (put_in_cache && cache_thread())
    DBUG_RETURN(0);                             // Thread is reused
unknown's avatar
unknown committed
2831

Michael Widenius's avatar
Michael Widenius committed
2832 2833 2834 2835 2836 2837 2838
  /*
    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)
2839 2840
  {
    mysql_mutex_lock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
2841 2842
    DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
    mysql_cond_broadcast(&COND_thread_count);
2843 2844
    mysql_mutex_unlock(&LOCK_thread_count);
  }
2845
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2846
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
2847 2848
  ERR_remove_state(0);
#endif
2849
  my_thread_end();
unknown's avatar
unknown committed
2850 2851

  pthread_exit(0);
2852
  return 0;                                     // Avoid compiler warnings
unknown's avatar
unknown committed
2853 2854 2855 2856 2857
}


void flush_thread_cache()
{
Michael Widenius's avatar
Michael Widenius committed
2858 2859
  DBUG_ENTER("flush_thread_cache");
  mysql_mutex_lock(&LOCK_thread_cache);
unknown's avatar
unknown committed
2860 2861 2862
  kill_cached_threads++;
  while (cached_thread_count)
  {
Marc Alff's avatar
Marc Alff committed
2863
    mysql_cond_broadcast(&COND_thread_cache);
Michael Widenius's avatar
Michael Widenius committed
2864
    mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache);
unknown's avatar
unknown committed
2865 2866
  }
  kill_cached_threads--;
Michael Widenius's avatar
Michael Widenius committed
2867 2868
  mysql_mutex_unlock(&LOCK_thread_cache);
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2869 2870 2871 2872
}


/******************************************************************************
2873 2874 2875
  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
2876 2877
******************************************************************************/

2878
#if defined(__WIN__)
2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892


/*
  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
2893
#ifndef EMBEDDED_LIBRARY
2894 2895 2896 2897 2898 2899 2900 2901
  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.
     */
2902
#ifndef EMBEDDED_LIBRARY
2903 2904 2905
     if(hEventShutdown)
       kill_mysql();
     else
2906
#endif
2907 2908 2909
       sql_print_warning("CTRL-C ignored during startup");
     DBUG_RETURN(TRUE);
  }
unknown's avatar
unknown committed
2910
#endif
2911 2912 2913 2914 2915 2916 2917 2918 2919
  DBUG_RETURN(FALSE);
}




#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
/*
2920 2921
  Wait for debugger to attach and break into debugger. If debugger is
  not attached, resume after timeout.
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
*/
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
  {
2972
    my_set_exception_pointers(ex_pointers);
2973
    handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991
  }
  __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
2992 2993
static void init_signals(void)
{
2994 2995
  if(opt_console)
    SetConsoleCtrlHandler(console_event_handler,TRUE);
2996

2997
    /* Avoid MessageBox()es*/
2998 2999 3000 3001 3002 3003
  _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);
3004 3005 3006 3007 3008 3009 3010 3011

   /*
     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)
   */
3012 3013
  SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
                               | SEM_NOOPENFILEERRORBOX);
3014
  SetUnhandledExceptionFilter(my_unhandler_exception_filter);
unknown's avatar
unknown committed
3015 3016
}

unknown's avatar
unknown committed
3017

3018
static void start_signal_handler(void)
3019
{
3020
#ifndef EMBEDDED_LIBRARY
3021 3022 3023
  // Save vm id of this process
  if (!opt_bootstrap)
    create_pid_file();
3024
#endif /* EMBEDDED_LIBRARY */
3025
}
unknown's avatar
unknown committed
3026

unknown's avatar
unknown committed
3027

unknown's avatar
unknown committed
3028 3029
static void check_data_home(const char *path)
{}
3030

3031
#endif /* __WIN__ */
unknown's avatar
unknown committed
3032

unknown's avatar
unknown committed
3033 3034 3035 3036 3037 3038 3039 3040 3041

#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

3042 3043 3044 3045 3046 3047 3048 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 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112

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


3113
#if !defined(__WIN__)
unknown's avatar
unknown committed
3114 3115
#ifndef SA_RESETHAND
#define SA_RESETHAND 0
3116
#endif /* SA_RESETHAND */
unknown's avatar
unknown committed
3117 3118
#ifndef SA_NODEFER
#define SA_NODEFER 0
3119
#endif /* SA_NODEFER */
3120

3121 3122
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
3123 3124 3125
static void init_signals(void)
{
  sigset_t set;
3126
  struct sigaction sa;
unknown's avatar
unknown committed
3127 3128
  DBUG_ENTER("init_signals");

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

Michael Widenius's avatar
Michael Widenius committed
3131
  if (opt_stack_trace || (test_flags & TEST_CORE_ON_SIGNAL))
unknown's avatar
unknown committed
3132
  {
unknown's avatar
unknown committed
3133 3134 3135 3136
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
    sigemptyset(&sa.sa_mask);
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);

3137
    my_init_stacktrace();
unknown's avatar
unknown committed
3138
#if defined(__amiga__)
3139
    sa.sa_handler=(void(*)())handle_fatal_signal;
unknown's avatar
unknown committed
3140
#else
3141
    sa.sa_handler=handle_fatal_signal;
unknown's avatar
unknown committed
3142
#endif
unknown's avatar
unknown committed
3143
    sigaction(SIGSEGV, &sa, NULL);
3144
    sigaction(SIGABRT, &sa, NULL);
unknown's avatar
unknown committed
3145
#ifdef SIGBUS
unknown's avatar
unknown committed
3146
    sigaction(SIGBUS, &sa, NULL);
unknown's avatar
unknown committed
3147
#endif
unknown's avatar
unknown committed
3148
    sigaction(SIGILL, &sa, NULL);
3149
    sigaction(SIGFPE, &sa, NULL);
unknown's avatar
unknown committed
3150
  }
3151 3152 3153 3154 3155

#ifdef HAVE_GETRLIMIT
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* Change limits so that we will get a core file */
3156
    STRUCT_RLIMIT rl;
3157
    rl.rlim_cur = rl.rlim_max = (rlim_t) RLIM_INFINITY;
unknown's avatar
unknown committed
3158
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
3159
      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");
3160 3161
  }
#endif
unknown's avatar
unknown committed
3162
  (void) sigemptyset(&set);
3163
  my_sigset(SIGPIPE,SIG_IGN);
unknown's avatar
unknown committed
3164
  sigaddset(&set,SIGPIPE);
3165
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3166 3167
  sigaddset(&set,SIGQUIT);
  sigaddset(&set,SIGHUP);
3168 3169
#endif
  sigaddset(&set,SIGTERM);
3170 3171

  /* Fix signals if blocked by parents (can happen on Mac OS X) */
unknown's avatar
unknown committed
3172
  sigemptyset(&sa.sa_mask);
3173 3174 3175 3176 3177 3178
  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
3179 3180 3181
#ifdef SIGTSTP
  sigaddset(&set,SIGTSTP);
#endif
3182 3183
  if (thd_lib_detected != THD_LIB_LT)
    sigaddset(&set,THR_SERVER_ALARM);
3184
  if (test_flags & TEST_SIGINT)
3185
  {
3186 3187
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    my_sigset(SIGINT, end_mysqld_signal);
unknown's avatar
unknown committed
3188
    sigdelset(&set, SIGINT);
3189
  }
3190 3191
  else
    sigaddset(&set,SIGINT);
unknown's avatar
unknown committed
3192

3193 3194
  sigprocmask(SIG_SETMASK,&set,NULL);
  pthread_sigmask(SIG_SETMASK,&set,NULL);
3195 3196 3197 3198 3199 3200 3201 3202 3203
  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
3204 3205 3206 3207

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

Marc Alff's avatar
Marc Alff committed
3210
  mysql_mutex_lock(&LOCK_thread_count);
Marc Alff's avatar
Marc Alff committed
3211 3212
  if ((error= mysql_thread_create(key_thread_signal_hand,
                                  &signal_thread, &thr_attr, signal_hand, 0)))
unknown's avatar
unknown committed
3213 3214 3215 3216 3217
  {
    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
		    error,errno);
    exit(1);
  }
Marc Alff's avatar
Marc Alff committed
3218 3219
  mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
3220 3221 3222 3223 3224 3225

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


unknown's avatar
unknown committed
3226
/** This threads handles all signals and alarms. */
unknown's avatar
unknown committed
3227
/* ARGSUSED */
3228
pthread_handler_t signal_hand(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
3229 3230 3231 3232 3233
{
  sigset_t set;
  int sig;
  my_thread_init();				// Init new thread
  DBUG_ENTER("signal_hand");
unknown's avatar
unknown committed
3234 3235
  signal_thread_in_use= 1;

unknown's avatar
unknown committed
3236 3237
  /*
    Setup alarm handler
3238 3239
    This should actually be '+ max_number_of_slaves' instead of +10,
    but the +10 should be quite safe.
unknown's avatar
unknown committed
3240
  */
Sergei Golubchik's avatar
Sergei Golubchik committed
3241
  init_thr_alarm(thread_scheduler->max_threads + extra_max_connections +
3242
		 global_system_variables.max_insert_delayed_threads + 10);
3243
  if (test_flags & TEST_SIGINT)
3244
  {
3245 3246 3247
    /* Allow SIGINT to break mysqld. This is for debugging with --gdb */
    (void) sigemptyset(&set);
    (void) sigaddset(&set,SIGINT);
3248 3249
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
  }
unknown's avatar
unknown committed
3250 3251 3252 3253
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND
  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
#endif
3254
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
3255 3256
  (void) sigaddset(&set,SIGQUIT);
  (void) sigaddset(&set,SIGHUP);
3257 3258
#endif
  (void) sigaddset(&set,SIGTERM);
unknown's avatar
unknown committed
3259 3260 3261
  (void) sigaddset(&set,SIGTSTP);

  /* Save pid to this process (or thread on Linux) */
3262
  if (!opt_bootstrap)
3263 3264
    create_pid_file();

3265 3266 3267 3268 3269
  /*
    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
3270
    should not be any other mysql_cond_signal() calls.
3271
  */
Marc Alff's avatar
Marc Alff committed
3272 3273 3274
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
3275

3276
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
unknown's avatar
unknown committed
3277 3278 3279 3280 3281
  for (;;)
  {
    int error;					// Used when debugging
    if (shutdown_in_progress && !abort_loop)
    {
3282
      sig= SIGTERM;
unknown's avatar
unknown committed
3283 3284 3285 3286 3287
      error=0;
    }
    else
      while ((error=my_sigwait(&set,&sig)) == EINTR) ;
    if (cleanup_done)
3288
    {
3289
      DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
3290
      my_thread_end();
3291
      DBUG_LEAVE;                               // Must match DBUG_ENTER()
Sergei Golubchik's avatar
Sergei Golubchik committed
3292
      signal_thread_in_use= 0;
unknown's avatar
unknown committed
3293
      pthread_exit(0);				// Safety
3294
      return 0;                                 // Avoid compiler warnings
3295
    }
unknown's avatar
unknown committed
3296 3297 3298 3299 3300
    switch (sig) {
    case SIGTERM:
    case SIGQUIT:
    case SIGKILL:
#ifdef EXTRA_DEBUG
3301
      sql_print_information("Got signal %d to shutdown mysqld",sig);
unknown's avatar
unknown committed
3302
#endif
3303
      /* switch to the old log message processing */
3304 3305
      logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
                          opt_log ? LOG_FILE:LOG_NONE);
unknown's avatar
unknown committed
3306 3307 3308 3309
      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
      if (!abort_loop)
      {
	abort_loop=1;				// mark abort for threads
3310
#ifdef HAVE_PSI_THREAD_INTERFACE
3311
        /* Delete the instrumentation for the signal thread */
3312
        PSI_THREAD_CALL(delete_current_thread)();
3313
#endif
unknown's avatar
unknown committed
3314 3315
#ifdef USE_ONE_SIGNAL_HAND
	pthread_t tmp;
3316 3317 3318 3319 3320 3321
        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
3322
#else
unknown's avatar
unknown committed
3323
	kill_server((void*) sig);	// MIT THREAD has a alarm thread
unknown's avatar
unknown committed
3324 3325 3326 3327
#endif
      }
      break;
    case SIGHUP:
unknown's avatar
unknown committed
3328 3329
      if (!abort_loop)
      {
3330
        int not_used;
unknown's avatar
Merge  
unknown committed
3331
	mysql_print_status();		// Print some debug info
unknown's avatar
unknown committed
3332 3333
	reload_acl_and_cache((THD*) 0,
			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
unknown's avatar
Merge  
unknown committed
3334
			      REFRESH_GRANT |
unknown's avatar
unknown committed
3335
			      REFRESH_THREADS | REFRESH_HOSTS),
unknown's avatar
unknown committed
3336
			     (TABLE_LIST*) 0, &not_used); // Flush logs
unknown's avatar
unknown committed
3337
      }
3338
      /* reenable logs after the options were reloaded */
3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350
      if (log_output_options & LOG_NONE)
      {
        logger.set_handlers(LOG_FILE,
                            opt_slow_log ? LOG_TABLE : LOG_NONE,
                            opt_log ? LOG_TABLE : LOG_NONE);
      }
      else
      {
        logger.set_handlers(LOG_FILE,
                            opt_slow_log ? log_output_options : LOG_NONE,
                            opt_log ? log_output_options : LOG_NONE);
      }
unknown's avatar
unknown committed
3351 3352 3353 3354 3355 3356 3357 3358
      break;
#ifdef USE_ONE_SIGNAL_HAND
    case THR_SERVER_ALARM:
      process_alarm(sig);			// Trigger alarms.
      break;
#endif
    default:
#ifdef EXTRA_DEBUG
3359
      sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
unknown's avatar
unknown committed
3360 3361 3362 3363 3364 3365 3366
#endif
      break;					/* purecov: tested */
    }
  }
  return(0);					/* purecov: deadcode */
}

unknown's avatar
unknown committed
3367
static void check_data_home(const char *path)
unknown's avatar
unknown committed
3368
{}
unknown's avatar
unknown committed
3369

3370
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
3371 3372 3373
#endif	/* __WIN__*/


unknown's avatar
unknown committed
3374
/**
unknown's avatar
Merge  
unknown committed
3375
  All global error messages are sent here where the first one is stored
unknown's avatar
unknown committed
3376
  for the client.
unknown's avatar
unknown committed
3377 3378
*/
/* ARGSUSED */
Marc Alff's avatar
Marc Alff committed
3379
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3380

Marc Alff's avatar
Marc Alff committed
3381
void my_message_sql(uint error, const char *str, myf MyFlags)
unknown's avatar
unknown committed
3382
{
Marc Alff's avatar
Marc Alff committed
3383
  THD *thd= current_thd;
3384
  Sql_condition::enum_warning_level level;
3385
  sql_print_message_func func;
unknown's avatar
unknown committed
3386
  DBUG_ENTER("my_message_sql");
3387 3388
  DBUG_PRINT("error", ("error: %u  message: '%s'  Flag: %lu", error, str,
                       MyFlags));
3389 3390

  DBUG_ASSERT(str != NULL);
3391
  DBUG_ASSERT(error != 0);
3392

3393
  mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);
3394 3395
  if (MyFlags & ME_JUST_INFO)
  {
3396
    level= Sql_condition::WARN_LEVEL_NOTE;
3397 3398 3399 3400
    func= sql_print_information;
  }
  else if (MyFlags & ME_JUST_WARNING)
  {
3401
    level= Sql_condition::WARN_LEVEL_WARN;
3402 3403 3404 3405
    func= sql_print_warning;
  }
  else
  {
3406
    level= Sql_condition::WARN_LEVEL_ERROR;
3407 3408
    func= sql_print_error;
  }
3409

Marc Alff's avatar
Marc Alff committed
3410
  if (thd)
unknown's avatar
unknown committed
3411
  {
Marc Alff's avatar
Marc Alff committed
3412 3413
    if (MyFlags & ME_FATALERROR)
      thd->is_fatal_error= 1;
Sergei Golubchik's avatar
Sergei Golubchik committed
3414
    (void) thd->raise_condition(error, NULL, level, str);
unknown's avatar
unknown committed
3415
  }
3416 3417

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

3420
  if (!thd || thd->log_all_errors || (MyFlags & ME_NOREFRESH))
3421
    (*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
Marc Alff's avatar
Marc Alff committed
3422
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
3423 3424
}

3425

3426 3427
extern "C" void *my_str_malloc_mysqld(size_t size);
extern "C" void my_str_free_mysqld(void *ptr);
3428
extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
3429 3430

void *my_str_malloc_mysqld(size_t size)
3431 3432 3433 3434 3435
{
  return my_malloc(size, MYF(MY_FAE));
}


3436
void my_str_free_mysqld(void *ptr)
3437
{
3438
  my_free(ptr);
3439
}
3440 3441 3442 3443 3444

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


unknown's avatar
unknown committed
3447 3448
#ifdef __WIN__

3449
pthread_handler_t handle_shutdown(void *arg)
unknown's avatar
unknown committed
3450 3451 3452 3453 3454 3455
{
  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
3456
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
3457
  if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
3458
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
3459 3460 3461 3462 3463
     kill_server(MYSQL_KILL_SIGNAL);
  return 0;
}
#endif

3464
#include <mysqld_default_groups.h>
unknown's avatar
Merge  
unknown committed
3465

3466
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
3467 3468
static const int load_default_groups_sz=
sizeof(load_default_groups)/sizeof(load_default_groups[0]);
unknown's avatar
Merge  
unknown committed
3469
#endif
unknown's avatar
unknown committed
3470

unknown's avatar
unknown committed
3471

3472
#ifndef EMBEDDED_LIBRARY
3473 3474 3475
/**
  This function is used to check for stack overrun for pathological
  cases of  regular expressions and 'like' expressions.
3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
*/
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.
3491 3492 3493 3494 3495
  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)
3496
{
3497 3498
  if (recurse_level % 16 != 0)
    return 0;
3499
  return check_enough_stack_size_slow();
3500 3501 3502 3503
}
#endif


3504 3505 3506 3507 3508 3509 3510 3511

/*
   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
3512
  my_str_realloc= &my_str_realloc_mysqld;
3513 3514 3515
#ifndef EMBEDDED_LIBRARY
  my_string_stack_guard= check_enough_stack_size;
#endif
3516
}
3517 3518 3519 3520 3521 3522 3523 3524


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;
3525
#endif
3526
}
3527 3528


unknown's avatar
unknown committed
3529 3530
/**
  Initialize one of the global date/time format variables.
3531

unknown's avatar
unknown committed
3532 3533
  @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
3534

unknown's avatar
unknown committed
3535
  @retval
3536
    0 ok
unknown's avatar
unknown committed
3537
  @retval
3538 3539 3540
    1 error
*/

unknown's avatar
unknown committed
3541
static bool init_global_datetime_format(timestamp_type format_type,
3542
                                        DATE_TIME_FORMAT *format)
3543
{
3544 3545 3546 3547 3548
  /*
    Get command line option
    format->format.str is already set by my_getopt
  */
  format->format.length= strlen(format->format.str);
3549

3550
  if (parse_date_time_format(format_type, format))
3551
  {
3552 3553 3554
    fprintf(stderr, "Wrong date/time format specifier: %s\n",
            format->format.str);
    return true;
3555
  }
3556
  return false;
3557 3558
}

unknown's avatar
unknown committed
3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569
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},
3570
  {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
  {"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},
  {"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},
3584
  {"create_role",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599
  {"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},
3600
  {"drop_role",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3601 3602 3603 3604 3605 3606 3607 3608
  {"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},
3609
  {"get_diagnostics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3610
  {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
3611
  {"grant_role",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633
  {"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
3634
  {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3635 3636
  {"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},
3637
  {"revoke_role",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ROLE]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3638 3639 3640 3641 3642 3643 3644 3645 3646
  {"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},
3647
  {"show_client_statistics",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CLIENT_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660
  {"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},
3661
  {"show_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
3662
  {"show_explain",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EXPLAIN]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3663 3664 3665 3666 3667 3668
  {"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},
3669
  {"show_index_statistics",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS},
3670
  {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3671 3672 3673 3674 3675 3676 3677 3678 3679
  {"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
3680 3681
  {"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},
3682
  {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3683 3684 3685 3686
  {"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},
3687
  {"show_table_statistics",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3688 3689 3690
  {"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},
3691
  {"show_user_statistics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_USER_STATS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3692 3693
  {"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},
3694
  {"shutdown",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHUTDOWN]), SHOW_LONG_STATUS},
3695
  {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
3696 3697
  {"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
3698 3699 3700 3701
  {"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
3702
  {"stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3703 3704
  {"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},
3705 3706
  {"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
3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717
  {"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},
3718
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
3719
};
3720

Sergei Golubchik's avatar
Sergei Golubchik committed
3721

3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783
#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;
  }

  /* "statement/com/query" can mutate into "statement/sql/..." */
  com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE;
}
#endif


3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
#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
3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826
/* 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);
      }
    }
  }
3827 3828 3829
  // 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
3830 3831 3832
}
}

3833

Marc Alff's avatar
Marc Alff committed
3834
static int init_common_variables()
unknown's avatar
unknown committed
3835
{
unknown's avatar
unknown committed
3836
  umask(((~my_umask) & 0666));
unknown's avatar
unknown committed
3837 3838 3839 3840 3841 3842
  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
3843
  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
Sergei Golubchik's avatar
Sergei Golubchik committed
3844

3845 3846 3847 3848 3849 3850 3851 3852
  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
3853 3854
  set_malloc_size_cb(my_malloc_size_cb_func);

3855
  init_libstrings();
unknown's avatar
unknown committed
3856 3857
  tzset();			// Set tzname

3858
  sf_leaking_memory= 0; // no memory leaks from now on
3859 3860 3861
#ifdef SAFEMALLOC
  sf_malloc_dbug_id= mariadb_dbug_id;
#endif
3862

unknown's avatar
SCRUM  
unknown committed
3863
  max_system_variables.pseudo_thread_id= (ulong)~0;
3864
  server_start_time= flush_status_time= my_time(0);
3865

3866
  global_rpl_filter= new Rpl_filter;
3867
  binlog_filter= new Rpl_filter;
3868
  if (!global_rpl_filter || !binlog_filter)
3869 3870
  {
    sql_perror("Could not allocate replication and binlog filters");
3871
    return 1;
3872 3873
  }

3874 3875
  if (init_thread_environment() ||
      mysql_init_variables())
unknown's avatar
unknown committed
3876
    return 1;
unknown's avatar
unknown committed
3877

3878 3879 3880
  if (ignore_db_dirs_init())
    return 1;

unknown's avatar
unknown committed
3881
#ifdef HAVE_TZNAME
3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894
  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
3895
  strmake_buf(system_time_zone, tz_name);
3896 3897
#endif /* _WIN32 */
#endif /* HAVE_TZNAME */
3898

3899
  /*
unknown's avatar
unknown committed
3900
    We set SYSTEM time zone as reasonable default and
3901 3902 3903 3904 3905
    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
3906

3907 3908 3909
#ifdef HAVE_PSI_INTERFACE
  /*
    Complete the mysql_bin_log initialization.
3910 3911 3912
    Instrumentation keys are known only after the performance schema
    initialization, and can not be set in the MYSQL_BIN_LOG
    constructor (called before main()).
3913 3914 3915 3916
  */
  mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
                             key_BINLOG_update_cond,
                             key_file_binlog,
3917 3918
                             key_file_binlog_index,
                             key_BINLOG_COND_queue_busy);
3919 3920
#endif

unknown's avatar
unknown committed
3921
  /*
3922
    Init mutexes for the global MYSQL_BIN_LOG objects.
unknown's avatar
unknown committed
3923
    As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3924 3925
    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
3926 3927
  */
  mysql_bin_log.init_pthread_objects();
3928

3929 3930 3931 3932 3933 3934 3935
  /* 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;
  }

3936 3937
  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
  {
3938 3939 3940 3941
    /*
      Get hostname of computer (used by 'show variables') and as default
      basename for the pid file if --log-basename is not given.
    */
3942 3943
    strmake(glob_hostname, STRING_WITH_LEN("localhost"));
    sql_print_warning("gethostname failed, using '%s' as hostname",
3944
                        glob_hostname);
Sergei Golubchik's avatar
Sergei Golubchik committed
3945
    opt_log_basename= const_cast<char *>("mysql");
3946 3947
  }
  else
Sergei Golubchik's avatar
Sergei Golubchik committed
3948
    opt_log_basename= glob_hostname;
3949

Sergei Golubchik's avatar
Sergei Golubchik committed
3950
  if (!*pidfile_name)
3951
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
3952 3953
    strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
    strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
3954
  }
unknown's avatar
unknown committed
3955

3956 3957 3958 3959 3960 3961 3962
  /*
    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.
3963 3964 3965 3966

    From MySQL 5.5 onwards, the default storage engine is InnoDB
    (except in the embedded server, where the default continues to
    be MyISAM)
3967
  */
3968
#if defined(WITH_INNOBASE_STORAGE_ENGINE) || defined(WITH_XTRADB_STORAGE_ENGINE)
3969
  default_storage_engine= const_cast<char *>("InnoDB");
3970 3971
#else
  default_storage_engine= const_cast<char *>("MyISAM");
3972
#endif
3973

3974 3975 3976
  /*
    Add server status variables to the dynamic list of
    status variables that is shown by SHOW STATUS.
3977
    Later, in plugin_init, and mysql_install_plugin
3978 3979 3980 3981 3982
    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
3983 3984 3985 3986 3987
#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
3988
    There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
unknown's avatar
unknown committed
3989 3990 3991 3992 3993 3994 3995 3996
    (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
3997
      Com_stmt_reprepare       => com_stmt_reprepare
unknown's avatar
unknown committed
3998 3999 4000
      Com_stmt_reset           => com_stmt_reset
      Com_stmt_send_long_data  => com_stmt_send_long_data

4001 4002 4003
    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
4004
  */
4005
  compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
unknown's avatar
unknown committed
4006
                     SQLCOM_END + 8);
unknown's avatar
unknown committed
4007 4008
#endif

Marc Alff's avatar
Marc Alff committed
4009
  if (get_options(&remaining_argc, &remaining_argv))
4010
    return 1;
4011 4012
  set_server_version();

4013
#ifndef EMBEDDED_LIBRARY
4014
  if (opt_abort && !opt_verbose)
4015 4016 4017
    unireg_abort(0);
#endif /*!EMBEDDED_LIBRARY*/

unknown's avatar
unknown committed
4018 4019 4020
  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
4021 4022 4023 4024
#ifdef HAVE_LARGE_PAGES
  /* Initialize large page size */
  if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
  {
4025 4026
      DBUG_PRINT("info", ("Large page set, large_page_size = %d",
                 opt_large_page_size));
unknown's avatar
Merge  
unknown committed
4027 4028 4029
      my_use_large_pages= 1;
      my_large_page_size= opt_large_page_size;
  }
4030 4031 4032 4033 4034 4035 4036 4037
  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
4038
#endif /* HAVE_LARGE_PAGES */
4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054
#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;
4055
   size_t max_desired_page_size;
4056
   if (opt_super_large_pages)
4057
     max_desired_page_size= SUPER_LARGE_PAGESIZE;
4058
   else
4059
     max_desired_page_size= LARGE_PAGESIZE;
4060 4061 4062 4063 4064 4065
   nelem = getpagesizes(NULL, 0);
   if (nelem > 0)
   {
     size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
     if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
     {
4066 4067
       size_t max_page_size= 0;
       for (int i= 0; i < nelem; i++)
4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088
       {
         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
4089

unknown's avatar
unknown committed
4090 4091
  /* connections and databases needs lots of files */
  {
4092
    uint files, wanted_files, max_open_files;
4093

4094
    /* MyISAM requires two file handles per table. */
4095
    wanted_files= (10 + max_connections + extra_max_connections +
4096
                   tc_size * 2);
4097 4098 4099 4100 4101 4102 4103 4104 4105 4106
    /*
      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).
    */
4107
    max_open_files= MY_MAX(MY_MAX(wanted_files,
4108
                            (max_connections + extra_max_connections)*5),
4109 4110
                        open_files_limit);
    files= my_set_max_open_files(max_open_files);
4111 4112

    if (files < wanted_files)
unknown's avatar
unknown committed
4113
    {
4114 4115
      if (!open_files_limit)
      {
4116 4117 4118 4119
        /*
          If we have requested too much file handles than we bring
          max_connections in supported bounds.
        */
4120
        max_connections= (ulong) MY_MIN(files-10-TABLE_OPEN_CACHE_MIN*2,
4121 4122
                                     max_connections);
        /*
4123
          Decrease tc_size according to max_connections, but
4124
          not below TABLE_OPEN_CACHE_MIN.  Outer MY_MIN() ensures that we
4125
          never increase tc_size automatically (that could
4126 4127
          happen if max_connections is decreased above).
        */
4128 4129
        tc_size= (ulong) MY_MIN(MY_MAX((files - 10 - max_connections) / 2,
                                       TABLE_OPEN_CACHE_MIN), tc_size);
4130 4131
	DBUG_PRINT("warning",
		   ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
4132
		    files, max_connections, tc_size));
unknown's avatar
unknown committed
4133
	if (global_system_variables.log_warnings)
4134
	  sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
4135
			files, max_connections, tc_size);
4136
      }
unknown's avatar
unknown committed
4137
      else if (global_system_variables.log_warnings)
4138
	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
4139
    }
unknown's avatar
unknown committed
4140
    open_files_limit= files;
unknown's avatar
unknown committed
4141 4142
  }
  unireg_init(opt_specialflag); /* Set up extern variabels */
4143 4144 4145 4146 4147 4148 4149
  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;
4150 4151
  if (init_errmessage())	/* Read error messages from file */
    return 1;
4152
  init_client_errs();
Sergei Golubchik's avatar
Sergei Golubchik committed
4153
  mysql_library_init(unused,unused,unused); /* for replication */
unknown's avatar
unknown committed
4154
  lex_init();
4155 4156
  if (item_create_init())
    return 1;
unknown's avatar
unknown committed
4157
  item_init();
4158
  init_pcre();
4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185
  /*
    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;
  }

4186 4187
  if (default_collation_name)
  {
unknown's avatar
unknown committed
4188 4189
    CHARSET_INFO *default_collation;
    default_collation= get_charset_by_name(default_collation_name, MYF(0));
unknown's avatar
unknown committed
4190 4191
    if (!default_collation)
    {
4192 4193 4194 4195
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
      buffered_logs.print();
      buffered_logs.cleanup();
#endif
4196
      sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
unknown's avatar
unknown committed
4197 4198 4199
      return 1;
    }
    if (!my_charset_same(default_charset_info, default_collation))
4200
    {
4201
      sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
4202 4203 4204 4205 4206 4207
		      default_collation_name,
		      default_charset_info->csname);
      return 1;
    }
    default_charset_info= default_collation;
  }
4208 4209 4210 4211
  /* 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;
4212
  global_system_variables.character_set_results= default_charset_info;
4213
  global_system_variables.character_set_client=  default_charset_info;
4214

4215
  if (!(character_set_filesystem=
unknown's avatar
unknown committed
4216 4217 4218 4219 4220
        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;

4221 4222 4223
  if (!(my_default_lc_time_names=
        my_locale_by_name(lc_time_names_name)))
  {
unknown's avatar
unknown committed
4224
    sql_print_error("Unknown locale: '%s'", lc_time_names_name);
4225 4226 4227
    return 1;
  }
  global_system_variables.lc_time_names= my_default_lc_time_names;
4228

4229
  /* check log options and issue warnings if needed */
4230 4231
  if (opt_log && opt_logname && *opt_logname &&
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4232 4233
    sql_print_warning("Although a path was specified for the "
                      "--log option, log tables are used. "
4234
                      "To enable logging to files use the --log-output option.");
4235

4236 4237
  if (opt_slow_log && opt_slow_logname && *opt_slow_logname &&
      !(log_output_options & (LOG_FILE | LOG_NONE)))
4238
    sql_print_warning("Although a path was specified for the "
Konstantin Osipov's avatar
Konstantin Osipov committed
4239
                      "--log-slow-queries option, log tables are used. "
4240
                      "To enable logging to files use the --log-output=file option.");
4241

Sergei Golubchik's avatar
Sergei Golubchik committed
4242 4243 4244 4245
  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);
4246

4247 4248 4249 4250 4251 4252
#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) */

4253
#if (ENABLE_TEMP_POOL)
4254
  if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
4255
    return 1;
4256 4257 4258 4259
#else
  use_temp_pool= 0;
#endif

4260
  if (my_dboptions_cache_init())
unknown's avatar
unknown committed
4261 4262
    return 1;

4263 4264 4265 4266 4267 4268
  /*
    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));
4269 4270
  lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
  if (!lower_case_table_names && lower_case_file_system == 1)
4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289
  {
    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 &&
4290
           !(lower_case_file_system= (lower_case_file_system == 1)))
4291 4292 4293 4294 4295 4296 4297 4298
  {
    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;
  }
4299 4300
  else
  {
4301
    lower_case_file_system= (lower_case_file_system == 1);
4302
  }
4303 4304 4305 4306 4307 4308

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

4309 4310 4311 4312 4313 4314
  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
4315 4316
  return 0;
}
unknown's avatar
unknown committed
4317

4318 4319

static int init_thread_environment()
unknown's avatar
unknown committed
4320
{
4321
  DBUG_ENTER("init_thread_environment");
Marc Alff's avatar
Marc Alff committed
4322
  mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
Michael Widenius's avatar
Michael Widenius committed
4323
  mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4324
  mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4325
  mysql_mutex_init(key_LOCK_delayed_insert,
Marc Alff's avatar
Marc Alff committed
4326 4327 4328 4329 4330
                   &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
4331 4332 4333 4334 4335
  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
4336
  mysql_mutex_record_order(&LOCK_active_mi, &LOCK_global_system_variables);
Marc Alff's avatar
Marc Alff committed
4337 4338 4339 4340 4341 4342
  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);
4343
  mysql_mutex_init(key_LOCK_uuid_short_generator,
Sergei Golubchik's avatar
Sergei Golubchik committed
4344
                   &LOCK_short_uuid_generator, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
4345 4346
  mysql_mutex_init(key_LOCK_connection_count,
                   &LOCK_connection_count, MY_MUTEX_INIT_FAST);
4347 4348 4349 4350 4351 4352 4353
  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
4354 4355
  mysql_mutex_init(key_LOCK_prepare_ordered, &LOCK_prepare_ordered,
                   MY_MUTEX_INIT_SLOW);
4356
  mysql_cond_init(key_COND_prepare_ordered, &COND_prepare_ordered, NULL);
Sergei Golubchik's avatar
Sergei Golubchik committed
4357 4358
  mysql_mutex_init(key_LOCK_commit_ordered, &LOCK_commit_ordered,
                   MY_MUTEX_INIT_SLOW);
4359

4360
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
4361 4362
  mysql_mutex_init(key_LOCK_des_key_file,
                   &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
unknown's avatar
unknown committed
4363 4364 4365 4366
#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)
4367
    mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
unknown's avatar
unknown committed
4368 4369 4370 4371 4372 4373
  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
4374
#endif
Marc Alff's avatar
Marc Alff committed
4375 4376 4377
  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
4378 4379 4380
  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
4381
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
4382
  mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
4383
#endif
Marc Alff's avatar
Marc Alff committed
4384 4385 4386
  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
4387
  sp_cache_init();
4388
#ifdef HAVE_EVENT_SCHEDULER
4389
  Events::init_mutexes();
4390
#endif
4391
  init_show_explain_psi_keys();
unknown's avatar
unknown committed
4392 4393 4394 4395 4396
  /* 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
4397

4398 4399 4400 4401
#ifdef HAVE_REPLICATION
  rpl_init_gtid_slave_state();
#endif

4402
  DBUG_RETURN(0);
unknown's avatar
unknown committed
4403 4404
}

4405

unknown's avatar
unknown committed
4406
#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
4407
static unsigned long openssl_id_function()
4408
{
4409
  return (unsigned long) pthread_self();
4410
}
4411 4412 4413


static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
4414
{
4415
  openssl_lock_t *lock= new openssl_lock_t;
4416
  mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
4417 4418 4419 4420
  return lock;
}


4421
static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
4422 4423
				    int line)
{
4424
  mysql_rwlock_destroy(&lock->lock);
4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440
  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);
}


4441
static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
4442 4443 4444 4445 4446 4447 4448 4449
			 int line)
{
  int err;
  char const *what;

  switch (mode) {
  case CRYPTO_LOCK|CRYPTO_READ:
    what = "read lock";
4450
    err= mysql_rwlock_rdlock(&lock->lock);
4451 4452 4453
    break;
  case CRYPTO_LOCK|CRYPTO_WRITE:
    what = "write lock";
4454
    err= mysql_rwlock_wrlock(&lock->lock);
4455 4456 4457 4458
    break;
  case CRYPTO_UNLOCK|CRYPTO_READ:
  case CRYPTO_UNLOCK|CRYPTO_WRITE:
    what = "unlock";
4459
    err= mysql_rwlock_unlock(&lock->lock);
4460 4461 4462 4463 4464 4465
    break;
  default:
    /* Unknown locking mode. */
    sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
    abort();
  }
4466
  if (err)
4467
  {
4468
    sql_print_error("Fatal: can't %s OpenSSL lock", what);
4469 4470 4471 4472 4473 4474
    abort();
  }
}
#endif /* HAVE_OPENSSL */


unknown's avatar
unknown committed
4475 4476
static void init_ssl()
{
unknown's avatar
unknown committed
4477
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
4478 4479
  if (opt_use_ssl)
  {
4480 4481
    enum enum_ssl_init_error error= SSL_INITERR_NOERROR;

4482 4483 4484
    /* 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,
4485 4486
					  opt_ssl_cipher, &error,
                                          opt_ssl_crl, opt_ssl_crlpath);
unknown's avatar
Merge  
unknown committed
4487
    DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
4488
    ERR_remove_state(0);
unknown's avatar
unknown committed
4489
    if (!ssl_acceptor_fd)
4490
    {
4491
      sql_print_warning("Failed to setup SSL");
4492
      sql_print_warning("SSL error: %s", sslGetErrString(error));
unknown's avatar
unknown committed
4493
      opt_use_ssl = 0;
4494
      have_ssl= SHOW_OPTION_DISABLED;
4495 4496 4497 4498
    }
  }
  else
  {
4499
    have_ssl= SHOW_OPTION_DISABLED;
unknown's avatar
unknown committed
4500
  }
unknown's avatar
unknown committed
4501 4502
  if (des_key_file)
    load_des_key_file(des_key_file);
unknown's avatar
unknown committed
4503
#endif /* HAVE_OPENSSL && ! EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
4504
}
unknown's avatar
unknown committed
4505

4506

4507 4508 4509
static void end_ssl()
{
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
4510
#ifndef EMBEDDED_LIBRARY
4511 4512 4513 4514 4515
  if (ssl_acceptor_fd)
  {
    free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
    ssl_acceptor_fd= 0;
  }
Konstantin Osipov's avatar
Konstantin Osipov committed
4516
#endif /* ! EMBEDDED_LIBRARY */
4517 4518 4519
#endif /* HAVE_OPENSSL */
}

4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545
#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
4546

unknown's avatar
unknown committed
4547 4548
static int init_server_components()
{
4549
  DBUG_ENTER("init_server_components");
unknown's avatar
unknown committed
4550 4551 4552 4553
  /*
    We need to call each of these following functions to ensure that
    all things are initialized so that unireg_abort() doesn't fail
  */
4554
  mdl_init();
4555
  if (tdc_init() | hostname_cache_init())
4556
    unireg_abort(1);
unknown's avatar
unknown committed
4557

4558
  query_cache_set_min_res_unit(query_cache_min_res_unit);
unknown's avatar
unknown committed
4559
  query_cache_init();
unknown's avatar
unknown committed
4560
  query_cache_resize(query_cache_size);
4561
  query_cache_result_size_limit(query_cache_limit);
4562
  my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
4563
  setup_fpu();
unknown's avatar
unknown committed
4564
  init_thr_lock();
4565
  my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345);
unknown's avatar
SCRUM  
unknown committed
4566
#ifdef HAVE_REPLICATION
4567
  init_slave_list();
4568
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
4569
  wt_init();
unknown's avatar
unknown committed
4570

4571 4572
  /* Setup logs */

4573 4574 4575 4576 4577
  /*
    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.
  */
4578
  if (opt_error_log && !opt_abort)
4579 4580
  {
    if (!log_error_file_ptr[0])
4581
      fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
4582 4583 4584 4585
                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);
4586 4587 4588 4589 4590
    /*
      _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;
4591
    if (!log_error_file[0])
4592
      opt_error_log= 0;                         // Too long file name
4593 4594
    else
    {
4595
      my_bool res;
4596
#ifndef EMBEDDED_LIBRARY
4597 4598 4599
      res= reopen_fstreams(log_error_file, stdout, stderr);
#else
      res= reopen_fstreams(log_error_file, NULL, stderr);
4600
#endif
4601 4602 4603

      if (!res)
        setbuf(stderr, NULL);
4604 4605 4606 4607 4608

#ifdef _WIN32
      /* Add error log to windows crash reporting. */
      add_file_to_crash_report(log_error_file);
#endif
4609 4610 4611
    }
  }

4612 4613
  /* set up the hook before initializing plugins which may use it */
  error_handler_hook= my_message_sql;
Sergei Golubchik's avatar
Sergei Golubchik committed
4614
  proc_info_hook= set_thd_stage_info;
4615

Marc Alff's avatar
Marc Alff committed
4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627
#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 */

4628 4629 4630 4631 4632 4633 4634 4635 4636
#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
4637 4638 4639 4640 4641 4642
  if (xid_cache_init())
  {
    sql_print_error("Out of memory");
    unireg_abort(1);
  }

4643 4644 4645 4646
  /*
    initialize delegates for extension observers, errors have already
    been reported in the function
  */
He Zhenxing's avatar
He Zhenxing committed
4647 4648 4649
  if (delegates_init())
    unireg_abort(1);

unknown's avatar
unknown committed
4650
  /* need to configure logging before initializing storage engines */
4651
  if (!opt_bin_log_used)
unknown's avatar
unknown committed
4652
  {
4653 4654 4655 4656 4657 4658
    if (opt_log_slave_updates)
      sql_print_warning("You need to use --log-bin to make "
                        "--log-slave-updates work.");
    if (binlog_format_used)
      sql_print_warning("You need to use --log-bin to make "
                        "--binlog-format work.");
4659
  }
4660

4661
  /* Check that we have not let the format to unspecified at this point */
4662
  DBUG_ASSERT((uint)global_system_variables.binlog_format <=
4663
              array_elements(binlog_format_names)-1);
4664

unknown's avatar
unknown committed
4665
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
4666 4667
  if (opt_log_slave_updates && replicate_same_server_id)
  {
4668 4669 4670
    if (opt_bin_log)
    {
      sql_print_error("using --replicate-same-server-id in conjunction with \
unknown's avatar
unknown committed
4671 4672
--log-slave-updates is impossible, it would lead to infinite loops in this \
server.");
4673 4674 4675 4676 4677 4678
      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
4679
  }
unknown's avatar
unknown committed
4680
#endif
4681

4682 4683
  DBUG_ASSERT(!opt_bin_log || opt_bin_logname);

unknown's avatar
Merge  
unknown committed
4684
  if (opt_bin_log)
4685
  {
4686 4687
    /* Reports an error and aborts, if the --log-bin's path 
       is a directory.*/
4688
    if (opt_bin_logname[0] && 
4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706
        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
4707 4708 4709
    char buf[FN_REFLEN];
    const char *ln;
    ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
4710
    if (!opt_bin_logname[0] && !opt_binlog_index_name)
4711 4712
    {
      /*
unknown's avatar
Merge  
unknown committed
4713 4714 4715 4716 4717
        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.
4718
      */
4719 4720 4721 4722
      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
4723
                        "changed! Please use '--log-basename=%s' or "
4724
                        "'--log-bin=%s' to avoid this problem.",
Sergei Golubchik's avatar
Sergei Golubchik committed
4725
                        opt_log_basename, ln);
4726
    }
unknown's avatar
Merge  
unknown committed
4727
    if (ln == buf)
4728
    {
4729
      opt_bin_logname= my_once_strdup(buf, MYF(MY_WME));
4730
    }
4731
    if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
unknown's avatar
unknown committed
4732 4733 4734
    {
      unireg_abort(1);
    }
4735 4736
  }

4737
  /* call ha_init_key_cache() on all key caches to init them */
4738
  process_key_caches(&ha_init_key_cache, 0);
4739

4740 4741 4742
  init_global_table_stats();
  init_global_index_stats();

4743 4744 4745 4746
  /* Allow storage engine to give real error messages */
  if (ha_init_errors())
    DBUG_RETURN(1);

Marc Alff's avatar
Marc Alff committed
4747
  if (plugin_init(&remaining_argc, remaining_argv,
4748
                  (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
4749
                  (opt_abort ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
4750 4751 4752
  {
    sql_print_error("Failed to initialize plugins.");
    unireg_abort(1);
unknown's avatar
unknown committed
4753
  }
4754
  plugins_are_initialized= TRUE;  /* Don't separate from init function */
unknown's avatar
unknown committed
4755

unknown's avatar
unknown committed
4756
  /* we do want to exit if there are any other unknown options */
Marc Alff's avatar
Marc Alff committed
4757
  if (remaining_argc > 1)
unknown's avatar
unknown committed
4758 4759
  {
    int ho_error;
unknown's avatar
unknown committed
4760
    struct my_option no_opts[]=
unknown's avatar
unknown committed
4761 4762 4763 4764 4765
    {
      {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
4766
      that there are unprocessed options.
unknown's avatar
unknown committed
4767 4768
    */
    my_getopt_skip_unknown= 0;
unknown's avatar
unknown committed
4769

Marc Alff's avatar
Marc Alff committed
4770
    if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
4771
                                  mysqld_get_one_option)))
unknown's avatar
unknown committed
4772
      unireg_abort(ho_error);
Marc Alff's avatar
Marc Alff committed
4773 4774 4775
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
4776
    my_getopt_skip_unknown= TRUE;
unknown's avatar
unknown committed
4777

Marc Alff's avatar
Marc Alff committed
4778
    if (remaining_argc > 1)
unknown's avatar
unknown committed
4779
    {
4780
      fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n",
Marc Alff's avatar
Marc Alff committed
4781
              my_progname, remaining_argv[1]);
unknown's avatar
unknown committed
4782 4783
      unireg_abort(1);
    }
unknown's avatar
unknown committed
4784 4785
  }

4786
  if (opt_abort)
4787 4788
    unireg_abort(0);

unknown's avatar
unknown committed
4789
  /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
4790 4791
  if (!DEFAULT_ERRMSGS[0][0])
    unireg_abort(1);  
unknown's avatar
unknown committed
4792

unknown's avatar
unknown committed
4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819
  /* 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
4820 4821
    LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
unknown's avatar
unknown committed
4822
    {
4823
      /* purecov: begin inspected */
unknown's avatar
unknown committed
4824 4825
      sql_print_error("CSV engine is not present, falling back to the "
                      "log files");
unknown's avatar
unknown committed
4826
      log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
4827
      /* purecov: end */
unknown's avatar
unknown committed
4828 4829 4830 4831 4832 4833
    }

    logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
                        opt_log ? log_output_options:LOG_NONE);
  }

4834
  /*
4835
    Set the default storage engine
4836
  */
4837 4838 4839 4840
  LEX_STRING name= { default_storage_engine, strlen(default_storage_engine) };
  plugin_ref plugin;
  handlerton *hton;
  if ((plugin= ha_resolve_by_name(0, &name)))
Sergei Golubchik's avatar
Sergei Golubchik committed
4841
    hton= plugin_hton(plugin);
4842
  else
4843
  {
4844 4845 4846 4847 4848 4849 4850
    sql_print_error("Unknown/unsupported storage engine: %s",
                    default_storage_engine);
    unireg_abort(1);
  }
  if (!ha_storage_engine_is_enabled(hton))
  {
    if (!opt_bootstrap)
4851
    {
4852 4853
      sql_print_error("Default storage engine (%s) is not available",
                      default_storage_engine);
4854 4855
      unireg_abort(1);
    }
4856 4857 4858 4859 4860 4861 4862 4863
    DBUG_ASSERT(global_system_variables.table_plugin);
  }
  else
  {
    /*
      Need to unlock as global_system_variables.table_plugin
      was acquired during plugin_init()
    */
Sergei Golubchik's avatar
Sergei Golubchik committed
4864
    mysql_mutex_lock(&LOCK_global_system_variables);
4865 4866
    plugin_unlock(0, global_system_variables.table_plugin);
    global_system_variables.table_plugin= plugin;
Sergei Golubchik's avatar
Sergei Golubchik committed
4867
    mysql_mutex_unlock(&LOCK_global_system_variables);
4868
  }
Sergei Golubchik's avatar
Sergei Golubchik committed
4869
#ifdef USE_ARIA_FOR_TMP_TABLES
4870
  if (!ha_storage_engine_is_enabled(maria_hton) && !opt_bootstrap)
4871
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
4872
    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");
4873 4874
    unireg_abort(1);
  }
4875 4876 4877 4878 4879
  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();
4880
#endif
4881

unknown's avatar
unknown committed
4882 4883 4884 4885
  tc_log= (total_ha_2pc > 1 ? (opt_bin_log  ?
                               (TC_LOG *) &mysql_bin_log :
                               (TC_LOG *) &tc_log_mmap) :
           (TC_LOG *) &tc_log_dummy);
unknown's avatar
unknown committed
4886

unknown's avatar
unknown committed
4887
  if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
unknown's avatar
Merge  
unknown committed
4888 4889 4890 4891 4892
  {
    sql_print_error("Can't init tc log");
    unireg_abort(1);
  }

unknown's avatar
unknown committed
4893 4894 4895 4896 4897
  if (ha_recover(0))
  {
    unireg_abort(1);
  }

unknown's avatar
Merge  
unknown committed
4898
  if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
4899
                                        WRITE_CACHE, max_binlog_size, 0, TRUE))
unknown's avatar
unknown committed
4900
    unireg_abort(1);
unknown's avatar
Merge  
unknown committed
4901 4902 4903

#ifdef HAVE_REPLICATION
  if (opt_bin_log && expire_logs_days)
4904
  {
4905
    time_t purge_time= server_start_time - expire_logs_days*24*60*60;
unknown's avatar
Merge  
unknown committed
4906 4907
    if (purge_time >= 0)
      mysql_bin_log.purge_logs_before_date(purge_time);
4908
  }
unknown's avatar
Merge  
unknown committed
4909 4910 4911 4912
#endif

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

unknown's avatar
unknown committed
4914
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
4915
  if (locked_in_memory && !getuid())
4916
  {
4917
    if (setreuid((uid_t)-1, 0) == -1)
4918
    {                        // this should never happen
4919
      sql_perror("setreuid");
4920 4921
      unireg_abort(1);
    }
4922 4923
    if (mlockall(MCL_CURRENT))
    {
4924
      if (global_system_variables.log_warnings)
4925
	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
unknown's avatar
unknown committed
4926
      locked_in_memory= 0;
4927
    }
4928 4929
    if (user_info)
      set_user(mysqld_user, user_info);
4930
  }
unknown's avatar
unknown committed
4931
  else
4932
#endif
unknown's avatar
unknown committed
4933
    locked_in_memory=0;
4934

4935
  ft_init_stopwords();
unknown's avatar
unknown committed
4936

unknown's avatar
unknown committed
4937
  init_max_user_conn();
4938
  init_update_queries();
4939 4940
  init_global_user_stats();
  init_global_client_stats();
4941 4942
  if (!opt_bootstrap)
    servers_init(0);
4943
  DBUG_RETURN(0);
unknown's avatar
unknown committed
4944
}
unknown's avatar
unknown committed
4945

4946

4947
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
4948

unknown's avatar
unknown committed
4949 4950 4951
static void create_shutdown_thread()
{
#ifdef __WIN__
4952 4953
  hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
  pthread_t hThread;
4954 4955 4956 4957 4958 4959
  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
4960

4961 4962
  // On "Stop Service" we have to do regular shutdown
  Service.SetShutdownEvent(hEventShutdown);
unknown's avatar
unknown committed
4963
#endif /* __WIN__ */
unknown's avatar
unknown committed
4964
}
unknown's avatar
unknown committed
4965

4966
#endif /* EMBEDDED_LIBRARY */
4967 4968


Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
4969
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
4970
static void handle_connections_methods()
unknown's avatar
unknown committed
4971
{
4972
  pthread_t hThread;
4973
  int error;
4974
  DBUG_ENTER("handle_connections_methods");
unknown's avatar
unknown committed
4975
  if (hPipe == INVALID_HANDLE_VALUE &&
4976 4977
      (!have_tcpip || opt_disable_networking) &&
      !opt_enable_shared_memory)
unknown's avatar
unknown committed
4978
  {
unknown's avatar
unknown committed
4979
    sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
4980
    unireg_abort(1);				// Will not return
unknown's avatar
unknown committed
4981
  }
4982

Marc Alff's avatar
Marc Alff committed
4983 4984
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
4985 4986
  handler_count=0;
  if (hPipe != INVALID_HANDLE_VALUE)
unknown's avatar
unknown committed
4987
  {
4988
    handler_count++;
4989 4990 4991
    if ((error= mysql_thread_create(key_thread_handle_con_namedpipes,
                                    &hThread, &connection_attrib,
                                    handle_connections_namedpipes, 0)))
unknown's avatar
unknown committed
4992
    {
4993 4994
      sql_print_warning("Can't create thread to handle named pipes"
                        " (errno= %d)", error);
4995 4996 4997 4998 4999 5000
      handler_count--;
    }
  }
  if (have_tcpip && !opt_disable_networking)
  {
    handler_count++;
5001 5002 5003
    if ((error= mysql_thread_create(key_thread_handle_con_sockets,
                                    &hThread, &connection_attrib,
                                    handle_connections_sockets_thread, 0)))
5004
    {
5005 5006
      sql_print_warning("Can't create thread to handle TCP/IP",
                        " (errno= %d)", error);
5007 5008 5009 5010 5011 5012 5013
      handler_count--;
    }
  }
#ifdef HAVE_SMEM
  if (opt_enable_shared_memory)
  {
    handler_count++;
5014 5015 5016
    if ((error= mysql_thread_create(key_thread_handle_con_sharedmem,
                                    &hThread, &connection_attrib,
                                    handle_connections_shared_memory, 0)))
5017
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
5018 5019
      sql_print_warning("Can't create thread to handle shared memory",
                        " (errno= %d)", error);
5020
      handler_count--;
unknown's avatar
unknown committed
5021 5022
    }
  }
5023
#endif
unknown's avatar
unknown committed
5024

5025
  while (handler_count > 0)
Marc Alff's avatar
Marc Alff committed
5026 5027
    mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
5028 5029
  DBUG_VOID_RETURN;
}
5030 5031 5032

void decrement_handler_count()
{
Marc Alff's avatar
Marc Alff committed
5033
  mysql_mutex_lock(&LOCK_thread_count);
5034
  handler_count--;
Marc Alff's avatar
Marc Alff committed
5035 5036
  mysql_cond_signal(&COND_handler_count);
  mysql_mutex_unlock(&LOCK_thread_count);
5037
  my_thread_end();
5038 5039 5040
}
#else
#define decrement_handler_count()
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
5041
#endif /* defined(_WIN32) || defined(HAVE_SMEM) */
5042 5043


5044
#ifndef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070

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
5071
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
5072
    var++;
unknown's avatar
unknown committed
5073
  }
unknown's avatar
unknown committed
5074

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

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

5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117
#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

5118

unknown's avatar
unknown committed
5119 5120 5121
#ifdef __WIN__
int win_main(int argc, char **argv)
#else
5122
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5123 5124
#endif
{
Marc Alff's avatar
Marc Alff committed
5125 5126 5127 5128 5129
  /*
    Perform basic thread library and malloc initialization,
    to be able to read defaults files and parse options.
  */
  my_progname= argv[0];
5130
  sf_leaking_memory= 1; // no safemalloc memory leak reports if we exit early
5131 5132
  mysqld_server_started= mysqld_server_initialized= 0;

5133 5134 5135
#ifdef HAVE_NPTL
  ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
#endif
5136 5137 5138
#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
5139
  {
5140
    fprintf(stderr, "my_init() failed.");
Marc Alff's avatar
Marc Alff committed
5141 5142
    return 1;
  }
5143
#endif
Marc Alff's avatar
Marc Alff committed
5144 5145 5146

  orig_argc= argc;
  orig_argv= argv;
5147
  my_getopt_use_args_separator= TRUE;
Marc Alff's avatar
Marc Alff committed
5148 5149
  if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
    return 1;
5150
  my_getopt_use_args_separator= FALSE;
Marc Alff's avatar
Marc Alff committed
5151 5152 5153 5154 5155 5156 5157 5158
  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;

5159
  init_sql_statement_names();
Marc Alff's avatar
Marc Alff committed
5160 5161
  sys_var_init();

5162
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5163
  /*
5164
    Initialize the array of performance schema instrument configurations.
Marc Alff's avatar
Marc Alff committed
5165
  */
5166 5167
  init_pfs_instrument_array();
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
Marc Alff's avatar
Marc Alff committed
5168 5169 5170 5171 5172 5173
  /*
    Logs generated while parsing the command line
    options are buffered and printed later.
  */
  buffered_logs.init();
  my_getopt_error_reporter= buffered_option_error_reporter;
5174
  my_charset_error_reporter= buffered_option_error_reporter;
5175
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5176
  pfs_param.m_pfs_instrument= const_cast<char*>("");
5177
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5178

5179
  int ho_error __attribute__((unused))= handle_early_options();
Marc Alff's avatar
Marc Alff committed
5180

5181
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
Marc Alff's avatar
Marc Alff committed
5182 5183
  if (ho_error == 0)
  {
5184
    if (pfs_param.m_enabled  && !opt_help && !opt_bootstrap)
Marc Alff's avatar
Marc Alff committed
5185
    {
5186
      /* Add sizing hints from the server sizing parameters. */
5187 5188
      pfs_param.m_hints.m_table_definition_cache= tdc_size;
      pfs_param.m_hints.m_table_open_cache= tc_size;
5189 5190
      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
5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218
      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)
  {
5219 5220 5221 5222
    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
5223

5224 5225 5226 5227 5228 5229 5230
      /*
        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 */
5231 5232
      PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_main, NULL, 0);
      PSI_THREAD_CALL(set_thread)(psi);
5233 5234 5235 5236 5237 5238 5239 5240

      /*
        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
5241 5242 5243 5244
  }
#endif /* HAVE_PSI_INTERFACE */

  init_error_log_mutex();
5245

5246 5247 5248
  /* Initialize audit interface globals. Audit plugins are inited later. */
  mysql_audit_initialize();

5249 5250 5251 5252 5253 5254
  /*
    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
5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276
#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
5277
#ifdef _CUSTOMSTARTUPCONFIG_
unknown's avatar
unknown committed
5278 5279 5280
  if (_cust_check_startup())
  {
    / * _cust_check_startup will report startup failure error * /
unknown's avatar
Merge  
unknown committed
5281
    exit(1);
unknown's avatar
unknown committed
5282 5283
  }
#endif
unknown's avatar
unknown committed
5284

Marc Alff's avatar
Marc Alff committed
5285
  if (init_common_variables())
5286
    unireg_abort(1);				// Will do exit
unknown's avatar
unknown committed
5287 5288

  init_signals();
5289 5290 5291

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

5293
  (void) thr_setconcurrency(concurrency);	// 10 by default
unknown's avatar
unknown committed
5294

5295 5296
  select_thread=pthread_self();
  select_thread_in_use=1;
unknown's avatar
unknown committed
5297 5298 5299 5300 5301 5302

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

5303 5304
#ifndef DBUG_OFF
  test_lc_time_sz();
5305
  srand((uint) time(NULL)); 
5306 5307
#endif

unknown's avatar
unknown committed
5308 5309 5310
  /*
    We have enough space for fiddling with the argv, continue
  */
unknown's avatar
unknown committed
5311
  check_data_home(mysql_real_data_home);
5312
  if (my_setwd(mysql_real_data_home, opt_abort ? 0 : MYF(MY_WME)) && !opt_abort)
unknown's avatar
unknown committed
5313
    unireg_abort(1);				/* purecov: inspected */
unknown's avatar
unknown committed
5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324

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

5325
  if (opt_bin_log && !global_system_variables.server_id)
unknown's avatar
unknown committed
5326
  {
5327
    global_system_variables.server_id= ::server_id= 1;
unknown's avatar
unknown committed
5328
#ifdef EXTRA_DEBUG
5329 5330 5331 5332
    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.");
5333
#endif
unknown's avatar
unknown committed
5334 5335
  }

5336 5337 5338 5339 5340 5341 5342 5343
  /* 
   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
5344
  if (init_server_components())
unknown's avatar
unknown committed
5345
    unireg_abort(1);
unknown's avatar
unknown committed
5346

5347
  init_ssl();
unknown's avatar
unknown committed
5348 5349
  network_init();

unknown's avatar
unknown committed
5350 5351 5352
#ifdef __WIN__
  if (!opt_console)
  {
5353 5354
    if (reopen_fstreams(log_error_file, stdout, stderr))
      unireg_abort(1);
5355
    setbuf(stderr, NULL);
unknown's avatar
unknown committed
5356
    FreeConsole();				// Remove window
5357
  }
unknown's avatar
unknown committed
5358 5359 5360 5361 5362 5363 5364
#endif

  /*
    init signals & alarm
    After this we can't quit by a simple unireg_abort
  */
  start_signal_handler();				// Creates pidfile
5365

5366
  if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
5367
      my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
unknown's avatar
unknown committed
5368 5369 5370
  {
    abort_loop=1;
    select_thread_in_use=0;
5371

unknown's avatar
unknown committed
5372
    (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
5373

5374
    delete_pid_file(MYF(MY_WME));
5375

5376
    if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
5377
      unlink(mysqld_unix_port);
unknown's avatar
unknown committed
5378 5379
    exit(1);
  }
5380

unknown's avatar
unknown committed
5381
  if (!opt_noacl)
5382
    (void) grant_init();
unknown's avatar
unknown committed
5383 5384

  if (!opt_noacl)
5385 5386
  {
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
5387 5388
    udf_init();
#endif
5389
  }
5390

5391
  init_status_vars();
unknown's avatar
unknown committed
5392 5393
  if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
    opt_skip_slave_start= 1;
5394 5395

  binlog_unsafe_map_init();
5396

Marc Alff's avatar
Marc Alff committed
5397 5398
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  initialize_performance_schema_acl(opt_bootstrap);
5399 5400 5401 5402 5403 5404 5405 5406
  /*
    Do not check the structure of the performance schema tables
    during bootstrap:
    - the tables are not supposed to exist yet, bootstrap will create them
    - a check would print spurious error messages
  */
  if (! opt_bootstrap)
    check_performance_schema();
Marc Alff's avatar
Marc Alff committed
5407 5408 5409 5410
#endif

  initialize_information_schema_acl();

5411 5412 5413 5414 5415
  execute_ddl_log_recovery();

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

unknown's avatar
unknown committed
5416 5417
  if (opt_bootstrap)
  {
5418
    select_thread_in_use= 0;                    // Allow 'kill' to work
Marc Alff's avatar
Marc Alff committed
5419
    bootstrap(mysql_stdin);
5420 5421 5422 5423 5424 5425 5426
    if (!kill_in_progress)
      unireg_abort(bootstrap_error ? 1 : 0);
    else
    {
      sleep(2);                                 // Wait for kill
      exit(0);
    }
unknown's avatar
unknown committed
5427
  }
5428

5429 5430 5431
  /* It's now safe to use thread specific memory */
  mysqld_server_initialized= 1;

5432 5433 5434
  create_shutdown_thread();
  start_handle_manager();

5435 5436 5437
  /* Copy default global rpl_filter to global_rpl_filter */
  copy_filter_setting(global_rpl_filter, get_or_create_rpl_filter("", 0));

5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448
  /*
    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);
  }

5449
  if (opt_init_file && *opt_init_file)
unknown's avatar
unknown committed
5450 5451 5452 5453
  {
    if (read_init_file(opt_init_file))
      unireg_abort(1);
  }
unknown's avatar
unknown committed
5454

5455
  sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version,
5456 5457
                        ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ?
                         (char*) "" : mysqld_unix_port),
unknown's avatar
unknown committed
5458
                         mysqld_port,
unknown's avatar
Merge  
unknown committed
5459
                         MYSQL_COMPILATION_COMMENT);
5460 5461 5462
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetRunning();
#endif
unknown's avatar
unknown committed
5463

unknown's avatar
unknown committed
5464
  /* Signal threads waiting for server to be started */
Marc Alff's avatar
Marc Alff committed
5465
  mysql_mutex_lock(&LOCK_server_started);
unknown's avatar
unknown committed
5466
  mysqld_server_started= 1;
Marc Alff's avatar
Marc Alff committed
5467 5468
  mysql_cond_signal(&COND_server_started);
  mysql_mutex_unlock(&LOCK_server_started);
unknown's avatar
unknown committed
5469

5470
#if defined(_WIN32) || defined(HAVE_SMEM)
5471
  handle_connections_methods();
unknown's avatar
unknown committed
5472
#else
5473 5474
  handle_connections_sockets();
#endif /* _WIN32 || HAVE_SMEM */
unknown's avatar
unknown committed
5475 5476

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

unknown's avatar
unknown committed
5478 5479 5480
  DBUG_PRINT("quit",("Exiting main thread"));

#ifndef __WIN__
unknown's avatar
unknown committed
5481
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
5482 5483
  sql_print_error("Before Lock_thread_count");
#endif
Marc Alff's avatar
Marc Alff committed
5484
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
5485
  DBUG_PRINT("quit", ("Got thread_count mutex"));
unknown's avatar
unknown committed
5486
  select_thread_in_use=0;			// For close_connections
Marc Alff's avatar
Marc Alff committed
5487 5488
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
5489
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
5490 5491
  sql_print_error("After lock_thread_count");
#endif
unknown's avatar
merge  
unknown committed
5492
#endif /* __WIN__ */
5493

5494
#ifdef HAVE_PSI_THREAD_INTERFACE
5495 5496 5497 5498
  /*
    Disable the main thread instrumentation,
    to avoid recording events during the shutdown.
  */
5499
  PSI_THREAD_CALL(delete_current_thread)();
5500 5501
#endif

unknown's avatar
unknown committed
5502
  /* Wait until cleanup is done */
Marc Alff's avatar
Marc Alff committed
5503
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
5504
  while (!ready_to_exit)
Marc Alff's avatar
Marc Alff committed
5505 5506
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
merge  
unknown committed
5507 5508

#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
merge  
unknown committed
5509 5510 5511 5512
  if (Service.IsNT() && start_mode)
    Service.Stop();
  else
  {
unknown's avatar
unknown committed
5513
    Service.SetShutdownEvent(0);
unknown's avatar
merge  
unknown committed
5514 5515 5516
    if (hEventShutdown)
      CloseHandle(hEventShutdown);
  }
unknown's avatar
unknown committed
5517
#endif
5518
  mysqld_exit(0);
5519
  return 0;
unknown's avatar
unknown committed
5520 5521
}

5522
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
5523

unknown's avatar
SCRUM  
unknown committed
5524

5525 5526 5527 5528 5529
/****************************************************************************
  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
5530
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
5531 5532
int mysql_service(void *p)
{
5533 5534 5535
  if (my_thread_init())
    return 1;
  
5536 5537 5538 5539
  if (use_opt_args)
    win_main(opt_argc, opt_argv);
  else
    win_main(Service.my_argc, Service.my_argv);
5540 5541

  my_thread_end();
unknown's avatar
unknown committed
5542 5543 5544
  return 0;
}

5545 5546 5547 5548 5549 5550 5551 5552

/* 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
5553 5554
    return strmake(to, from, length-1);
  return strxnmov(to, length-1, "\"", from, "\"", NullS);
5555 5556 5557
}


unknown's avatar
unknown committed
5558 5559
/**
  Handle basic handling of services, like installation and removal.
5560

unknown's avatar
unknown committed
5561 5562 5563 5564 5565 5566
  @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

5567 5568
  @retval 0	option handled
  @retval 1	Could not handle option
unknown's avatar
unknown committed
5569
*/
5570

5571 5572 5573 5574 5575
static bool
default_service_handling(char **argv,
			 const char *servicename,
			 const char *displayname,
			 const char *file_path,
unknown's avatar
Merge  
unknown committed
5576 5577
			 const char *extra_opt,
			 const char *account_name)
5578
{
5579
  char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
5580
  const char *opt_delim;
5581
  end= path_and_service + sizeof(path_and_service)-3;
5582 5583 5584 5585 5586

  /* We have to quote filename if it contains spaces */
  pos= add_quoted_string(path_and_service, file_path, end);
  if (*extra_opt)
  {
5587 5588 5589 5590 5591
    /* 
     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.  
    */
5592
    *pos++= ' ';
5593 5594 5595
    if (opt_delim= strchr(extra_opt, '='))
    {
      size_t length= ++opt_delim - extra_opt;
5596
      pos= strnmov(pos, extra_opt, length);
5597 5598 5599 5600 5601
    }
    else
      opt_delim= extra_opt;
    
    pos= add_quoted_string(pos, opt_delim, end);
5602
  }
5603 5604
  /* We must have servicename last */
  *pos++= ' ';
unknown's avatar
unknown committed
5605
  (void) add_quoted_string(pos, servicename, end);
5606

5607 5608
  if (Service.got_service_option(argv, "install"))
  {
unknown's avatar
Merge  
unknown committed
5609 5610
    Service.Install(1, servicename, displayname, path_and_service,
                    account_name);
5611 5612 5613 5614
    return 0;
  }
  if (Service.got_service_option(argv, "install-manual"))
  {
unknown's avatar
Merge  
unknown committed
5615 5616
    Service.Install(0, servicename, displayname, path_and_service,
                    account_name);
5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627
    return 0;
  }
  if (Service.got_service_option(argv, "remove"))
  {
    Service.Remove(servicename);
    return 0;
  }
  return 1;
}


5628
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5629
{
5630 5631
  my_progname= argv[0];

unknown's avatar
unknown committed
5632 5633 5634 5635
  /*
    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
5636
  */
5637
  int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
unknown's avatar
Merge  
unknown committed
5638 5639
                                                  "MySQLShutdown"), 10);

5640 5641 5642
  /* Must be initialized early for comparison of service name */
  system_charset_info= &my_charset_utf8_general_ci;

5643 5644 5645 5646 5647 5648
  if (my_init())
  {
    fprintf(stderr, "my_init() failed.");
    return 1;
  }

unknown's avatar
unknown committed
5649
  if (Service.GetOS())	/* true NT family */
unknown's avatar
unknown committed
5650
  {
unknown's avatar
unknown committed
5651
    char file_path[FN_REFLEN];
5652
    my_path(file_path, argv[0], "");		      /* Find name in path */
unknown's avatar
unknown committed
5653 5654
    fn_format(file_path,argv[0],file_path,"",
	      MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
unknown's avatar
unknown committed
5655

unknown's avatar
unknown committed
5656
    if (argc == 2)
5657
    {
5658
      if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
unknown's avatar
Merge  
unknown committed
5659
				   file_path, "", NULL))
5660
	return 0;
unknown's avatar
unknown committed
5661
      if (Service.IsService(argv[1]))        /* Start an optional service */
unknown's avatar
unknown committed
5662
      {
unknown's avatar
unknown committed
5663 5664 5665 5666 5667 5668
	/*
	  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.
	*/
5669
	if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
5670
	  load_default_groups[load_default_groups_sz-2]= argv[1];
unknown's avatar
unknown committed
5671
        start_mode= 1;
5672
        Service.Init(argv[1], mysql_service);
unknown's avatar
unknown committed
5673 5674 5675 5676
        return 0;
      }
    }
    else if (argc == 3) /* install or remove any optional service */
unknown's avatar
unknown committed
5677
    {
unknown's avatar
Merge  
unknown committed
5678 5679
      if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
                                    NULL))
5680 5681
	return 0;
      if (Service.IsService(argv[2]))
unknown's avatar
unknown committed
5682
      {
5683 5684 5685 5686
	/*
	  mysqld was started as
	  mysqld --defaults-file=my_path\my.ini service-name
	*/
5687
	use_opt_args=1;
5688
	opt_argc= 2;				// Skip service-name
5689 5690
	opt_argv=argv;
	start_mode= 1;
5691
	if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
5692
	  load_default_groups[load_default_groups_sz-2]= argv[2];
5693
	Service.Init(argv[2], mysql_service);
5694
	return 0;
unknown's avatar
unknown committed
5695 5696
      }
    }
unknown's avatar
Merge  
unknown committed
5697
    else if (argc == 4 || argc == 5)
5698 5699
    {
      /*
unknown's avatar
Merge  
unknown committed
5700 5701 5702 5703 5704
        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.)
5705
      */
unknown's avatar
Merge  
unknown committed
5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720
      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;
5721
    }
unknown's avatar
unknown committed
5722
    else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
unknown's avatar
unknown committed
5723
    {
unknown's avatar
unknown committed
5724 5725 5726
      /* start the default service */
      start_mode= 1;
      Service.Init(MYSQL_SERVICENAME, mysql_service);
unknown's avatar
unknown committed
5727 5728 5729
      return 0;
    }
  }
unknown's avatar
unknown committed
5730
  /* Start as standalone server */
unknown's avatar
unknown committed
5731 5732 5733 5734 5735 5736 5737 5738
  Service.my_argc=argc;
  Service.my_argv=argv;
  mysql_service(NULL);
  return 0;
}
#endif


unknown's avatar
unknown committed
5739
/**
5740 5741 5742
  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.
*/
5743

Marc Alff's avatar
Marc Alff committed
5744
static void bootstrap(MYSQL_FILE *file)
unknown's avatar
unknown committed
5745
{
5746
  DBUG_ENTER("bootstrap");
5747

5748
  THD *thd= new THD;
unknown's avatar
unknown committed
5749
  thd->bootstrap=1;
5750
  my_net_init(&thd->net,(st_vio*) 0, MYF(0));
unknown's avatar
unknown committed
5751
  thd->max_client_packet_length= thd->net.max_packet;
5752
  thd->security_ctx->master_access= ~(ulong)0;
unknown's avatar
unknown committed
5753
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
Michael Widenius's avatar
Michael Widenius committed
5754
  thread_count++;                        // Safe as only one thread running
5755
  in_bootstrap= TRUE;
5756 5757

  bootstrap_file=file;
unknown's avatar
unknown committed
5758
#ifndef EMBEDDED_LIBRARY			// TODO:  Enable this
5759 5760 5761 5762 5763
  int error;
  if ((error= mysql_thread_create(key_thread_bootstrap,
                                  &thd->real_id, &connection_attrib,
                                  handle_bootstrap,
                                  (void*) thd)))
5764
  {
5765 5766
    sql_print_warning("Can't create thread to handle bootstrap (errno= %d)",
                      error);
unknown's avatar
Merge  
unknown committed
5767 5768
    bootstrap_error=-1;
    DBUG_VOID_RETURN;
5769 5770
  }
  /* Wait for thread to die */
Marc Alff's avatar
Marc Alff committed
5771
  mysql_mutex_lock(&LOCK_thread_count);
5772
  while (in_bootstrap)
5773
  {
Marc Alff's avatar
Marc Alff committed
5774
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
5775 5776
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
5777
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
5778 5779
#else
  thd->mysql= 0;
Marc Alff's avatar
Marc Alff committed
5780
  do_handle_bootstrap(thd);
unknown's avatar
unknown committed
5781 5782
#endif

unknown's avatar
Merge  
unknown committed
5783
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
5784 5785
}

5786

unknown's avatar
unknown committed
5787 5788
static bool read_init_file(char *file_name)
{
Marc Alff's avatar
Marc Alff committed
5789
  MYSQL_FILE *file;
unknown's avatar
unknown committed
5790 5791
  DBUG_ENTER("read_init_file");
  DBUG_PRINT("enter",("name: %s",file_name));
Marc Alff's avatar
Marc Alff committed
5792 5793
  if (!(file= mysql_file_fopen(key_file_init, file_name,
                               O_RDONLY, MYF(MY_WME))))
5794
    DBUG_RETURN(TRUE);
unknown's avatar
Merge  
unknown committed
5795
  bootstrap(file);
Marc Alff's avatar
Marc Alff committed
5796
  mysql_file_fclose(file, MYF(MY_WME));
5797
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
5798 5799 5800
}


Mikael Ronström's avatar
Mikael Ronström committed
5801 5802 5803 5804 5805 5806 5807 5808
/**
  Increment number of created threads
*/
void inc_thread_created(void)
{
  thread_created++;
}

5809
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
5810 5811 5812 5813 5814 5815 5816 5817 5818 5819

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

unknown's avatar
unknown committed
5821 5822
void handle_connection_in_main_thread(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
5823
  mysql_mutex_assert_owner(&LOCK_thread_count);
unknown's avatar
unknown committed
5824 5825
  thread_cache_size=0;			// Safety
  threads.append(thd);
Marc Alff's avatar
Marc Alff committed
5826
  mysql_mutex_unlock(&LOCK_thread_count);
5827
  thd->start_utime= microsecond_interval_timer();
Marc Alff's avatar
Marc Alff committed
5828
  do_handle_one_connection(thd);
unknown's avatar
unknown committed
5829 5830 5831 5832 5833 5834 5835 5836 5837
}


/*
  Scheduler that uses one thread per connection
*/

void create_thread_to_handle_connection(THD *thd)
{
Michael Widenius's avatar
Michael Widenius committed
5838 5839 5840 5841
  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
5842 5843
  if (cached_thread_count > wake_thread)
  {
Michael Widenius's avatar
Michael Widenius committed
5844 5845 5846
    mysql_mutex_lock(&LOCK_thread_cache);
    /* Recheck condition when we have the lock */
    if (cached_thread_count > wake_thread)
unknown's avatar
unknown committed
5847
    {
Marc Alff's avatar
Marc Alff committed
5848
      mysql_mutex_unlock(&LOCK_thread_count);
Michael Widenius's avatar
Michael Widenius committed
5849 5850 5851 5852 5853 5854 5855 5856 5857 5858
      /* 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);
  }
5859

Michael Widenius's avatar
Michael Widenius committed
5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877
  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);
5878

Michael Widenius's avatar
Michael Widenius committed
5879 5880 5881
    mysql_mutex_lock(&LOCK_connection_count);
    (*thd->scheduler->connection_count)--;
    mysql_mutex_unlock(&LOCK_connection_count);
5882

Michael Widenius's avatar
Michael Widenius committed
5883
    statistic_increment(aborted_connects,&LOCK_status);
Sergei Golubchik's avatar
Sergei Golubchik committed
5884
    statistic_increment(connection_errors_internal, &LOCK_status);
Michael Widenius's avatar
Michael Widenius committed
5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897
    /* 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
5898
  }
Marc Alff's avatar
Marc Alff committed
5899
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
5900
  DBUG_PRINT("info",("Thread created"));
Michael Widenius's avatar
Michael Widenius committed
5901
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
5902 5903 5904
}


unknown's avatar
unknown committed
5905
/**
5906 5907 5908 5909 5910 5911
  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
5912
    In single-threaded mode (\#define ONE_THREAD) connection will be
5913 5914
    handled inside this function.

unknown's avatar
unknown committed
5915
  @param[in,out] thd    Thread handle of future thread.
5916 5917
*/

unknown's avatar
unknown committed
5918 5919 5920 5921
static void create_new_thread(THD *thd)
{
  DBUG_ENTER("create_new_thread");

5922 5923 5924 5925 5926
  /*
    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
5927
  mysql_mutex_lock(&LOCK_connection_count);
5928

5929 5930
  if (*thd->scheduler->connection_count >=
      *thd->scheduler->max_connections + 1|| abort_loop)
unknown's avatar
unknown committed
5931
  {
Marc Alff's avatar
Marc Alff committed
5932
    mysql_mutex_unlock(&LOCK_connection_count);
5933

unknown's avatar
unknown committed
5934
    DBUG_PRINT("error",("Too many connections"));
5935
    close_connection(thd, ER_CON_COUNT_ERROR);
5936
    statistic_increment(denied_connections, &LOCK_status);
unknown's avatar
unknown committed
5937
    delete thd;
unknown's avatar
unknown committed
5938
    statistic_increment(connection_errors_max_connection, &LOCK_status);
unknown's avatar
unknown committed
5939 5940
    DBUG_VOID_RETURN;
  }
5941

5942
  ++*thd->scheduler->connection_count;
5943

5944 5945
  if (connection_count + extra_connection_count > max_used_connections)
    max_used_connections= connection_count + extra_connection_count;
5946

Marc Alff's avatar
Marc Alff committed
5947
  mysql_mutex_unlock(&LOCK_connection_count);
5948

Michael Widenius's avatar
Michael Widenius committed
5949
  thread_safe_increment32(&thread_count, &thread_count_lock);
5950

Michael Widenius's avatar
Michael Widenius committed
5951
  /* Start a new thread to handle connection. */
Marc Alff's avatar
Marc Alff committed
5952
  mysql_mutex_lock(&LOCK_thread_count);
5953 5954 5955 5956 5957
  /*
    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
5958
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
unknown's avatar
unknown committed
5959

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

unknown's avatar
unknown committed
5962 5963
  DBUG_VOID_RETURN;
}
5964 5965
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
5966

unknown's avatar
unknown committed
5967 5968 5969 5970
#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
{
  /* hack to get around signals ignored in syscalls for problem OS's */
5971 5972 5973
  if (mysql_socket_getfd(unix_sock) == INVALID_SOCKET ||
      (!opt_disable_networking &&
       mysql_socket_getfd(base_ip_sock) == INVALID_SOCKET))
unknown's avatar
unknown committed
5974 5975
  {
    select_thread_in_use = 0;
unknown's avatar
unknown committed
5976
    /* The following call will never return */
5977
    DBUG_PRINT("general", ("killing server because socket is closed"));
5978
    kill_server((void*) MYSQL_KILL_SIGNAL);
unknown's avatar
unknown committed
5979 5980 5981 5982 5983 5984
  }
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
#else
#define MAYBE_BROKEN_SYSCALL
#endif
unknown's avatar
unknown committed
5985 5986 5987

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

5988
#ifndef EMBEDDED_LIBRARY
5989

5990
void handle_connections_sockets()
unknown's avatar
unknown committed
5991
{
5992 5993
  MYSQL_SOCKET sock= mysql_socket_invalid();
  MYSQL_SOCKET new_sock= mysql_socket_invalid();
unknown's avatar
unknown committed
5994 5995
  uint error_count=0;
  THD *thd;
5996
  struct sockaddr_storage cAddr;
Michael Widenius's avatar
Michael Widenius committed
5997 5998 5999 6000
  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
6001
  st_vio *vio_tmp;
6002
  bool is_unix_sock;
6003 6004
#ifdef HAVE_POLL
  int socket_count= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
6005
  struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock
6006
  MYSQL_SOCKET  pfs_fds[3]; // for performance schema
Sergei Golubchik's avatar
Sergei Golubchik committed
6007
#define setup_fds(X)                    \
Sergei Golubchik's avatar
Sergei Golubchik committed
6008
    mysql_socket_set_thread_owner(X);             \
6009 6010
    pfs_fds[socket_count]= (X);                   \
    fds[socket_count].fd= mysql_socket_getfd(X);  \
Sergei Golubchik's avatar
Sergei Golubchik committed
6011 6012
    fds[socket_count].events= POLLIN;   \
    socket_count++
6013
#else
6014
#define setup_fds(X)    FD_SET(mysql_socket_getfd(X),&clientFDs)
6015
  fd_set readFDs,clientFDs;
Sergei Golubchik's avatar
Sergei Golubchik committed
6016
  FD_ZERO(&clientFDs);
6017 6018
#endif

unknown's avatar
unknown committed
6019 6020
  DBUG_ENTER("handle_connections_sockets");

6021
  if (mysql_socket_getfd(base_ip_sock) != INVALID_SOCKET)
unknown's avatar
unknown committed
6022
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6023
    setup_fds(base_ip_sock);
6024
    ip_flags = fcntl(mysql_socket_getfd(base_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6025
  }
6026
  if (mysql_socket_getfd(extra_ip_sock) != INVALID_SOCKET)
6027
  {
Sergei Golubchik's avatar
Sergei Golubchik committed
6028
    setup_fds(extra_ip_sock);
6029
    extra_ip_flags = fcntl(mysql_socket_getfd(extra_ip_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6030 6031
  }
#ifdef HAVE_SYS_UN_H
Sergei Golubchik's avatar
Sergei Golubchik committed
6032
  setup_fds(unix_sock);
6033
  socket_flags=fcntl(mysql_socket_getfd(unix_sock), F_GETFL, 0);
unknown's avatar
unknown committed
6034 6035 6036
#endif

  DBUG_PRINT("general",("Waiting for connections."));
unknown's avatar
unknown committed
6037
  MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6038 6039
  while (!abort_loop)
  {
6040 6041
#ifdef HAVE_POLL
    retval= poll(fds, socket_count, -1);
unknown's avatar
unknown committed
6042
#else
6043
    readFDs=clientFDs;
6044
    retval= select((int) 0,&readFDs,0,0,0);
6045 6046 6047
#endif

    if (retval < 0)
unknown's avatar
unknown committed
6048
    {
unknown's avatar
unknown committed
6049
      if (socket_errno != SOCKET_EINTR)
unknown's avatar
unknown committed
6050
      {
unknown's avatar
unknown committed
6051 6052 6053 6054 6055 6056
        /*
          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
6057
	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
unknown's avatar
unknown committed
6058
	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
unknown's avatar
unknown committed
6059
      }
unknown's avatar
unknown committed
6060
      MAYBE_BROKEN_SYSCALL
unknown's avatar
unknown committed
6061 6062
      continue;
    }
6063

unknown's avatar
unknown committed
6064
    if (abort_loop)
unknown's avatar
unknown committed
6065 6066
    {
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6067
      break;
unknown's avatar
unknown committed
6068
    }
unknown's avatar
unknown committed
6069

6070
    /* Is this a new connection request ? */
6071 6072 6073 6074 6075
#ifdef HAVE_POLL
    for (int i= 0; i < socket_count; ++i) 
    {
      if (fds[i].revents & POLLIN)
      {
6076 6077
        sock= pfs_fds[i];
        flags= fcntl(mysql_socket_getfd(sock), F_GETFL, 0);
6078 6079 6080 6081
        break;
      }
    }
#else  // HAVE_POLL
6082
    if (FD_ISSET(mysql_socket_getfd(base_ip_sock),&readFDs))
unknown's avatar
unknown committed
6083
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6084 6085
      sock=  base_ip_sock;
      flags= ip_flags;
unknown's avatar
unknown committed
6086 6087
    }
    else
6088
    if (FD_ISSET(mysql_socket_getfd(extra_ip_sock),&readFDs))
unknown's avatar
unknown committed
6089
    {
Sergei Golubchik's avatar
Sergei Golubchik committed
6090 6091 6092 6093 6094 6095 6096
      sock=  extra_ip_sock;
      flags= extra_ip_flags;
    }
    else
    {
      sock = unix_sock;
      flags= socket_flags;
unknown's avatar
unknown committed
6097
    }
6098
#endif // HAVE_POLL
unknown's avatar
unknown committed
6099 6100 6101 6102 6103

#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
    {
#if defined(O_NONBLOCK)
6104
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NONBLOCK);
unknown's avatar
unknown committed
6105
#elif defined(O_NDELAY)
6106
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NDELAY);
unknown's avatar
unknown committed
6107 6108 6109 6110 6111
#endif
    }
#endif /* NO_FCNTL_NONBLOCK */
    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
    {
6112
      size_socket length= sizeof(struct sockaddr_storage);
6113 6114 6115 6116
      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
6117
	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
unknown's avatar
unknown committed
6118
	break;
unknown's avatar
unknown committed
6119
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6120 6121 6122 6123
#if !defined(NO_FCNTL_NONBLOCK)
      if (!(test_flags & TEST_BLOCKING))
      {
	if (retry == MAX_ACCEPT_RETRY - 1)
6124 6125 6126 6127
        {
          // Try without O_NONBLOCK
	  fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
        }
unknown's avatar
unknown committed
6128 6129 6130 6131 6132
      }
#endif
    }
#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
6133
      fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
unknown's avatar
unknown committed
6134
#endif
6135
    if (mysql_socket_getfd(new_sock) == INVALID_SOCKET)
unknown's avatar
unknown committed
6136
    {
unknown's avatar
unknown committed
6137 6138 6139 6140 6141 6142
      /*
        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
6143 6144
      if ((error_count++ & 255) == 0)		// This can happen often
	sql_perror("Error in accept");
unknown's avatar
unknown committed
6145
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
6146
      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
unknown's avatar
unknown committed
6147 6148 6149 6150 6151 6152
	sleep(1);				// Give other threads some time
      continue;
    }

#ifdef HAVE_LIBWRAP
    {
6153 6154
      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
6155 6156 6157
      {
	struct request_info req;
	signal(SIGCHLD, SIG_DFL);
6158 6159
	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE,
                     mysql_socket_getfd(new_sock), NULL);
6160 6161
	my_fromhost(&req);
	if (!my_hosts_access(&req))
unknown's avatar
unknown committed
6162
	{
unknown's avatar
unknown committed
6163 6164 6165 6166 6167
	  /*
	    This may be stupid but refuse() includes an exit(0)
	    which we surely don't want...
	    clean_exit() - same stupid thing ...
	  */
6168
	  syslog(deny_severity, "refused connect from %s",
6169
		 my_eval_client(&req));
unknown's avatar
unknown committed
6170

unknown's avatar
unknown committed
6171 6172 6173 6174 6175 6176
	  /*
	    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
6177 6178 6179
	  if (req.sink)
	    ((void (*)(int))req.sink)(req.fd);

6180
	  (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6181
	  (void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6182 6183 6184 6185 6186
          /*
            The connection was refused by TCP wrappers.
            There are no details (by client IP) available to update the host_cache.
          */
          statistic_increment(connection_tcpwrap_errors, &LOCK_status);
unknown's avatar
unknown committed
6187 6188 6189 6190 6191 6192 6193 6194 6195 6196
	  continue;
	}
      }
    }
#endif /* HAVE_LIBWRAP */

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

6197
    DBUG_PRINT("info", ("Creating THD for new connection"));
unknown's avatar
unknown committed
6198 6199
    if (!(thd= new THD))
    {
6200
      (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6201
      (void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6202
      statistic_increment(connection_errors_internal, &LOCK_status);
unknown's avatar
unknown committed
6203 6204
      continue;
    }
6205 6206
    /* Set to get io buffers to be part of THD */
    set_current_thd(thd);
Sergei Golubchik's avatar
Sergei Golubchik committed
6207

6208 6209 6210 6211 6212 6213 6214
    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)) ||
6215
	my_net_init(&thd->net, vio_tmp, MYF(MY_THREAD_SPECIFIC)))
unknown's avatar
unknown committed
6216
    {
6217 6218 6219 6220 6221 6222 6223
      /*
        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
6224 6225
      else
      {
6226
	(void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
6227
	(void) mysql_socket_close(new_sock);
unknown's avatar
unknown committed
6228 6229
      }
      delete thd;
6230
      set_current_thd(0);
unknown's avatar
unknown committed
6231
      statistic_increment(connection_errors_internal, &LOCK_status);
unknown's avatar
unknown committed
6232 6233
      continue;
    }
Sergei Golubchik's avatar
Sergei Golubchik committed
6234 6235

    init_net_server_extension(thd);
6236
    if (is_unix_sock)
6237
      thd->security_ctx->host=(char*) my_localhost;
6238

6239
    if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock))
6240 6241
    {
      thd->extra_port= 1;
Sergei Golubchik's avatar
Sergei Golubchik committed
6242
      thd->scheduler= extra_thread_scheduler;
6243
    }
unknown's avatar
unknown committed
6244
    create_new_thread(thd);
6245
    set_current_thd(0);
unknown's avatar
unknown committed
6246
  }
6247 6248 6249
  DBUG_VOID_RETURN;
}

unknown's avatar
unknown committed
6250

6251 6252 6253 6254 6255
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg)
{
  my_thread_init();
  handle_connections_sockets();
6256
  decrement_handler_count();
6257
  return 0;
unknown's avatar
unknown committed
6258 6259
}

6260
pthread_handler_t handle_connections_namedpipes(void *arg)
unknown's avatar
unknown committed
6261 6262
{
  HANDLE hConnectedPipe;
6263
  OVERLAPPED connectOverlapped= {0};
unknown's avatar
unknown committed
6264 6265 6266
  THD *thd;
  my_thread_init();
  DBUG_ENTER("handle_connections_namedpipes");
6267 6268 6269 6270 6271 6272
  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
6273 6274 6275 6276
  DBUG_PRINT("general",("Waiting for named pipe connections."));
  while (!abort_loop)
  {
    /* wait for named pipe connection */
6277 6278 6279 6280 6281 6282 6283 6284 6285 6286
    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
6287 6288
    if (abort_loop)
      break;
unknown's avatar
unknown committed
6289
    if (!fConnected)
unknown's avatar
unknown committed
6290
      fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
unknown's avatar
unknown committed
6291
    if (!fConnected)
unknown's avatar
unknown committed
6292
    {
unknown's avatar
Merge  
unknown committed
6293 6294
      CloseHandle(hPipe);
      if ((hPipe= CreateNamedPipe(pipe_name,
6295 6296
                                  PIPE_ACCESS_DUPLEX |
                                  FILE_FLAG_OVERLAPPED,
unknown's avatar
Merge  
unknown committed
6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307
                                  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
6308 6309 6310 6311 6312 6313 6314
      {
	sql_perror("Can't create new named pipe!");
	break;					// Abort
      }
    }
    hConnectedPipe = hPipe;
    /* create new pipe for new connection */
6315
    if ((hPipe = CreateNamedPipe(pipe_name,
6316 6317
                 PIPE_ACCESS_DUPLEX |
                 FILE_FLAG_OVERLAPPED,
unknown's avatar
unknown committed
6318 6319 6320 6321
				 PIPE_TYPE_BYTE |
				 PIPE_READMODE_BYTE |
				 PIPE_WAIT,
				 PIPE_UNLIMITED_INSTANCES,
6322 6323
				 (int) global_system_variables.net_buffer_length,
				 (int) global_system_variables.net_buffer_length,
unknown's avatar
unknown committed
6324 6325 6326 6327 6328 6329 6330 6331 6332
				 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
6333
    if (!(thd = new THD))
unknown's avatar
unknown committed
6334
    {
unknown's avatar
Merge  
unknown committed
6335 6336
      DisconnectNamedPipe(hConnectedPipe);
      CloseHandle(hConnectedPipe);
unknown's avatar
unknown committed
6337 6338
      continue;
    }
6339
    set_current_thd(thd);
6340
    if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
6341
	my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
unknown's avatar
unknown committed
6342
    {
6343
      close_connection(thd, ER_OUT_OF_RESOURCES);
unknown's avatar
unknown committed
6344
      delete thd;
6345
      set_current_thd(0);
unknown's avatar
unknown committed
6346 6347
      continue;
    }
6348 6349
    /* Host is unknown */
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
unknown's avatar
unknown committed
6350
    create_new_thread(thd);
6351
    set_current_thd(0);
unknown's avatar
unknown committed
6352
  }
6353
  CloseHandle(connectOverlapped.hEvent);
6354
  DBUG_LEAVE;
6355
  decrement_handler_count();
6356
  return 0;
unknown's avatar
unknown committed
6357
}
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
6358
#endif /* _WIN32 */
unknown's avatar
unknown committed
6359

6360

unknown's avatar
unknown committed
6361
#ifdef HAVE_SMEM
6362

unknown's avatar
unknown committed
6363 6364
/**
  Thread of shared memory's service.
6365

unknown's avatar
unknown committed
6366 6367
  @param arg                              Arguments of thread
*/
6368
pthread_handler_t handle_connections_shared_memory(void *arg)
6369
{
6370 6371
  /* file-mapping object, use for create shared memory */
  HANDLE handle_connect_file_map= 0;
6372
  char  *handle_connect_map= 0;                 // pointer on shared memory
6373 6374 6375
  HANDLE event_connect_answer= 0;
  ulong smem_buffer_length= shared_memory_buffer_length + 4;
  ulong connect_number= 1;
6376
  char *tmp= NULL;
6377 6378
  char *suffix_pos;
  char connect_number_char[22], *p;
6379
  const char *errmsg= 0;
6380
  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
6381 6382 6383 6384
  my_thread_init();
  DBUG_ENTER("handle_connections_shared_memorys");
  DBUG_PRINT("general",("Waiting for allocated shared memory."));

6385 6386 6387 6388 6389 6390
  /*
     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;

6391 6392 6393 6394 6395 6396 6397 6398
  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;

6399 6400 6401 6402 6403 6404 6405
  /*
    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)
  */
6406
  suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
6407
  strmov(suffix_pos, "CONNECT_REQUEST");
6408 6409
  if ((smem_event_connect_request= CreateEvent(sa_event,
                                               FALSE, FALSE, tmp)) == 0)
6410
  {
6411
    errmsg= "Could not create request event";
6412 6413
    goto error;
  }
6414
  strmov(suffix_pos, "CONNECT_ANSWER");
6415
  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6416
  {
6417
    errmsg="Could not create answer event";
6418 6419
    goto error;
  }
6420
  strmov(suffix_pos, "CONNECT_DATA");
6421 6422 6423
  if ((handle_connect_file_map=
       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
6424
  {
6425
    errmsg= "Could not create file mapping";
6426 6427
    goto error;
  }
6428 6429 6430
  if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
						  FILE_MAP_WRITE,0,0,
						  sizeof(DWORD))) == 0)
6431
  {
6432
    errmsg= "Could not create shared memory service";
6433 6434 6435 6436 6437
    goto error;
  }

  while (!abort_loop)
  {
6438
    /* Wait a request from client */
6439
    WaitForSingleObject(smem_event_connect_request,INFINITE);
6440

unknown's avatar
unknown committed
6441 6442 6443
    /*
       it can be after shutdown command
    */
unknown's avatar
Merge  
unknown committed
6444
    if (abort_loop)
unknown's avatar
unknown committed
6445
      goto error;
6446

6447 6448 6449 6450 6451 6452
    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
6453
    HANDLE event_conn_closed= 0;
6454
    THD *thd= 0;
6455

6456
    p= int10_to_str(connect_number, connect_number_char, 10);
6457 6458 6459 6460 6461 6462 6463 6464 6465 6466
    /*
      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);
6467
    strmov(suffix_pos, "DATA");
6468 6469 6470
    if ((handle_client_file_map=
         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
6471
    {
6472
      errmsg= "Could not create file mapping";
6473 6474
      goto errorconn;
    }
6475 6476 6477
    if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
						  FILE_MAP_WRITE,0,0,
						  smem_buffer_length)) == 0)
6478
    {
6479
      errmsg= "Could not create memory map";
6480 6481 6482
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_WROTE");
6483
    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6484
    {
6485
      errmsg= "Could not create client write event";
6486 6487 6488
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_READ");
6489
    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6490
    {
6491
      errmsg= "Could not create client read event";
6492 6493 6494
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_READ");
6495
    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
6496
    {
6497
      errmsg= "Could not create server read event";
6498 6499 6500
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_WROTE");
6501 6502
    if ((event_server_wrote= CreateEvent(sa_event,
                                         FALSE, FALSE, tmp)) == 0)
6503
    {
6504
      errmsg= "Could not create server write event";
6505 6506
      goto errorconn;
    }
unknown's avatar
unknown committed
6507
    strmov(suffix_pos, "CONNECTION_CLOSED");
6508 6509
    if ((event_conn_closed= CreateEvent(sa_event,
                                        TRUE, FALSE, tmp)) == 0)
unknown's avatar
unknown committed
6510 6511 6512 6513
    {
      errmsg= "Could not create closed connection event";
      goto errorconn;
    }
6514
    if (abort_loop)
6515
      goto errorconn;
6516 6517 6518
    if (!(thd= new THD))
      goto errorconn;
    /* Send number of connection to client */
6519
    int4store(handle_connect_map, connect_number);
6520
    if (!SetEvent(event_connect_answer))
6521
    {
6522
      errmsg= "Could not send answer event";
6523 6524
      goto errorconn;
    }
6525
    /* Set event that client should receive data */
6526 6527
    if (!SetEvent(event_client_read))
    {
6528
      errmsg= "Could not set client to read mode";
6529 6530
      goto errorconn;
    }
6531
    set_current_thd(thd);
6532
    if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
unknown's avatar
unknown committed
6533 6534 6535 6536 6537
                                                   handle_client_map,
                                                   event_client_wrote,
                                                   event_client_read,
                                                   event_server_wrote,
                                                   event_server_read,
unknown's avatar
unknown committed
6538
                                                   event_conn_closed)) ||
6539
        my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC)))
6540
    {
6541
      close_connection(thd, ER_OUT_OF_RESOURCES);
6542 6543
      errmsg= 0;
      goto errorconn;
6544
    }
6545
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
6546
    create_new_thread(thd);
6547
    connect_number++;
6548
    set_current_thd(thd);
6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559
    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);
    }
6560
    if (handle_client_file_map)
unknown's avatar
unknown committed
6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573
      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);
6574
    delete thd;
6575
  }
6576
  set_current_thd(0);
6577 6578

  /* End shared memory handling */
6579
error:
6580
  if (tmp)
6581
    my_free(tmp);
6582

6583 6584 6585 6586 6587 6588
  if (errmsg)
  {
    char buff[180];
    strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
    sql_perror(buff);
  }
6589 6590
  my_security_attr_free(sa_event);
  my_security_attr_free(sa_mapping);
6591 6592 6593
  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);
6594
  if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
6595
  DBUG_LEAVE;
6596
  decrement_handler_count();
6597
  return 0;
6598 6599
}
#endif /* HAVE_SMEM */
6600
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
6601

6602 6603 6604

/****************************************************************************
  Handle start options
unknown's avatar
unknown committed
6605 6606
******************************************************************************/

6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651

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


6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664
#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 }


6665 6666 6667 6668 6669
/**
  System variables are automatically command-line options (few
  exceptions are documented in sys_var.h), so don't need
  to be listed here.
*/
6670

Marc Alff's avatar
Marc Alff committed
6671
struct my_option my_long_options[]=
6672
{
unknown's avatar
unknown committed
6673
  {"help", '?', "Display this help and exit.", 
6674
   &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
unknown's avatar
unknown committed
6675
   0, 0},
6676
  {"allow-suspicious-udfs", 0,
unknown's avatar
unknown committed
6677 6678
   "Allows use of UDFs consisting of only one symbol xxx() "
   "without corresponding xxx_init() or xxx_deinit(). That also means "
6679 6680
   "that one can load any function from any library, for example exit() "
   "from libc.so",
6681
   &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
6682
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6683 6684
  {"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
6685
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6686 6687 6688 6689
  /*
    Because Sys_var_bit does not support command-line options, we need to
    explicitely add one for --autocommit
  */
6690 6691 6692
  {"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
6693
  {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
6694
   &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR,
unknown's avatar
unknown committed
6695
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6696
  {"binlog-do-db", OPT_BINLOG_DO_DB,
6697 6698
   "Tells the master it should log updates for the specified database, "
   "and exclude all others not explicitly mentioned.",
6699
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6700
  {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
Staale Smedseng's avatar
Staale Smedseng committed
6701
   "Tells the master that updates to the given database should not be logged to the binary log.",
6702
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6703
  {"binlog-row-event-max-size", 0,
6704 6705 6706
   "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.",
6707 6708
   &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
   0, GET_ULONG, REQUIRED_ARG,
6709 6710 6711 6712
   /* def_value */ 1024, /* min_value */  256, /* max_value */ ULONG_MAX, 
   /* sub_size */     0, /* block_size */ 256, 
   /* app_type */ 0
  },
6713
#ifndef DISABLE_GRANT_OPTIONS
6714
  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
6715
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6716
#endif
6717
  {"character-set-client-handshake", 0,
unknown's avatar
unknown committed
6718
   "Don't ignore client side character set value sent during handshake.",
6719 6720
   &opt_character_set_client_handshake,
   &opt_character_set_client_handshake,
6721
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
6722
  {"character-set-filesystem", 0,
unknown's avatar
unknown committed
6723
   "Set the filesystem character set.",
6724 6725
   &character_set_filesystem_name,
   &character_set_filesystem_name,
unknown's avatar
unknown committed
6726
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6727
  {"character-set-server", 'C', "Set the default character set.",
6728
   &default_character_set_name, &default_character_set_name,
unknown's avatar
unknown committed
6729
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6730
  {"chroot", 'r', "Chroot mysqld daemon during startup.",
6731
   &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6732
   0, 0, 0, 0, 0, 0},
6733
  {"collation-server", 0, "Set the default collation.",
6734
   &default_collation_name, &default_collation_name,
unknown's avatar
unknown committed
6735
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Staale Smedseng's avatar
Staale Smedseng committed
6736
  {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
6737
   &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
6738
   0, 0, 0},
6739
  {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
6740
   NO_ARG, 0, 0, 0, 0, 0, 0},
6741 6742 6743
  /* 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. */
Michael Widenius's avatar
Michael Widenius committed
6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791
#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!",
6792
   &my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
Michael Widenius's avatar
Michael Widenius committed
6793 6794 6795 6796 6797 6798 6799
#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 */
6800
  {"default-storage-engine", 0, "The default storage engine for new tables",
6801
   &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
6802
   0, 0, 0, 0, 0, 0 },
6803
  {"default-time-zone", 0, "Set the default time zone.",
6804
   &default_tz_name, &default_tz_name,
6805
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
Michael Widenius's avatar
Michael Widenius committed
6806 6807 6808 6809 6810 6811 6812 6813
#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
6814
#ifdef HAVE_OPENSSL
6815
  {"des-key-file", 0,
unknown's avatar
unknown committed
6816
   "Load keys for des_encrypt() and des_encrypt from given file.",
6817
   &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6818 6819
   0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
Michael Widenius's avatar
Michael Widenius committed
6820
#ifdef HAVE_STACKTRACE
Sergei Golubchik's avatar
Sergei Golubchik committed
6821
  {"stack-trace", 0 , "Print a symbolic stack trace on failure",
Michael Widenius's avatar
Michael Widenius committed
6822 6823
   &opt_stack_trace, &opt_stack_trace, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_STACKTRACE */
6824 6825 6826 6827
  {"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
6828
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6829 6830
  /* We must always support the next option to make scripts like mysqltest
     easier to do */
6831
  {"gdb", 0,
Sergei Golubchik's avatar
Sergei Golubchik committed
6832 6833 6834
   "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},
6835
#ifdef HAVE_LARGE_PAGE_OPTION
6836
  {"super-large-pages", 0, "Enable support for super large pages.",
6837
   &opt_super_large_pages, &opt_super_large_pages, 0,
6838
   GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
unknown's avatar
Merge  
unknown committed
6839
#endif
6840
  {"language", 'L',
6841 6842
   "Client error messages in given language. May be given as a full path. "
   "Deprecated. Use --lc-messages-dir instead.",
6843
   0, 0, 0,
6844
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6845
  {"lc-messages", 0,
6846
   "Set the language used for the error messages.",
6847
   &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
6848
   0, 0, 0, 0, 0, 0 },
6849
  {"lc-time-names", 0,
6850
   "Set the language used for the month names and the days of the week.",
6851
   &lc_time_names_name, &lc_time_names_name,
6852
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6853 6854 6855
  {"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
6856
   "for specifying log files. Sets names for --log-bin, --log-bin-index, "
6857
   "--relay-log, --relay-log-index, --general-log-file, "
Sergei Golubchik's avatar
Sergei Golubchik committed
6858
   "--log-slow-query-log-file, --log-error-file, and --pid-file",
6859 6860
   &opt_log_basename, &opt_log_basename, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0},
6861
  {"log-bin", OPT_BIN_LOG,
6862 6863
   "Log update queries in binary format. Optional argument should be name for "
   "binary log. If not given "
6864
   "'datadir'/'log-basename'-bin or 'datadir'/mysql-bin will be used (the later if "
Sergei Golubchik's avatar
Sergei Golubchik committed
6865
   "--log-basename is not specified). We strongly recommend to use either "
6866
   "--log-basename or specify a filename to ensure that replication doesn't "
6867
   "stop if the real hostname of the computer changes.",
6868
   &opt_bin_logname, &opt_bin_logname, 0, GET_STR,
unknown's avatar
unknown committed
6869
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6870
  {"log-bin-index", 0,
6871
   "File that holds the names for last binary log files.",
6872
   &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
6873
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6874
  {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
6875
   &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
6876
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6877
  {"log-short-format", 0,
unknown's avatar
unknown committed
6878
   "Don't log extra information to update and slow-query logs.",
6879
   &opt_short_log_format, &opt_short_log_format,
unknown's avatar
unknown committed
6880
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6881
  {"log-slow-admin-statements", 0,
6882 6883
   "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to "
   "the slow log if it is open.", &opt_log_slow_admin_statements,
6884
   &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6885
 {"log-slow-slave-statements", 0,
6886
  "Log slow statements executed by slave thread to the slow log if it is open.",
6887
  &opt_log_slow_slave_statements, &opt_log_slow_slave_statements,
6888
  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6889
  {"log-tc", 0,
unknown's avatar
Merge  
unknown committed
6890
   "Path to transaction coordinator log (used for transactions that affect "
Staale Smedseng's avatar
Staale Smedseng committed
6891
   "more than one storage engine, when binary log is disabled).",
6892
   &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
unknown's avatar
Merge  
unknown committed
6893
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6894
#ifdef HAVE_MMAP
6895
  {"log-tc-size", 0, "Size of transaction coordinator log.",
6896
   &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
unknown's avatar
unknown committed
6897
   REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0,
6898
   TC_LOG_PAGE_SIZE, 0},
6899
#endif
6900
  {"master-info-file", 0,
6901
   "The location and name of the file that remembers the master and where "
6902
   "the I/O replication thread is in the master's binlogs. Defaults to "
Sergei Golubchik's avatar
Sergei Golubchik committed
6903
   "master.info",
6904
   &master_info_file, &master_info_file, 0, GET_STR,
unknown's avatar
unknown committed
6905
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6906
  {"master-retry-count", 0,
6907
   "The number of tries the slave will make to connect to the master before giving up.",
6908
   &master_retry_count, &master_retry_count, 0, GET_ULONG,
6909
   REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6910
#ifdef HAVE_REPLICATION
6911
  {"init-rpl-role", 0, "Set the replication role.",
6912
   &rpl_status, &rpl_status, &rpl_role_typelib,
6913
   GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6914
#endif /* HAVE_REPLICATION */
6915
  {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
6916
   &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6917
  {"old-style-user-limits", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6918 6919
   "Enable old-style user limits (before 5.0.3, user resources were counted "
   "per each user+host vs. per account).",
6920
   &opt_old_style_user_limits, &opt_old_style_user_limits,
unknown's avatar
Merge  
unknown committed
6921
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6922
  {"port-open-timeout", 0,
6923
   "Maximum time in seconds to wait for the port to become free. "
6924 6925
   "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
   GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6926
  {"replicate-do-db", OPT_REPLICATE_DO_DB,
6927 6928 6929 6930 6931 6932 6933
   "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.%.",
6934
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6935
  {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
6936 6937 6938
   "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 "
6939
   "to replicate-do-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6940
  {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
6941 6942 6943 6944 6945
   "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-"
6946
   "table=db_name.%. ", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6947
  {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
6948 6949 6950
   "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 "
6951
   "replicate-ignore-db.", 0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6952
  {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
6953 6954
   "Updates to a database with a different name than the original. Example: "
   "replicate-rewrite-db=master_db_name->slave_db_name.",
6955
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6956
#ifdef HAVE_REPLICATION
6957
  {"replicate-same-server-id", 0,
6958 6959 6960 6961
   "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,
6962
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6963
#endif
unknown's avatar
unknown committed
6964
  {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
6965 6966 6967 6968 6969 6970
   "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.",
6971
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6972
  {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
6973 6974 6975 6976 6977 6978
   "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.",
6979
   0, 0, 0, GET_STR | GET_ASK_ADDR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6980
  {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing). Deprecated.",
6981
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6982
  {"safe-user-create", 0,
6983
   "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
6984
   &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
6985
   NO_ARG, 0, 0, 0, 0, 0, 0},
6986
  {"show-slave-auth-info", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6987
   "Show user and password in SHOW SLAVE HOSTS on this master.",
6988
   &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
6989
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6990 6991 6992
  {"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},
6993
#ifndef DISABLE_GRANT_OPTIONS
6994
  {"skip-grant-tables", 0,
Staale Smedseng's avatar
Staale Smedseng committed
6995
   "Start without grant tables. This gives all users FULL ACCESS to all tables.",
6996
   &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6997
   0},
6998
#endif
unknown's avatar
unknown committed
6999 7000
  {"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},
7001
  {"skip-slave-start", 0,
7002 7003
   "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},
7004 7005 7006 7007 7008 7009 7010
#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
7011
#ifdef HAVE_OPENSSL
7012
  {"ssl", 0,
7013
   "Enable SSL for connection (automatically enabled if an ssl option is used).",
7014
   &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
7015
   0, 0, 0},
7016
#endif
unknown's avatar
unknown committed
7017
#ifdef __WIN__
7018
  {"standalone", 0,
unknown's avatar
unknown committed
7019 7020 7021 7022
  "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.",
7023
   &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
7024 7025 7026 7027
   /*
     The system call realpath() produces warnings under valgrind and
     purify. These are not suppressed: instead we disable symlinks
     option if compiled with valgrind support.
7028 7029
     Also disable by default on Windows, due to high overhead for checking .sym 
     files.
7030
   */
7031
   IF_VALGRIND(0,IF_WIN(0,1)), 0, 0, 0, 0, 0},
7032
  {"sysdate-is-now", 0,
7033 7034 7035 7036
   "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
7037
   0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
7038
  {"tc-heuristic-recover", 0,
7039
   "Decision to use in heuristic recover process. Possible values are COMMIT "
7040
   "or ROLLBACK.", &tc_heuristic_recover, &tc_heuristic_recover,
7041 7042
   &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"temp-pool", 0,
7043
#if (ENABLE_TEMP_POOL)
7044 7045
   "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.",
7046 7047 7048
#else
   "This option is ignored on this OS.",
#endif
7049
   &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
unknown's avatar
unknown committed
7050
   0, 0, 0, 0, 0},
7051 7052
  {"transaction-isolation", 0,
   "Default transaction isolation level.",
7053 7054
   &global_system_variables.tx_isolation,
   &global_system_variables.tx_isolation, &tx_isolation_typelib,
7055
   GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
7056 7057 7058 7059 7060 7061
  {"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},
7062
  {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
7063
   0, 0, 0, 0, 0, 0},
Staale Smedseng's avatar
Staale Smedseng committed
7064
  {"verbose", 'v', "Used with --help option for detailed help.",
7065
   &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7066
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
7067
   NO_ARG, 0, 0, 0, 0, 0, 0},
7068
  {"plugin-load", OPT_PLUGIN_LOAD,
7069 7070 7071
   "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.",
7072
   0, 0, 0,
unknown's avatar
unknown committed
7073
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7074 7075 7076 7077 7078 7079
  {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
   "Optional semicolon-separated list of plugins to load. This option adds "
   "to the list speficied by --plugin-load in an incremental way. "
   "It can be specified many times, adding more plugins every time.",
   0, 0, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7080
  {"table_cache", 0, "Deprecated; use --table-open-cache instead.",
7081
   &tc_size, &tc_size, 0, GET_ULONG,
7082 7083 7084 7085 7086
   REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},

  /* 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"),
7087
  MYSQL_COMPATIBILITY_OPTION("log-bin-use-v1-row-events"),
7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126
  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
7127
};
unknown's avatar
unknown committed
7128

7129
static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
7130
{
7131
  var->type= SHOW_LONGLONG;
7132 7133 7134 7135
  var->value= (char *)&thd->query_id;
  return 0;
}

7136

7137
static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
7138
{
7139
  var->type= SHOW_MY_BOOL;
7140 7141 7142 7143
  var->value= (char *)&thd->net.compress;
  return 0;
}

7144
static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
7145
{
7146
  var->type= SHOW_LONG;
7147
  var->value= buff;
unknown's avatar
unknown committed
7148
  *((long *)buff)= (long) (thd->query_start() - server_start_time);
7149 7150 7151
  return 0;
}

7152
#ifdef ENABLED_PROFILING
7153 7154 7155 7156 7157 7158 7159
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;
}
7160
#endif
7161

7162
#ifdef HAVE_REPLICATION
7163
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
7164
{
7165
  var->type= SHOW_CHAR;
7166 7167 7168 7169
  var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
  return 0;
}

7170
static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
7171
{
7172
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7173
  bool tmp;
unknown's avatar
unknown committed
7174
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7175

7176 7177
  var->type= SHOW_MY_BOOL;
  var->value= buff;
unknown's avatar
unknown committed
7178
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7179
  mysql_mutex_lock(&LOCK_active_mi);
7180 7181 7182 7183 7184 7185 7186 7187 7188
  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
7189 7190 7191 7192
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
    *((my_bool *)buff)= tmp;
7193
  else
7194
    var->type= SHOW_UNDEF;
7195 7196
  return 0;
}
Andrei Elkin's avatar
Andrei Elkin committed
7197

7198

Andrei Elkin's avatar
Andrei Elkin committed
7199 7200
static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
{
7201
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7202
  longlong tmp;
unknown's avatar
unknown committed
7203
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7204

7205 7206
  var->type= SHOW_LONGLONG;
  var->value= buff;
unknown's avatar
unknown committed
7207
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7208
  mysql_mutex_lock(&LOCK_active_mi);
7209 7210 7211 7212 7213 7214 7215 7216
  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
7217 7218 7219 7220
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
    *((longlong *)buff)= tmp;
Andrei Elkin's avatar
Andrei Elkin committed
7221 7222 7223 7224 7225
  else
    var->type= SHOW_UNDEF;
  return 0;
}

7226

Andrei Elkin's avatar
Andrei Elkin committed
7227 7228
static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
{
7229
  Master_info *mi= NULL;
unknown's avatar
unknown committed
7230 7231
  float tmp;
  LINT_INIT(tmp);
unknown's avatar
unknown committed
7232

7233 7234
  var->type= SHOW_CHAR;
  var->value= buff;
unknown's avatar
unknown committed
7235
  mysql_mutex_unlock(&LOCK_status);
Marc Alff's avatar
Marc Alff committed
7236
  mysql_mutex_lock(&LOCK_active_mi);
7237 7238 7239 7240
  if (master_info_index) 
  {
    mi= master_info_index->
      get_master_info(&thd->variables.default_master_connection,
7241
                    Sql_condition::WARN_LEVEL_NOTE);
7242 7243 7244
    if (mi)
      tmp= mi->heartbeat_period;
  }
unknown's avatar
unknown committed
7245 7246 7247
  mysql_mutex_unlock(&LOCK_active_mi);
  mysql_mutex_lock(&LOCK_status);
  if (mi)
unknown's avatar
unknown committed
7248
    sprintf(buff, "%.3f", tmp);
Andrei Elkin's avatar
Andrei Elkin committed
7249 7250 7251 7252 7253 7254
  else
    var->type= SHOW_UNDEF;
  return 0;
}


7255 7256
#endif /* HAVE_REPLICATION */

7257
static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
7258
{
7259
  var->type= SHOW_LONG;
7260
  var->value= buff;
7261
  *((long *) buff)= (long) tc_records();
7262 7263 7264
  return 0;
}

unknown's avatar
unknown committed
7265 7266 7267 7268
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
7269
  mysql_mutex_lock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7270
  *((long *)buff)= (long)prepared_stmt_count;
Marc Alff's avatar
Marc Alff committed
7271
  mysql_mutex_unlock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
7272 7273 7274
  return 0;
}

7275
static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
7276
{
7277
  var->type= SHOW_LONG;
7278
  var->value= buff;
7279
  *((long *) buff)= (long) tdc_records();
7280 7281 7282
  return 0;
}

7283 7284 7285 7286 7287 7288 7289 7290 7291 7292

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
7293
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
7294
/* Functions relying on CTX */
7295
static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
7296
{
7297
  var->type= SHOW_LONG;
7298 7299 7300 7301 7302 7303
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
  return 0;
}

7304
static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
7305
{
7306
  var->type= SHOW_LONG;
7307 7308 7309 7310 7311 7312
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

7313
static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
7314
{
7315
  var->type= SHOW_LONG;
7316 7317 7318 7319 7320 7321
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

7322
static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7323
{
7324
  var->type= SHOW_LONG;
7325 7326 7327 7328 7329 7330
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

7331
static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
7332
{
7333
  var->type= SHOW_LONG;
7334 7335 7336 7337 7338 7339
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

7340
static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
7341
{
7342
  var->type= SHOW_LONG;
7343 7344 7345 7346 7347 7348
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

7349
static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
7350
{
7351
  var->type= SHOW_LONG;
7352 7353 7354 7355 7356 7357
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

7358
static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
7359
{
7360
  var->type= SHOW_LONG;
7361 7362 7363 7364 7365 7366
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
  return 0;
}

7367
static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
7368
{
7369
  var->type= SHOW_LONG;
7370 7371 7372 7373 7374 7375
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
  return 0;
}

7376
static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
7377
{
7378
  var->type= SHOW_LONG;
7379 7380 7381 7382 7383 7384
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
  return 0;
}

7385
static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
7386
{
7387
  var->type= SHOW_LONG;
7388 7389 7390 7391 7392 7393
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
  return 0;
}

7394
static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
7395
{
7396
  var->type= SHOW_LONG;
7397 7398 7399 7400 7401 7402
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
  return 0;
}

7403
static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
7404
{
7405
  var->type= SHOW_LONG;
7406 7407 7408 7409 7410 7411
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
  return 0;
}

7412
static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7413
{
7414
  var->type= SHOW_LONG;
7415 7416 7417 7418 7419 7420
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
  return 0;
}

7421
static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7422
{
7423
  var->type= SHOW_LONG;
7424 7425 7426 7427 7428 7429
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
  return 0;
}

7430
static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
7431
{
7432
  var->type= SHOW_CHAR;
7433
  if (!ssl_acceptor_fd)
unknown's avatar
unknown committed
7434
    var->value= const_cast<char*>("NONE");
7435 7436 7437 7438
  else
    switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
    {
    case SSL_SESS_CACHE_OFF:
unknown's avatar
unknown committed
7439
      var->value= const_cast<char*>("OFF"); break;
7440
    case SSL_SESS_CACHE_CLIENT:
unknown's avatar
unknown committed
7441
      var->value= const_cast<char*>("CLIENT"); break;
7442
    case SSL_SESS_CACHE_SERVER:
unknown's avatar
unknown committed
7443
      var->value= const_cast<char*>("SERVER"); break;
7444
    case SSL_SESS_CACHE_BOTH:
unknown's avatar
unknown committed
7445
      var->value= const_cast<char*>("BOTH"); break;
7446
    case SSL_SESS_CACHE_NO_AUTO_CLEAR:
unknown's avatar
unknown committed
7447
      var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
7448
    case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
unknown's avatar
unknown committed
7449
      var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
7450
    default:
unknown's avatar
unknown committed
7451
      var->value= const_cast<char*>("Unknown"); break;
7452 7453 7454 7455
    }
  return 0;
}

7456
/*
7457
   Functions relying on SSL
7458 7459 7460 7461 7462
   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.
 */
7463
static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
7464
{
7465
  var->type= SHOW_CHAR;
7466 7467 7468
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
  else
7469
    var->value= (char *)"";
7470 7471 7472
  return 0;
}

7473
static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
7474
{
7475
  var->type= SHOW_LONG;
7476
  var->value= buff;
7477 7478 7479 7480
  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
7481
  return 0;
7482 7483
}

7484
static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
7485
{
7486
  var->type= SHOW_LONG;
7487
  var->value= buff;
7488 7489 7490 7491
  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;
7492 7493 7494
  return 0;
}

7495
static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
7496
{
7497
  var->type= SHOW_LONG;
7498
  var->value= buff;
7499 7500 7501 7502
  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;
7503 7504 7505
  return 0;
}

7506
static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
7507
{
7508
  var->type= SHOW_LONG;
7509
  var->value= buff;
7510 7511 7512 7513
  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;
7514 7515 7516
  return 0;
}

7517
static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
7518
{
7519
  var->type= SHOW_CHAR;
7520 7521 7522
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
  else
7523
    var->value= (char *)"";
7524 7525 7526
  return 0;
}

7527
static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
7528
{
7529
  var->type= SHOW_CHAR;
7530
  var->value= buff;
7531
  if (thd->vio_ok() && thd->net.vio->ssl_arg)
7532 7533 7534
  {
    int i;
    const char *p;
7535 7536 7537
    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++)
7538
    {
7539
      buff= strnmov(buff, p, end-buff-1);
7540 7541 7542 7543 7544 7545 7546 7547 7548
      *buff++= ':';
    }
    if (i)
      buff--;
  }
  *buff=0;
  return 0;
}

7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652

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

7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679
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
7680
  set_one_keycache_var("blocks_warm",        blocks_warm);
7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694
  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;
}

7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730
#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

7731 7732 7733 7734 7735 7736 7737 7738 7739
#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
7740

7741 7742 7743 7744
/*
  Variables shown by SHOW STATUS in alphabetical order
*/

7745
SHOW_VAR status_vars[]= {
7746 7747
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
7748
  {"Access_denied_errors",     (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7749
  {"Binlog_bytes_written",     (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
7750 7751
  {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
  {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
7752 7753
  {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,  SHOW_LONG},
  {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,       SHOW_LONG},
7754
  {"Busy_time",                (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
7755 7756
  {"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
7757
  {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
7758
  {"Compression",              (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
7759
  {"Connections",              (char*) &thread_id,              SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7760 7761 7762 7763 7764 7765
  {"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},
7766
  {"Cpu_time",                 (char*) offsetof(STATUS_VAR, cpu_time), SHOW_DOUBLE_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7767
  {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables_), SHOW_LONG_STATUS},
7768
  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
Sergei Golubchik's avatar
Sergei Golubchik committed
7769
  {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables_), SHOW_LONG_STATUS},
7770 7771 7772
#ifndef DBUG_OFF
  {"Debug",                    (char*) &debug_status_func,  SHOW_FUNC},
#endif
7773
  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
7774
  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
7775
  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
7776
  {"Empty_queries",            (char*) offsetof(STATUS_VAR, empty_queries), SHOW_LONG_STATUS},
7777 7778 7779 7780 7781 7782 7783 7784
  {"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},
7785 7786
  {"Feature_trigger",          (char*) offsetof(STATUS_VAR, feature_trigger), SHOW_LONG_STATUS},
  {"Feature_xml",              (char*) offsetof(STATUS_VAR, feature_xml), SHOW_LONG_STATUS},
7787
  {"Flush_commands",           (char*) &show_flush_commands, SHOW_SIMPLE_FUNC},
unknown's avatar
Merge  
unknown committed
7788 7789 7790
  {"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},
7791
  {"Handler_external_lock",    (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS},
7792
  {"Handler_icp_attempts",     (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
7793 7794
  {"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},
7795 7796
  {"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
7797 7798 7799
  {"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},
7800
  {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7801 7802 7803
  {"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},
7804
  {"Handler_read_rnd_deleted", (char*) offsetof(STATUS_VAR, ha_read_rnd_deleted_count), SHOW_LONG_STATUS},
unknown's avatar
Merge  
unknown committed
7805 7806 7807 7808
  {"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},
7809 7810
  {"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},
7811 7812
  {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
  {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
7813
  {"Key",                      (char*) &show_default_keycache, SHOW_FUNC},
7814
  {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
7815
  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
7816
  {"Memory_used",              (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS},
7817 7818 7819
  {"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},
7820 7821
  {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_SIMPLE_FUNC},
  {"Open_tables",              (char*) &show_open_tables,       SHOW_SIMPLE_FUNC},
7822
  {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
7823
  {"Opened_plugin_libraries",  (char*) &dlopen_count, SHOW_LONG},
7824
  {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7825
  {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
7826
  {"Opened_views",             (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
7827
  {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC},
Sergei Golubchik's avatar
Sergei Golubchik committed
7828
  {"Rows_sent",                (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
7829
  {"Rows_read",                (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
7830
  {"Rows_tmp_read",            (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
unknown's avatar
unknown committed
7831
#ifdef HAVE_QUERY_CACHE
7832 7833
  {"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
7834
  {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
7835
  {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
7836
  {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
unknown's avatar
unknown committed
7837
  {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
7838 7839
  {"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
7840
#endif /*HAVE_QUERY_CACHE*/
7841
  {"Queries",                  (char*) &show_queries,            SHOW_SIMPLE_FUNC},
7842
  {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
7843
#ifdef HAVE_REPLICATION
7844
  {"Rpl_status",               (char*) &show_rpl_status,          SHOW_SIMPLE_FUNC},
7845
#endif
Sergei Golubchik's avatar
Sergei Golubchik committed
7846 7847 7848 7849 7850
  {"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
7851
  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_INT},
7852
#ifdef HAVE_REPLICATION
7853 7854
  {"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
7855
  {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
7856
  {"Slave_running",            (char*) &show_slave_running,     SHOW_SIMPLE_FUNC},
7857
#endif
7858
  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
unknown's avatar
Merge  
unknown committed
7859
  {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
Sergei Golubchik's avatar
Sergei Golubchik committed
7860 7861 7862 7863
  {"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
7864
#ifdef HAVE_OPENSSL
Konstantin Osipov's avatar
Konstantin Osipov committed
7865
#ifndef EMBEDDED_LIBRARY
7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877
  {"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
7878 7879
  {"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},
7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890
  {"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
7891
#endif
unknown's avatar
unknown committed
7892
#endif /* HAVE_OPENSSL */
7893
  {"Syncs",                    (char*) &my_sync_count,          SHOW_LONG_NOFLUSH},
unknown's avatar
unknown committed
7894 7895 7896 7897
  /*
    Expression cache used only for caching subqueries now, so its statistic
    variables we call subquery_cache*.
  */
7898 7899
  {"Subquery_cache_hit",       (char*) &subquery_cache_hit,     SHOW_LONG},
  {"Subquery_cache_miss",      (char*) &subquery_cache_miss,    SHOW_LONG},
unknown's avatar
unknown committed
7900 7901
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
7902
#ifdef HAVE_MMAP
unknown's avatar
Merge  
unknown committed
7903
  {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
7904
  {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
7905
  {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
7906
#endif
7907
#ifdef HAVE_POOL_OF_THREADS
7908
  {"Threadpool_idle_threads",  (char *) &show_threadpool_idle_threads, SHOW_SIMPLE_FUNC},
7909
  {"Threadpool_threads",       (char *) &tp_stats.num_worker_threads, SHOW_INT},
7910
#endif
7911
  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_NOFLUSH},
Konstantin Osipov's avatar
Konstantin Osipov committed
7912
  {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
7913 7914
  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
  {"Threads_running",          (char*) &thread_running,         SHOW_INT},
7915
  {"Uptime",                   (char*) &show_starttime,         SHOW_SIMPLE_FUNC},
7916
#ifdef ENABLED_PROFILING
7917
  {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_SIMPLE_FUNC},
7918
#endif
7919
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
7920 7921
};

7922
static bool add_terminator(DYNAMIC_ARRAY *options)
7923 7924
{
  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
7925
  return insert_dynamic(options, (uchar *)&empty_element);
7926 7927
}

7928 7929 7930 7931 7932 7933 7934 7935 7936
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;
}

7937
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
7938 7939
static void print_version(void)
{
7940
  set_server_version();
7941

7942 7943
  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
7944 7945
}

7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974
/** 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;
    }
  }
  DBUG_ASSERT(a->name == b->name);
  return 0;
}

static void print_help()
{
  MEM_ROOT mem_root;
7975
  init_alloc_root(&mem_root, 4096, 4096, MYF(0));
7976 7977

  pop_dynamic(&all_options);
7978 7979
  add_many_options(&all_options, pfs_early_options,
                  array_elements(pfs_early_options));
Marc Alff's avatar
Marc Alff committed
7980
  sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
7981 7982
  add_plugin_options(&all_options, &mem_root);
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
Marc Alff's avatar
Marc Alff committed
7983
  add_terminator(&all_options);
7984 7985 7986 7987 7988 7989 7990

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

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

unknown's avatar
unknown committed
7991 7992
static void usage(void)
{
7993
  DBUG_ENTER("usage");
7994
  if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
unknown's avatar
unknown committed
7995 7996 7997 7998 7999
					           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
8000
  print_version();
8001
  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
Sergei Golubchik's avatar
Sergei Golubchik committed
8002
  puts("Starts the MariaDB database server.\n");
unknown's avatar
unknown committed
8003
  printf("Usage: %s [OPTIONS]\n", my_progname);
8004
  if (!opt_verbose)
Staale Smedseng's avatar
Staale Smedseng committed
8005
    puts("\nFor more help options (several pages), use mysqld --verbose --help.");
8006 8007
  else
  {
unknown's avatar
unknown committed
8008 8009
#ifdef __WIN__
  puts("NT and Win32 specific options:\n\
Staale Smedseng's avatar
Staale Smedseng committed
8010 8011 8012 8013 8014 8015 8016 8017
  --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
8018
");
8019
  puts("");
unknown's avatar
unknown committed
8020
#endif
8021
  print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
unknown's avatar
unknown committed
8022 8023
  puts("");
  set_ports();
8024

unknown's avatar
unknown committed
8025
  /* Print out all the options including plugin supplied options */
8026
  print_help();
8027

8028 8029 8030 8031 8032 8033 8034
  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
8035
  puts("\n\
unknown's avatar
unknown committed
8036
To see what values a running MySQL server is using, type\n\
8037
'mysqladmin variables' instead of 'mysqld --verbose --help'.");
8038
  }
8039
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
8040
}
8041
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
8042

unknown's avatar
unknown committed
8043
/**
8044
  Initialize MySQL global variables to default values.
unknown's avatar
unknown committed
8045

unknown's avatar
unknown committed
8046
  @note
unknown's avatar
unknown committed
8047 8048 8049 8050
    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
8051

8052
    We don't need to set variables refered to in my_long_options
unknown's avatar
unknown committed
8053 8054
    as these are initialized by my_getopt.
*/
unknown's avatar
unknown committed
8055

8056
static int mysql_init_variables(void)
unknown's avatar
unknown committed
8057 8058 8059 8060
{
  /* Things reset to zero */
  opt_skip_slave_start= opt_reckless_slave = 0;
  mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
8061
#if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH)
8062
  /*  We can only test for sub paths if my_symlink.c is using realpath */
8063
  myisam_test_invalid_symlink= test_if_data_home_dir;
8064
#endif
unknown's avatar
unknown committed
8065
  opt_log= opt_slow_log= 0;
8066
  opt_bin_log= opt_bin_log_used= 0;
unknown's avatar
unknown committed
8067
  opt_disable_networking= opt_skip_show_db=0;
8068
  opt_skip_name_resolve= 0;
8069
  opt_ignore_builtin_innodb= 0;
Sergei Golubchik's avatar
Sergei Golubchik committed
8070
  opt_logname= opt_binlog_index_name= opt_slow_logname= 0;
8071
  opt_log_basename= 0;
unknown's avatar
Merge  
unknown committed
8072
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
8073 8074
  opt_secure_auth= 0;
  opt_bootstrap= opt_myisam_log= 0;
unknown's avatar
unknown committed
8075
  mqh_used= 0;
8076
  kill_in_progress= 0;
unknown's avatar
unknown committed
8077 8078 8079 8080 8081 8082 8083
  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;
8084
  opt_using_transactions= 0;
unknown's avatar
unknown committed
8085 8086
  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
8087
  aborted_threads= aborted_connects= 0;
unknown's avatar
unknown committed
8088
  subquery_cache_miss= subquery_cache_hit= 0;
unknown's avatar
unknown committed
8089 8090
  delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
  delayed_insert_errors= thread_created= 0;
unknown's avatar
Merge  
unknown committed
8091
  specialflag= 0;
8092
  binlog_cache_use=  binlog_cache_disk_use= 0;
unknown's avatar
unknown committed
8093 8094
  max_used_connections= slow_launch_threads = 0;
  mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
8095
  prepared_stmt_count= 0;
8096
  mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
8097
  bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
unknown's avatar
Merge  
unknown committed
8098
  bzero((char *) &global_status_var, sizeof(global_status_var));
8099
  opt_large_pages= 0;
8100
  opt_super_large_pages= 0;
8101 8102 8103
#if defined(ENABLED_DEBUG_SYNC)
  opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
8104
  key_map_full.set_all();
unknown's avatar
unknown committed
8105

8106 8107 8108 8109 8110
  /* 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
8111
  character_set_filesystem= &my_charset_bin;
8112

unknown's avatar
unknown committed
8113
  opt_specialflag= SPECIAL_ENGLISH;
8114
  unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET;
unknown's avatar
unknown committed
8115 8116 8117 8118 8119
  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);
8120
  denied_connections= 0;
8121
  executed_events= 0;
8122
  global_query_id= thread_id= 1L;
8123
  my_atomic_rwlock_init(&global_query_id_lock);
8124
  my_atomic_rwlock_init(&thread_running_lock);
Michael Widenius's avatar
Michael Widenius committed
8125
  my_atomic_rwlock_init(&thread_count_lock);
8126
  my_atomic_rwlock_init(&statistics_lock);
8127
  my_atomic_rwlock_init(slave_executed_entries_lock);
unknown's avatar
unknown committed
8128 8129 8130
  strmov(server_version, MYSQL_SERVER_VERSION);
  threads.empty();
  thread_cache.empty();
8131
  key_caches.empty();
unknown's avatar
unknown committed
8132
  if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
8133
                                                default_key_cache_base.length)))
8134 8135 8136 8137
  {
    sql_print_error("Cannot allocate the keycache");
    return 1;
  }
8138

8139 8140
  /* set key_cache_hash.default_value = dflt_key_cache */
  multi_keycache_init();
unknown's avatar
unknown committed
8141 8142

  /* Set directory paths */
8143
  mysql_real_data_home_len=
8144 8145
    strmake_buf(mysql_real_data_home,
                get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home;
unknown's avatar
unknown committed
8146 8147
  /* Replication parameters */
  master_info_file= (char*) "master.info",
unknown's avatar
unknown committed
8148
    relay_log_info_file= (char*) "relay-log.info";
unknown's avatar
unknown committed
8149 8150
  report_user= report_password = report_host= 0;	/* TO BE DELETED */
  opt_relay_logname= opt_relaylog_index_name= 0;
8151
  slave_retried_transactions= 0;
unknown's avatar
unknown committed
8152 8153 8154

  /* Variables in libraries */
  charsets_dir= 0;
8155
  default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
8156
  default_collation_name= compiled_default_collation_name;
unknown's avatar
unknown committed
8157
  character_set_filesystem_name= (char*) "binary";
8158
  lc_messages= (char*) "en_US";
8159
  lc_time_names_name= (char*) "en_US";
8160
  
unknown's avatar
unknown committed
8161 8162 8163 8164
  /* 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");
8165
  current_dbug_option= default_dbug_option;
unknown's avatar
unknown committed
8166 8167
#endif
  opt_error_log= IF_WIN(1,0);
8168 8169
#ifdef ENABLED_PROFILING
    have_profiling = SHOW_OPTION_YES;
8170
#else
8171
    have_profiling = SHOW_OPTION_NO;
8172
#endif
8173

unknown's avatar
unknown committed
8174
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8175
  have_ssl=SHOW_OPTION_YES;
8176 8177
#if HAVE_YASSL
  have_openssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8178
#else
8179 8180 8181 8182
  have_openssl= SHOW_OPTION_YES;
#endif
#else
  have_openssl= have_ssl= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8183
#endif
unknown's avatar
unknown committed
8184
#ifdef HAVE_BROKEN_REALPATH
unknown's avatar
unknown committed
8185 8186 8187 8188
  have_symlink=SHOW_OPTION_NO;
#else
  have_symlink=SHOW_OPTION_YES;
#endif
8189 8190 8191 8192 8193
#ifdef HAVE_DLOPEN
  have_dlopen=SHOW_OPTION_YES;
#else
  have_dlopen=SHOW_OPTION_NO;
#endif
unknown's avatar
unknown committed
8194 8195 8196 8197 8198
#ifdef HAVE_QUERY_CACHE
  have_query_cache=SHOW_OPTION_YES;
#else
  have_query_cache=SHOW_OPTION_NO;
#endif
8199 8200 8201 8202 8203 8204 8205 8206 8207 8208
#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
8209 8210 8211 8212 8213 8214
#ifdef HAVE_CRYPT
  have_crypt=SHOW_OPTION_YES;
#else
  have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
8215
  have_compress= SHOW_OPTION_YES;
unknown's avatar
unknown committed
8216
#else
8217
  have_compress= SHOW_OPTION_NO;
unknown's avatar
unknown committed
8218 8219 8220 8221 8222 8223
#endif
#ifdef HAVE_LIBWRAP
  libwrapName= NullS;
#endif
#ifdef HAVE_OPENSSL
  des_key_file = 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8224
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
8225
  ssl_acceptor_fd= 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
8226 8227
#endif /* ! EMBEDDED_LIBRARY */
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
8228 8229 8230 8231
#ifdef HAVE_SMEM
  shared_memory_base_name= default_shared_memory_base_name;
#endif

8232 8233
#if defined(__WIN__)
  /* Allow Win32 users to move MySQL anywhere */
unknown's avatar
unknown committed
8234 8235
  {
    char prg_dev[LIBLEN];
8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246
    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
8247 8248 8249 8250 8251
    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
    cleanup_dirname(mysql_home,prg_dev);
  }
#else
  const char *tmpenv;
unknown's avatar
unknown committed
8252
  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
unknown's avatar
unknown committed
8253
    tmpenv = DEFAULT_MYSQL_HOME;
8254
  strmake_buf(mysql_home, tmpenv);
unknown's avatar
unknown committed
8255
#endif
8256
  return 0;
unknown's avatar
unknown committed
8257 8258
}

8259 8260 8261 8262
my_bool
mysqld_get_one_option(int optid,
                      const struct my_option *opt __attribute__((unused)),
                      char *argument)
unknown's avatar
unknown committed
8263
{
8264 8265
  switch(optid) {
  case '#':
8266
#ifndef DBUG_OFF
8267 8268 8269
    if (!argument)
      argument= (char*) default_dbug_option;
    if (argument[0] == '0' && !argument[1])
unknown's avatar
unknown committed
8270 8271 8272 8273
    {
      DEBUGGER_OFF;
      break;
    }
8274
    DEBUGGER_ON;
8275
    if (argument[0] == '1' && !argument[1])
unknown's avatar
unknown committed
8276
      break;
8277
    DBUG_SET_INITIAL(argument);
8278
    opt_endinfo=1;				/* unireg: memory allocation */
8279 8280
#else
    sql_print_warning("'%s' is disabled in this build", opt->name);
8281
#endif
8282
    break;
8283
  case OPT_DEPRECATED_OPTION:
Sergei Golubchik's avatar
Sergei Golubchik committed
8284 8285
    sql_print_warning("'%s' is deprecated. It does nothing and exists only "
                      "for compatiblity with old my.cnf files.",
8286 8287
                      opt->name);
    break;
8288 8289 8290 8291 8292 8293 8294 8295
  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;
8296
  case 'a':
8297
    global_system_variables.sql_mode= MODE_ANSI;
unknown's avatar
unknown committed
8298
    global_system_variables.tx_isolation= ISO_SERIALIZABLE;
8299 8300
    break;
  case 'b':
8301
    strmake_buf(mysql_home, argument);
8302
    break;
8303
  case 'C':
8304 8305
    if (default_collation_name == compiled_default_collation_name)
      default_collation_name= 0;
8306
    break;
8307
  case 'h':
8308
    strmake_buf(mysql_real_data_home, argument);
8309
    /* Correct pointer set by my_getopt (for embedded library) */
8310
    mysql_real_data_home_ptr= mysql_real_data_home;
8311
    break;
8312
  case 'u':
8313
    if (!mysqld_user || !strcmp(mysqld_user, argument))
unknown's avatar
unknown committed
8314
      mysqld_user= argument;
8315
    else
8316
      sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
8317
    break;
8318
  case 'L':
8319
    strmake_buf(lc_messages_dir, argument);
8320
    break;
8321 8322
  case OPT_BINLOG_FORMAT:
    binlog_format_used= true;
8323
    break;
8324
#include <sslopt-case.h>
8325
#ifndef EMBEDDED_LIBRARY
8326 8327
  case 'V':
    print_version();
8328 8329
    opt_abort= 1;                    // Abort after parsing all options
    break;
8330
#endif /*EMBEDDED_LIBRARY*/
8331 8332 8333 8334 8335 8336 8337 8338
  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;
8339 8340 8341 8342 8343 8344 8345 8346
  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:
8347
    opt_bin_log= test(argument != disabled_my_option);
8348
    opt_bin_log_used= 1;
8349
    break;
8350 8351 8352 8353 8354 8355 8356 8357
  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
8358 8359
    if (log_error_file_ptr != disabled_my_option)
      log_error_file_ptr= opt_log_basename;
8360

Sergei Golubchik's avatar
Sergei Golubchik committed
8361 8362 8363 8364 8365 8366
    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);
8367 8368 8369 8370 8371 8372 8373

    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
8374
        ! opt_slow_logname || !pidfile_name_ptr)
8375 8376 8377
      return 1;                                 // out of memory error
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8378
#ifdef HAVE_REPLICATION
8379
  case (int)OPT_REPLICATE_IGNORE_DB:
8380
  {
8381
    cur_rpl_filter->add_ignore_db(argument);
8382 8383 8384 8385
    break;
  }
  case (int)OPT_REPLICATE_DO_DB:
  {
8386
    cur_rpl_filter->add_do_db(argument);
8387 8388 8389 8390
    break;
  }
  case (int)OPT_REPLICATE_REWRITE_DB:
  {
8391
    /* See also OPT_REWRITE_DB handling in client/mysqlbinlog.cc */
8392
    char* key = argument,*p, *val;
8393

8394
    if (!(p= strstr(argument, "->")))
8395
    {
8396 8397
      sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
      return 1;
8398
    }
8399
    val= p--;
unknown's avatar
unknown committed
8400
    while (my_isspace(mysqld_charset, *p) && p > argument)
8401 8402
      *p-- = 0;
    if (p == argument)
8403
    {
8404 8405
      sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
      return 1;
8406
    }
8407 8408
    *val= 0;
    val+= 2;
unknown's avatar
unknown committed
8409
    while (*val && my_isspace(mysqld_charset, *val))
8410
      val++;
8411
    if (!*val)
8412
    {
8413 8414
      sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
      return 1;
8415 8416
    }

8417
    cur_rpl_filter->add_db_rewrite(key, val);
8418 8419 8420
    break;
  }

8421
  case (int)OPT_BINLOG_IGNORE_DB:
8422
  {
8423
    binlog_filter->add_ignore_db(argument);
8424 8425
    break;
  }
8426
  case (int)OPT_BINLOG_DO_DB:
8427
  {
8428
    binlog_filter->add_do_db(argument);
8429 8430
    break;
  }
8431
  case (int)OPT_REPLICATE_DO_TABLE:
8432
  {
8433
    if (cur_rpl_filter->add_do_table(argument))
8434
    {
8435 8436
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
8437
    }
8438 8439
    break;
  }
8440
  case (int)OPT_REPLICATE_WILD_DO_TABLE:
8441
  {
8442
    if (cur_rpl_filter->add_wild_do_table(argument))
8443
    {
8444 8445
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
8446
    }
8447 8448
    break;
  }
8449
  case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
8450
  {
8451
    if (cur_rpl_filter->add_wild_ignore_table(argument))
8452
    {
8453 8454
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
8455
    }
8456 8457
    break;
  }
8458
  case (int)OPT_REPLICATE_IGNORE_TABLE:
8459
  {
8460
    if (cur_rpl_filter->add_ignore_table(argument))
8461
    {
8462 8463
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
8464
    }
8465 8466
    break;
  }
unknown's avatar
SCRUM  
unknown committed
8467
#endif /* HAVE_REPLICATION */
8468
  case (int) OPT_SAFE:
8469
    opt_specialflag|= SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC;
8470
    delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
8471 8472
    myisam_recover_options= HA_RECOVER_DEFAULT;
    ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
unknown's avatar
unknown committed
8473
#ifdef HAVE_QUERY_CACHE
8474 8475
    query_cache_size=0;
#endif
8476 8477
    sql_print_warning("The syntax '--safe-mode' is deprecated and will be "
                      "removed in a future release.");
8478 8479 8480 8481 8482
    break;
  case (int) OPT_SKIP_HOST_CACHE:
    opt_specialflag|= SPECIAL_NO_HOST_CACHE;
    break;
  case (int) OPT_SKIP_RESOLVE:
8483
    opt_skip_name_resolve= 1;
8484 8485 8486 8487 8488
    opt_specialflag|=SPECIAL_NO_RESOLVE;
    break;
  case (int) OPT_WANT_CORE:
    test_flags |= TEST_CORE_ON_SIGNAL;
    break;
8489 8490 8491 8492
  case OPT_CONSOLE:
    if (opt_console)
      opt_error_log= 0;			// Force logs to stdout
    break;
8493 8494 8495 8496 8497
  case OPT_BOOTSTRAP:
    opt_noacl=opt_bootstrap=1;
    break;
  case OPT_SERVER_ID:
    server_id_supplied = 1;
8498
    ::server_id= global_system_variables.server_id;
8499
    break;
unknown's avatar
unknown committed
8500
  case OPT_LOWER_CASE_TABLE_NAMES:
8501
    lower_case_table_names_used= 1;
unknown's avatar
unknown committed
8502
    break;
8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518
#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) */
8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530
  case OPT_ENGINE_CONDITION_PUSHDOWN:
    /*
      The last of --engine-condition-pushdown and --optimizer_switch on
      command line wins (see get_options().
    */
    if (global_system_variables.engine_condition_pushdown)
      global_system_variables.optimizer_switch|=
        OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
    else
      global_system_variables.optimizer_switch&=
        ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
    break;
8531 8532 8533 8534 8535 8536 8537 8538
  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;
8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552
  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;
8553 8554 8555 8556 8557 8558 8559

  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;
8560 8561 8562
  case OPT_MAX_LONG_DATA_SIZE:
    max_long_data_size_used= true;
    break;
8563 8564
  case OPT_PFS_INSTRUMENT:
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
8565
#ifndef EMBEDDED_LIBRARY
8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628
    /* 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;
    }
8629
#endif /* EMBEDDED_LIBRARY */
8630 8631
#endif
    break;
unknown's avatar
unknown committed
8632
  }
8633 8634
  return 0;
}
8635

8636

unknown's avatar
unknown committed
8637
/** Handle arguments for multiple key caches. */
8638

8639
C_MODE_START
8640

8641
static void*
8642
mysql_getopt_value(const char *name, uint length,
8643
		   const struct my_option *option, int *error)
8644
{
8645 8646
  if (error)
    *error= 0;
8647 8648
  switch (option->id) {
  case OPT_KEY_BUFFER_SIZE:
unknown's avatar
unknown committed
8649
  case OPT_KEY_CACHE_BLOCK_SIZE:
8650 8651
  case OPT_KEY_CACHE_DIVISION_LIMIT:
  case OPT_KEY_CACHE_AGE_THRESHOLD:
8652
  case OPT_KEY_CACHE_PARTITIONS:
8653
  {
unknown's avatar
unknown committed
8654
    KEY_CACHE *key_cache;
8655
    if (!(key_cache= get_or_create_key_cache(name, length)))
8656 8657 8658 8659 8660
    {
      if (error)
        *error= EXIT_OUT_OF_MEMORY;
      return 0;
    }
8661 8662
    switch (option->id) {
    case OPT_KEY_BUFFER_SIZE:
8663
      return &key_cache->param_buff_size;
8664
    case OPT_KEY_CACHE_BLOCK_SIZE:
8665
      return &key_cache->param_block_size;
8666
    case OPT_KEY_CACHE_DIVISION_LIMIT:
8667
      return &key_cache->param_division_limit;
8668
    case OPT_KEY_CACHE_AGE_THRESHOLD:
8669
      return &key_cache->param_age_threshold;
8670 8671
    case OPT_KEY_CACHE_PARTITIONS:
      return (uchar**) &key_cache->param_partitions;
8672
    }
8673
  }
8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689
  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;
  }
8690
  }
8691
  return option->value;
8692 8693
}

8694
static void option_error_reporter(enum loglevel level, const char *format, ...)
unknown's avatar
unknown committed
8695
{
8696
  va_list args;
unknown's avatar
unknown committed
8697
  va_start(args, format);
8698 8699 8700 8701 8702 8703 8704

  /* 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
8705
  va_end(args);
unknown's avatar
unknown committed
8706
}
8707

8708
C_MODE_END
unknown's avatar
unknown committed
8709

unknown's avatar
unknown committed
8710
/**
Marc Alff's avatar
Marc Alff committed
8711 8712 8713 8714 8715 8716
  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
8717 8718 8719
  @todo
  - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
*/
Marc Alff's avatar
Marc Alff committed
8720
static int get_options(int *argc_ptr, char ***argv_ptr)
8721 8722 8723
{
  int ho_error;

8724
  my_getopt_register_get_addr(mysql_getopt_value);
8725
  my_getopt_error_reporter= option_error_reporter;
unknown's avatar
unknown committed
8726

Marc Alff's avatar
Marc Alff committed
8727 8728 8729
  /* prepare all_options array */
  my_init_dynamic_array(&all_options, sizeof(my_option),
                        array_elements(my_long_options),
8730
                        array_elements(my_long_options)/4, MYF(0));
8731
  add_many_options(&all_options, my_long_options, array_elements(my_long_options));
8732
  sys_var_add_options(&all_options, 0);
Marc Alff's avatar
Marc Alff committed
8733
  add_terminator(&all_options);
8734

unknown's avatar
unknown committed
8735 8736 8737
  /* Skip unknown options so that they may be processed later by plugins */
  my_getopt_skip_unknown= TRUE;

Marc Alff's avatar
Marc Alff committed
8738
  if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer),
8739
                                mysqld_get_one_option)))
8740
    return ho_error;
8741 8742 8743

  if (!opt_help)
    delete_dynamic(&all_options);
8744 8745
  else
    opt_abort= 1;
8746

Marc Alff's avatar
Marc Alff committed
8747 8748 8749
  /* Add back the program name handle_options removes */
  (*argc_ptr)++;
  (*argv_ptr)--;
8750

8751 8752 8753 8754 8755 8756
  /*
    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.
  */
8757

8758 8759
  if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
       opt_log_slow_slave_statements) &&
8760
      !opt_slow_log)
8761
    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");
8762 8763 8764 8765 8766 8767 8768 8769
  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);
  }
8770

8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789
  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
8790
    mysqld_port= mysqld_extra_port= 0;
8791

8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807
  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;

8808 8809 8810 8811 8812 8813
  // 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;
8814 8815 8816

  global_system_variables.sql_mode=
    expand_sql_mode(global_system_variables.sql_mode);
Sergei Golubchik's avatar
Sergei Golubchik committed
8817
#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH)
8818 8819 8820 8821 8822 8823 8824 8825 8826 8827
  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
8828 8829 8830
  if (opt_debugging)
  {
    /* Allow break with SIGINT, no core or stack trace */
Michael Widenius's avatar
Michael Widenius committed
8831 8832
    test_flags|= TEST_SIGINT;
    opt_stack_trace= 1;
8833 8834
    test_flags&= ~TEST_CORE_ON_SIGNAL;
  }
8835
  /* Set global MyISAM variables from delay_key_write_options */
8836
  fix_delay_key_write(0, 0, OPT_GLOBAL);
8837

8838
#ifndef EMBEDDED_LIBRARY
8839 8840
  if (mysqld_chroot)
    set_root(mysqld_chroot);
8841
#else
8842
  thread_handling = SCHEDULER_NO_THREADS;
8843 8844
  max_allowed_packet= global_system_variables.max_allowed_packet;
  net_buffer_length= global_system_variables.net_buffer_length;
8845
#endif
8846 8847
  if (fix_paths())
    return 1;
unknown's avatar
unknown committed
8848

unknown's avatar
unknown committed
8849 8850 8851 8852
  /*
    Set some global variables from the global_system_variables
    In most cases the global variables will not be used
  */
8853
  my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
unknown's avatar
unknown committed
8854
  my_default_record_cache_size=global_system_variables.read_buff_size;
unknown's avatar
unknown committed
8855

8856
  /*
8857 8858 8859
    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.
8860 8861 8862 8863 8864 8865
  */
  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;
8866 8867
  if (my_assert_on_error)
    debug_assert_if_crashed_table= 1;
8868

8869 8870
  global_system_variables.long_query_time= (ulonglong)
    (global_system_variables.long_query_time_double * 1e6);
8871

8872 8873
  if (opt_short_log_format)
    opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
8874

8875
  if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
8876
                                  &global_date_format) ||
8877
      init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
8878
                                  &global_time_format) ||
8879
      init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
8880
                                  &global_datetime_format))
8881
    return 1;
8882

unknown's avatar
unknown committed
8883
#ifdef EMBEDDED_LIBRARY
Sergei Golubchik's avatar
Sergei Golubchik committed
8884 8885
  one_thread_scheduler(thread_scheduler);
  one_thread_scheduler(extra_thread_scheduler);
unknown's avatar
unknown committed
8886
#else
8887 8888 8889 8890 8891 8892 8893 8894

#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

8895
  if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
Sergei Golubchik's avatar
Sergei Golubchik committed
8896
    one_thread_per_connection_scheduler(thread_scheduler, &max_connections,
8897
                                        &connection_count);
8898
  else if (thread_handling == SCHEDULER_NO_THREADS)
Sergei Golubchik's avatar
Sergei Golubchik committed
8899
    one_thread_scheduler(thread_scheduler);
unknown's avatar
unknown committed
8900
  else
8901 8902 8903
    pool_of_threads_scheduler(thread_scheduler,  &max_connections,
                                        &connection_count); 

Sergei Golubchik's avatar
Sergei Golubchik committed
8904
  one_thread_per_connection_scheduler(extra_thread_scheduler,
8905 8906
                                      &extra_max_connections,
                                      &extra_connection_count);
unknown's avatar
unknown committed
8907
#endif
8908 8909 8910 8911 8912

  global_system_variables.engine_condition_pushdown=
    test(global_system_variables.optimizer_switch &
         OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN);

8913 8914
  opt_readonly= read_only;

8915 8916 8917 8918 8919 8920 8921
  /*
    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;

8922
  /* Remember if max_user_connections was 0 at startup */
Sergei Golubchik's avatar
Sergei Golubchik committed
8923
  max_user_connections_checking= global_system_variables.max_user_connections != 0;
8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937

  {
    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).
    */
    max_relay_log_size_var= intern_find_sys_var("max_relay_log_size", 0);
    max_binlog_size_var= intern_find_sys_var("max_binlog_size", 0);
Sergei Golubchik's avatar
Sergei Golubchik committed
8938 8939 8940 8941 8942 8943 8944
    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;
    }
8945
  }
8946 8947 8948 8949 8950 8951 8952

  /* 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;
  
8953
  return 0;
unknown's avatar
unknown committed
8954 8955 8956
}


8957 8958 8959 8960 8961 8962 8963
/*
  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
8964
void set_server_version(void)
8965 8966
{
  char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
8967
                     MYSQL_SERVER_SUFFIX_STR, NullS);
8968 8969 8970 8971
#ifdef EMBEDDED_LIBRARY
  end= strmov(end, "-embedded");
#endif
#ifndef DBUG_OFF
8972
  if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
8973 8974
    end= strmov(end, "-debug");
#endif
8975
  if (opt_log || opt_slow_log || opt_bin_log)
8976 8977 8978 8979
    strmov(end, "-log");                        // This may slow down system
}


unknown's avatar
unknown committed
8980 8981 8982
static char *get_relative_path(const char *path)
{
  if (test_if_hard_path(path) &&
8983
      is_prefix(path,DEFAULT_MYSQL_HOME) &&
unknown's avatar
unknown committed
8984 8985
      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
  {
unknown's avatar
unknown committed
8986
    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
8987
    while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
unknown's avatar
unknown committed
8988 8989 8990 8991 8992 8993
      path++;
  }
  return (char*) path;
}


unknown's avatar
unknown committed
8994
/**
8995 8996
  Fix filename and replace extension where 'dir' is relative to
  mysql_real_data_home.
unknown's avatar
unknown committed
8997 8998
  @return
    1 if len(path) > FN_REFLEN
8999 9000 9001
*/

bool
9002
fn_format_relative_to_data_home(char * to, const char *name,
9003 9004 9005 9006 9007 9008 9009 9010 9011 9012
				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,
9013
		    MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
9014 9015 9016
}


9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030
/**
  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];
9031
  size_t opt_secure_file_priv_len;
9032 9033 9034 9035 9036 9037
  /*
    All paths are secure if opt_secure_file_path is 0
  */
  if (!opt_secure_file_priv)
    return TRUE;

9038 9039
  opt_secure_file_priv_len= strlen(opt_secure_file_priv);

Georgi Kodinov's avatar
Georgi Kodinov committed
9040 9041 9042
  if (strlen(path) >= FN_REFLEN)
    return FALSE;

9043 9044 9045 9046 9047
  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
9048
    size_t length= dirname_length(path);        // Guaranteed to be < FN_REFLEN
9049 9050 9051 9052 9053 9054
    memcpy(buff2, path, length);
    buff2[length]= '\0';
    if (length == 0 || my_realpath(buff1, buff2, 0))
      return FALSE;
  }
  convert_dirname(buff2, buff1, NullS);
9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068
  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;
  }
9069 9070 9071
  return TRUE;
}

Michael Widenius's avatar
Michael Widenius committed
9072

9073
static int fix_paths(void)
unknown's avatar
unknown committed
9074
{
9075
  char buff[FN_REFLEN],*pos;
9076 9077
  DBUG_ENTER("fix_paths");

9078
  convert_dirname(mysql_home,mysql_home,NullS);
9079
  /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
9080
  my_realpath(mysql_home,mysql_home,MYF(0));
9081 9082 9083 9084 9085 9086 9087
  /* Ensure that mysql_home ends in FN_LIBCHAR */
  pos=strend(mysql_home);
  if (pos[-1] != FN_LIBCHAR)
  {
    pos[0]= FN_LIBCHAR;
    pos[1]= 0;
  }
9088
  convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
9089
  convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
unknown's avatar
unknown committed
9090 9091
  (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);
9092
  (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
Marc Alff's avatar
Marc Alff committed
9093

Sergei Golubchik's avatar
Sergei Golubchik committed
9094 9095 9096
  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);
9097
  opt_plugin_dir_ptr= opt_plugin_dir;
Sergei Golubchik's avatar
Sergei Golubchik committed
9098
  pidfile_name_ptr= pidfile_name;
unknown's avatar
unknown committed
9099

9100 9101 9102 9103 9104 9105
  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
9106
  char *sharedir=get_relative_path(SHAREDIR);
unknown's avatar
unknown committed
9107
  if (test_if_hard_path(sharedir))
9108
    strmake_buf(buff, sharedir);		/* purecov: tested */
unknown's avatar
unknown committed
9109
  else
unknown's avatar
unknown committed
9110
    strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
9111
  convert_dirname(buff,buff,NullS);
9112
  (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
unknown's avatar
unknown committed
9113 9114

  /* If --character-sets-dir isn't given, use shared library dir */
9115
  if (charsets_dir)
9116
    strmake_buf(mysql_charsets_dir, charsets_dir);
9117
  else
unknown's avatar
unknown committed
9118 9119
    strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
	     CHARSET_DIR, NullS);
unknown's avatar
unknown committed
9120
  (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
9121
  convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
unknown's avatar
unknown committed
9122
  charsets_dir=mysql_charsets_dir;
unknown's avatar
unknown committed
9123

unknown's avatar
unknown committed
9124
  if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
9125
    DBUG_RETURN(1);
9126 9127
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir= mysql_tmpdir;
unknown's avatar
SCRUM  
unknown committed
9128
#ifdef HAVE_REPLICATION
9129
  if (!slave_load_tmpdir)
9130
    slave_load_tmpdir= mysql_tmpdir;
9131
#endif /* HAVE_REPLICATION */
9132 9133 9134
  /*
    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
9135
  */
9136 9137
  if (opt_secure_file_priv)
  {
9138 9139
    if (*opt_secure_file_priv == 0)
    {
9140
      my_free(opt_secure_file_priv);
9141 9142 9143 9144
      opt_secure_file_priv= 0;
    }
    else
    {
9145 9146
      if (strlen(opt_secure_file_priv) >= FN_REFLEN)
        opt_secure_file_priv[FN_REFLEN-1]= '\0';
9147
      if (my_realpath(buff, opt_secure_file_priv, 0))
9148 9149
      {
        sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
9150
        DBUG_RETURN(1);
9151
      }
9152
      char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
9153
      convert_dirname(secure_file_real_path, buff, NullS);
9154
      my_free(opt_secure_file_priv);
9155 9156
      opt_secure_file_priv= secure_file_real_path;
    }
9157
  }
9158
  DBUG_RETURN(0);
unknown's avatar
unknown committed
9159 9160
}

unknown's avatar
unknown committed
9161 9162
/**
  Check if file system used for databases is case insensitive.
9163

unknown's avatar
unknown committed
9164
  @param dir_name			Directory to test
9165

9166 9167 9168
  @retval -1  Don't know (Test failed)
  @retval  0   File system is case sensitive
  @retval  1   File system is case insensitive
9169 9170 9171 9172 9173 9174 9175 9176
*/

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;
9177
  DBUG_ENTER("test_if_case_insensitive");
9178 9179 9180 9181 9182

  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
9183 9184 9185
  mysql_file_delete(key_file_casetest, buff2, MYF(0));
  if ((file= mysql_file_create(key_file_casetest,
                               buff, 0666, O_RDWR, MYF(0))) < 0)
9186
  {
9187
    if (!opt_abort)
9188
      sql_print_warning("Can't create test file %s", buff);
9189
    DBUG_RETURN(-1);
9190
  }
Marc Alff's avatar
Marc Alff committed
9191 9192
  mysql_file_close(file, MYF(0));
  if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
9193
    result= 1;					// Can access file
Marc Alff's avatar
Marc Alff committed
9194
  mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
9195 9196
  DBUG_PRINT("exit", ("result: %d", result));
  DBUG_RETURN(result);
9197 9198 9199
}


9200 9201
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
9202 9203 9204
/**
  Create file to store pid number.
*/
9205 9206 9207
static void create_pid_file()
{
  File file;
Marc Alff's avatar
Marc Alff committed
9208 9209
  if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
                               O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
9210
  {
9211
    char buff[MAX_BIGINT_WIDTH + 1], *end;
9212
    end= int10_to_str((long) getpid(), buff, 10);
unknown's avatar
unknown committed
9213
    *end++= '\n';
Marc Alff's avatar
Marc Alff committed
9214 9215
    if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
                          MYF(MY_WME | MY_NABP)))
9216
    {
Marc Alff's avatar
Marc Alff committed
9217
      mysql_file_close(file, MYF(0));
9218
      pid_file_created= true;
9219 9220
      return;
    }
Marc Alff's avatar
Marc Alff committed
9221
    mysql_file_close(file, MYF(0));
9222
  }
9223
  sql_perror("Can't start server: can't create PID file");
unknown's avatar
foo1  
unknown committed
9224
  exit(1);
9225
}
9226
#endif /* EMBEDDED_LIBRARY */
9227

Marc Alff's avatar
Marc Alff committed
9228

9229 9230 9231 9232 9233
/**
  Remove the process' pid file.
  
  @param  flags  file operation flags
*/
Marc Alff's avatar
Marc Alff committed
9234

9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245
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
9246 9247


unknown's avatar
unknown committed
9248
/** Clear most status variables. */
9249 9250
void refresh_status(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
9251
  mysql_mutex_lock(&LOCK_status);
9252

9253
  /* Add thread's status variabes to global status */
9254
  add_to_status(&global_status_var, &thd->status_var);
9255 9256

  /* Reset thread's status variables */
9257
  thd->set_status_var_init();
9258 9259
  bzero((uchar*) &thd->org_status_var, sizeof(thd->org_status_var)); 
  thd->start_bytes_received= 0;
9260

9261
  /* Reset some global variables */
unknown's avatar
unknown committed
9262
  reset_status_vars();
9263

9264
  /* Reset the counters of all key caches (default and named). */
9265
  process_key_caches(reset_key_cache_counters, 0);
9266
  flush_status_time= time((time_t*) 0);
Marc Alff's avatar
Marc Alff committed
9267
  mysql_mutex_unlock(&LOCK_status);
9268 9269 9270

  /*
    Set max_used_connections to the number of currently open
Michael Widenius's avatar
Michael Widenius committed
9271
    connections.  This is not perfect, but status data is not exact anyway.
9272 9273
  */
  max_used_connections= thread_count-delayed_insert_threads;
9274 9275
}

Sergei Golubchik's avatar
Sergei Golubchik committed
9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308
#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
9309 9310
  { &key_file_init, "init", 0},
  { &key_file_binlog_state, "binlog_state", 0}
Sergei Golubchik's avatar
Sergei Golubchik committed
9311 9312 9313
};
#endif /* HAVE_PSI_INTERFACE */

9314 9315
PSI_stage_info stage_after_create= { 0, "After create", 0};
PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
9316 9317 9318
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};
9319 9320 9321 9322 9323 9324 9325 9326
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
9327
PSI_stage_info stage_converting_heap_to_myisam= { 0, "converting HEAP to " TMP_ENGINE_NAME, 0};
9328 9329 9330 9331 9332 9333 9334 9335 9336 9337
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
9338
PSI_stage_info stage_enabling_keys= { 0, "enabling keys", 0};
9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378
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};
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};
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
9379
PSI_stage_info stage_show_explain= { 0, "show explain", 0};
9380
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
9381
PSI_stage_info stage_sorting= { 0, "Sorting", 0};
9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419
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};
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};
9420 9421 9422
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};
9423
PSI_stage_info stage_waiting_for_work_from_sql_thread= { 0, "Waiting for work from SQL thread", 0};
9424

9425
#ifdef HAVE_PSI_INTERFACE
9426

9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449
PSI_stage_info *all_server_stages[]=
{
  & stage_after_create,
  & stage_allocating_local_table,
  & 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,
  & stage_copying_to_group_table,
  & stage_copying_to_tmp_table,
  & stage_copy_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
9450
  & stage_enabling_keys,
9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491
  & stage_end,
  & stage_executing,
  & stage_execution_of_init_command,
  & stage_explaining,
  & 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,
  & 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,
  & stage_slave_has_read_all_relay_log,
Sergei Golubchik's avatar
Sergei Golubchik committed
9492
  & stage_show_explain,
Sergei Golubchik's avatar
Sergei Golubchik committed
9493
  & stage_sorting,
9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543
  & 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,
  & 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,
  & 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,
  & stage_waiting_for_slave_mutex_on_exit,
  & stage_waiting_for_slave_thread_to_start,
  & stage_waiting_for_table_flush,
  & stage_waiting_for_query_cache_lock,
  & stage_waiting_for_the_next_event_in_relay_log,
  & stage_waiting_for_the_slave_thread_to_advance_position,
  & stage_waiting_to_finalize_termination,
  & stage_waiting_to_get_readlock
};

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
9544

9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 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
  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();
  count= array_elements(com_statement_info);
  mysql_statement_register(category, com_statement_info, count);

  /*
    When a new packet is received,
    it is instrumented as "statement/com/".
    Based on the packet type found, it later mutates to the
    proper narrow type, for example
    "statement/com/query" or "statement/com/ping".
    In cases of "statement/com/query", SQL queries are given to
    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;
  stmt_info_new_packet.m_name= "";
  stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE;
  mysql_statement_register(category, & stmt_info_new_packet, 1);
unknown's avatar
unknown committed
9590
#endif
9591
}
Marc Alff's avatar
Marc Alff committed
9592

9593
#endif /* HAVE_PSI_INTERFACE */