mysqld.cc 268 KB
Newer Older
Marc Alff's avatar
Marc Alff committed
1
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
2

unknown's avatar
unknown committed
3 4
   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
5
   the Free Software Foundation; version 2 of the License.
6

unknown's avatar
unknown committed
7 8 9 10
   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.
11

unknown's avatar
unknown committed
12 13 14 15 16 17
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "mysql_priv.h"
#include <m_ctype.h>
18
#include <my_dir.h>
19
#include <my_bit.h>
20
#include "slave.h"
21
#include "rpl_mi.h"
22
#include "sql_repl.h"
unknown's avatar
unknown committed
23
#include "rpl_filter.h"
24
#include "repl_failsafe.h"
25
#include <my_stacktrace.h>
26
#include "mysqld_suffix.h"
unknown's avatar
Merge  
unknown committed
27
#include "mysys_err.h"
28
#include "events.h"
Sergey Vojtovich's avatar
Sergey Vojtovich committed
29
#include "sql_audit.h"
30
#include "probes_mysql.h"
Ingo Struewing's avatar
Ingo Struewing committed
31
#include "debug_sync.h"
Marc Alff's avatar
Marc Alff committed
32 33 34 35 36

#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
#include "../storage/perfschema/pfs_server.h"
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */

37
#include "keycaches.h"
38
#include "../storage/myisam/ha_myisam.h"
39
#include "set_var.h"
40

41 42
#include "rpl_injector.h"

He Zhenxing's avatar
He Zhenxing committed
43 44
#include "rpl_handler.h"

45 46
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
47 48
#endif

unknown's avatar
unknown committed
49 50
#include <thr_alarm.h>
#include <ft_global.h>
51
#include <errmsg.h>
unknown's avatar
Merge  
unknown committed
52 53
#include "sp_rcontext.h"
#include "sp_cache.h"
unknown's avatar
unknown committed
54

55 56 57 58
#ifdef HAVE_POLL_H
#include <poll.h>
#endif

unknown's avatar
unknown committed
59
#define mysqld_charset &my_charset_latin1
unknown's avatar
unknown committed
60

61
/* stack traces are only supported on linux intel */
62 63 64 65 66 67
#if defined(__linux__)  && defined(__i386__) && defined(USE_PSTACK)
#define	HAVE_STACK_TRACE_ON_SEGV
#include "../pstack/pstack.h"
char pstack_file_name[80];
#endif /* __linux__ */

68 69 70
/* We have HAVE_purify below as this speeds up the shutdown of MySQL */

#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
unknown's avatar
unknown committed
71
#define HAVE_CLOSE_SERVER_SOCK 1
72
#endif
unknown's avatar
unknown committed
73

unknown's avatar
unknown committed
74 75 76 77
extern "C" {					// Because of SCO 3.2V4.2
#include <errno.h>
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
78
#define __GNU_LIBRARY__				// Skip warnings in getopt.h
unknown's avatar
unknown committed
79
#endif
80
#include <my_getopt.h>
unknown's avatar
unknown committed
81 82 83 84 85 86 87 88 89
#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
90
#include <my_net.h>
unknown's avatar
unknown committed
91

92
#if !defined(__WIN__)
unknown's avatar
unknown committed
93
#  ifndef __NETWARE__
unknown's avatar
unknown committed
94
#include <sys/resource.h>
unknown's avatar
unknown committed
95
#  endif /* __NETWARE__ */
unknown's avatar
unknown committed
96 97 98 99 100 101 102 103 104 105
#ifdef HAVE_SYS_UN_H
#  include <sys/un.h>
#endif
#ifdef HAVE_SELECT_H
#  include <select.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/utsname.h>
unknown's avatar
unknown committed
106
#endif /* __WIN__ */
unknown's avatar
unknown committed
107

108
#include <my_libwrap.h>
unknown's avatar
unknown committed
109

110 111 112 113
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

114 115 116 117 118 119 120
#ifdef __WIN__ 
#include <crtdbg.h>
#define SIGNAL_FMT "exception 0x%x"
#else
#define SIGNAL_FMT "signal %d"
#endif

121 122 123 124 125 126 127 128 129 130
#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
Merge  
unknown committed
131
#ifdef __NETWARE__
unknown's avatar
unknown committed
132 133 134 135
#define zVOLSTATE_ACTIVE 6
#define zVOLSTATE_DEACTIVE 2
#define zVOLSTATE_MAINTENANCE 3

unknown's avatar
unknown committed
136 137 138 139 140 141 142
#undef __event_h__
#include <../include/event.h>
/*
  This #undef exists here because both libc of NetWare and MySQL have
  files named event.h which causes compilation errors.
*/

143
#include <nks/netware.h>
unknown's avatar
unknown committed
144 145 146
#include <nks/vm.h>
#include <library.h>
#include <monitor.h>
unknown's avatar
unknown committed
147 148 149 150 151 152
#include <zOmni.h>                              //For NEB
#include <neb.h>                                //For NEB
#include <nebpub.h>                             //For NEB
#include <zEvent.h>                             //For NSS event structures
#include <zPublics.h>

153 154 155
static void *neb_consumer_id= NULL;             //For storing NEB consumer id
static char datavolname[256]= {0};
static VolumeID_t datavolid;
unknown's avatar
unknown committed
156 157
static event_handle_t eh;
static Report_t ref;
158
static void *refneb= NULL;
159
my_bool event_flag= FALSE;
160
static int volumeid= -1;
unknown's avatar
unknown committed
161 162 163

  /* NEB event callback */
unsigned long neb_event_callback(struct EventBlock *eblock);
164 165 166
static void registerwithneb();
static void getvolumename();
static void getvolumeID(BYTE *volumeName);
unknown's avatar
unknown committed
167
#endif /* __NETWARE__ */
168

unknown's avatar
unknown committed
169

unknown's avatar
unknown committed
170
#ifdef _AIX41
unknown's avatar
unknown committed
171
int initgroups(const char *,unsigned int);
unknown's avatar
unknown committed
172 173
#endif

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

200
inline void setup_fpu()
unknown's avatar
unknown committed
201
{
202
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
unknown's avatar
unknown committed
203
  /* We can't handle floating point exceptions with threads, so disable
unknown's avatar
unknown committed
204
     this on freebsd
205
     Don't fall for overflow, underflow,divide-by-zero or loss of precision
unknown's avatar
unknown committed
206
  */
unknown's avatar
unknown committed
207 208 209
#if defined(__i386__)
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
	      FP_X_IMP));
unknown's avatar
unknown committed
210
#else
211 212 213 214
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
              FP_X_IMP));
#endif /* __i386__ */
#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
215

216 217 218 219
#ifdef HAVE_FESETROUND
    /* Set FPU rounding mode to "round-to-nearest" */
  fesetround(FE_TONEAREST);
#endif /* HAVE_FESETROUND */
220 221

  /*
222 223 224 225
    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.
226
  */
227
#if defined(__i386__) && !defined(__SSE2_MATH__)
228 229 230 231 232 233 234 235 236 237 238 239
#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__ */

240
#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
241
  /* Enable denormalized DOUBLE values support for IRIX */
242 243 244 245 246
  union fpc_csr n;
  n.fc_word = get_fpc_csr();
  n.fc_struct.flush = 0;
  set_fpc_csr(n.fc_word);
#endif
247
}
unknown's avatar
unknown committed
248

unknown's avatar
unknown committed
249 250
} /* cplusplus */

unknown's avatar
unknown committed
251
#define MYSQL_KILL_SIGNAL SIGTERM
unknown's avatar
unknown committed
252 253 254 255 256 257 258 259 260 261 262

#ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
#include <sys/types.h>
#else
#include <my_pthread.h>			// For thr_setconcurency()
#endif

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

263
extern "C" sig_handler handle_segfault(int sig);
264

265 266 267
#if defined(__linux__)
#define ENABLE_TEMP_POOL 1
#else
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
268
#define ENABLE_TEMP_POOL 0
269 270
#endif

unknown's avatar
unknown committed
271
/* Constants */
272

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

unknown's avatar
unknown committed
275 276 277 278 279 280 281 282 283
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
284

unknown's avatar
unknown committed
285
const char *first_keyword= "first", *binary_keyword= "BINARY";
unknown's avatar
SCRUM:  
unknown committed
286
const char *my_localhost= "localhost", *delayed_user= "DELAYED";
287

unknown's avatar
unknown committed
288
bool opt_large_files= sizeof(my_off_t) > 4;
289 290 291 292

/*
  Used with --help for detailed option
*/
293
static my_bool opt_help= 0, opt_verbose= 0;
294

unknown's avatar
Merge  
unknown committed
295
arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
296 297 298
{{&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
299 300
 {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
 {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
unknown's avatar
unknown committed
301

302 303
const char *log_output_names[] = { "NONE", "FILE", "TABLE", NullS};
static const unsigned int log_output_names_len[]= { 4, 4, 5, 0 };
304
TYPELIB log_output_typelib= {array_elements(log_output_names)-1,"",
305 306
                             log_output_names, 
                             (unsigned int *) log_output_names_len};
307

unknown's avatar
unknown committed
308 309
/* static variables */

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

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

333
/* the default log output is log tables */
unknown's avatar
unknown committed
334 335 336 337 338 339
static bool lower_case_table_names_used= 0;
static bool volatile select_thread_in_use, signal_thread_in_use;
static bool volatile ready_to_exit;
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;
340
static ulong killed_threads;
unknown's avatar
unknown committed
341 342
static ulong max_used_connections;
static volatile ulong cached_thread_count= 0;
343
static char *mysqld_user, *mysqld_chroot;
unknown's avatar
unknown committed
344
static char *default_character_set_name;
unknown's avatar
unknown committed
345
static char *character_set_filesystem_name;
346
static char *lc_messages;
347
static char *lc_time_names_name;
unknown's avatar
unknown committed
348
static char *my_bind_addr_str;
349 350
static char *default_collation_name;
char *default_storage_engine;
351
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
unknown's avatar
unknown committed
352
static I_List<THD> thread_cache;
353 354 355
static bool binlog_format_used= false;

LEX_STRING opt_init_connect, opt_init_slave;
unknown's avatar
unknown committed
356

Marc Alff's avatar
Marc Alff committed
357
static mysql_cond_t COND_thread_cache, COND_flush_thread_cache;
unknown's avatar
unknown committed
358

unknown's avatar
unknown committed
359
/* Global variables */
unknown's avatar
unknown committed
360

361
bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0;
362
my_bool opt_log, opt_slow_log;
363
ulonglong log_output_options;
364
my_bool opt_log_queries_not_using_indexes= 0;
365
bool opt_error_log= IF_WIN(1,0);
unknown's avatar
unknown committed
366
bool opt_disable_networking=0, opt_skip_show_db=0;
367
my_bool opt_character_set_client_handshake= 1;
unknown's avatar
unknown committed
368
bool server_id_supplied = 0;
369
bool opt_endinfo, using_udf_functions;
370
my_bool locked_in_memory;
371
bool opt_using_transactions;
unknown's avatar
unknown committed
372
bool volatile abort_loop;
373
bool volatile shutdown_in_progress;
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
/*
  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;
389 390 391 392 393 394 395 396
/**
   @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.
   @note This flag is dropped in 5.1 
   @see grant_init()
 */
bool volatile grant_option;
unknown's avatar
unknown committed
397

unknown's avatar
unknown committed
398
my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
unknown's avatar
unknown committed
399
my_bool opt_reckless_slave = 0;
unknown's avatar
unknown committed
400 401
my_bool opt_enable_named_pipe= 0;
my_bool opt_local_infile, opt_slave_compressed_protocol;
402 403
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
404
my_bool opt_log_slave_updates= 0;
405 406 407 408 409 410 411
char *opt_slave_skip_errors;

/**
  compatibility option:
    - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
*/
my_bool old_mode;
412 413 414 415 416 417

/*
  Legacy global handlerton. These will be removed (please do not add more).
*/
handlerton *heap_hton;
handlerton *myisam_hton;
418
handlerton *partition_hton;
419

420
my_bool opt_readonly= 0, use_temp_pool, relay_log_purge;
421
my_bool relay_log_recovery;
unknown's avatar
unknown committed
422
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
423
my_bool opt_secure_auth= 0;
424
char* opt_secure_file_priv;
425
my_bool opt_log_slow_admin_statements= 0;
426
my_bool opt_log_slow_slave_statements= 0;
unknown's avatar
unknown committed
427
my_bool lower_case_file_system= 0;
428
my_bool opt_large_pages= 0;
429
my_bool opt_super_large_pages= 0;
unknown's avatar
unknown committed
430
my_bool opt_myisam_use_mmap= 0;
431
uint   opt_large_page_size= 0;
Ingo Struewing's avatar
Ingo Struewing committed
432 433 434
#if defined(ENABLED_DEBUG_SYNC)
uint    opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
435
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
unknown's avatar
Merge  
unknown committed
436 437 438 439 440
/*
  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
441
volatile bool mqh_used = 0;
442
my_bool opt_noacl;
unknown's avatar
Merge  
unknown committed
443
my_bool sp_automatic_privileges= 1;
444

445
ulong opt_binlog_rows_event_max_size;
unknown's avatar
unknown committed
446
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
447
TYPELIB binlog_format_typelib=
448
  { array_elements(binlog_format_names) - 1, "",
449
    binlog_format_names, NULL };
450
#ifdef HAVE_INITGROUPS
unknown's avatar
unknown committed
451
static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
452
#endif
453
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
454
uint mysqld_port_timeout;
455 456
uint delay_key_write_options;
uint protocol_version;
unknown's avatar
unknown committed
457
uint lower_case_table_names;
unknown's avatar
Merge  
unknown committed
458
uint tc_heuristic_recover= 0;
459
uint volatile thread_count;
460
int32 thread_running;
461
ulong thread_created;
462
ulong back_log, connect_timeout, concurrency, server_id;
unknown's avatar
unknown committed
463
ulong table_cache_size, table_def_size;
464
ulong what_to_log;
unknown's avatar
unknown committed
465
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
unknown's avatar
unknown committed
466
ulong open_files_limit, max_binlog_size, max_relay_log_size;
467
ulong slave_net_timeout, slave_trans_retries;
468
uint slave_exec_mode_options;
unknown's avatar
unknown committed
469
ulonglong slave_type_conversions_options;
unknown's avatar
unknown committed
470
ulong thread_cache_size=0, thread_pool_size= 0;
471 472
ulong binlog_cache_size=0;
ulonglong  max_binlog_cache_size=0;
473
ulong query_cache_size=0;
474
ulong refresh_version;  /* Increments on each reload */
475
query_id_t global_query_id;
476
my_atomic_rwlock_t global_query_id_lock;
477
my_atomic_rwlock_t thread_running_lock;
unknown's avatar
unknown committed
478
ulong aborted_threads, aborted_connects;
unknown's avatar
unknown committed
479 480
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
481
ulong delayed_insert_errors,flush_time;
unknown's avatar
Merge  
unknown committed
482
ulong specialflag=0;
483
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
unknown's avatar
unknown committed
484
ulong max_connections, max_connect_errors;
unknown's avatar
unknown committed
485
/**
486 487 488 489
  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
490
/**
491 492 493 494 495 496 497 498 499 500
  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
501
ulong thread_id=1L,current_pid;
502
ulong slow_launch_threads = 0;
503 504
uint sync_binlog_period= 0, sync_relaylog_period= 0,
     sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
unknown's avatar
unknown committed
505
ulong expire_logs_days = 0;
unknown's avatar
unknown committed
506 507
ulong rpl_recovery_rank=0;

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
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
};

542
time_t server_start_time, flush_status_time;
543

544
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
545
char default_logfile_name[FN_REFLEN];
546
char *default_tz_name;
unknown's avatar
unknown committed
547
char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
unknown's avatar
unknown committed
548
char mysql_real_data_home[FN_REFLEN],
549 550
     lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
     mysql_charsets_dir[FN_REFLEN],
551 552
     *opt_init_file, *opt_tc_log_file;
char *lc_messages_dir_ptr, *log_error_file_ptr;
553
char err_shared_dir[FN_REFLEN];
554
char mysql_unpacked_real_data_home[FN_REFLEN];
555
int mysql_unpacked_real_data_home_len;
556
uint mysql_real_data_home_len, mysql_data_home_len= 1;
557
uint reg_ext_length;
558 559 560
const key_map key_map_empty(0);
key_map key_map_full(0);                        // Will be initialized later

561 562
DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
Time_zone *default_tz;
563

564 565
char *mysql_data_home= const_cast<char*>(".");
const char *mysql_real_data_home_ptr= mysql_real_data_home;
566
char server_version[SERVER_VERSION_LENGTH];
567
char *mysqld_unix_port, *opt_mysql_tmpdir;
568
uint thread_handling;
569

570
/** name of reference on left expression in rewritten IN subquery */
571
const char *in_left_expr_name= "<left expr>";
unknown's avatar
unknown committed
572
/** name of additional condition */
573
const char *in_additional_cond= "<IN COND>";
574 575
const char *in_having_cond= "<IN HAVING>";

unknown's avatar
Merge  
unknown committed
576
my_decimal decimal_zero;
unknown's avatar
unknown committed
577 578 579 580 581 582 583 584
/* 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
585
MYSQL_FILE *bootstrap_file;
unknown's avatar
Merge  
unknown committed
586
int bootstrap_error;
587
FILE *stderror_file=0;
unknown's avatar
unknown committed
588

unknown's avatar
unknown committed
589
I_List<THD> threads;
unknown's avatar
unknown committed
590 591
Rpl_filter* rpl_filter;
Rpl_filter* binlog_filter;
unknown's avatar
unknown committed
592

unknown's avatar
unknown committed
593 594
struct system_variables global_system_variables;
struct system_variables max_system_variables;
unknown's avatar
Merge  
unknown committed
595
struct system_status_var global_status_var;
unknown's avatar
unknown committed
596

unknown's avatar
unknown committed
597
MY_TMPDIR mysql_tmpdir_list;
598
MY_BITMAP temp_pool;
unknown's avatar
unknown committed
599

600 601
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
unknown's avatar
unknown committed
602
CHARSET_INFO *character_set_filesystem;
Marc Alff's avatar
Marc Alff committed
603
CHARSET_INFO *error_message_charset_info;
604

605
MY_LOCALE *my_default_lc_messages;
606 607
MY_LOCALE *my_default_lc_time_names;

608
SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
609
SHOW_COMP_OPTION have_geometry, have_rtree_keys;
unknown's avatar
unknown committed
610
SHOW_COMP_OPTION have_crypt, have_compress;
611
SHOW_COMP_OPTION have_profiling;
unknown's avatar
unknown committed
612 613

/* Thread specific variables */
614

unknown's avatar
unknown committed
615
pthread_key(MEM_ROOT**,THR_MALLOC);
unknown's avatar
unknown committed
616
pthread_key(THD*, THR_THD);
Marc Alff's avatar
Marc Alff committed
617
mysql_mutex_t LOCK_thread_count;
Marc Alff's avatar
Marc Alff committed
618 619 620 621 622 623 624 625
mysql_mutex_t LOCK_mysql_create_db, LOCK_open,
  LOCK_mapped_file, LOCK_status, LOCK_global_read_lock,
  LOCK_error_log, LOCK_uuid_generator,
  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;
unknown's avatar
unknown committed
626
/**
627 628 629 630 631 632
  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
633
mysql_mutex_t LOCK_prepared_stmt_count;
634
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
635
mysql_mutex_t LOCK_des_key_file;
636
#endif
Marc Alff's avatar
Marc Alff committed
637 638
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
639
mysql_cond_t COND_thread_count;
Marc Alff's avatar
Marc Alff committed
640
mysql_cond_t COND_refresh, COND_global_read_lock;
unknown's avatar
unknown committed
641 642
pthread_t signal_thread;
pthread_attr_t connection_attrib;
Marc Alff's avatar
Marc Alff committed
643 644
mysql_mutex_t LOCK_server_started;
mysql_cond_t COND_server_started;
unknown's avatar
unknown committed
645 646

int mysqld_server_started= 0;
unknown's avatar
unknown committed
647

648 649
File_parser_dummy_hook file_parser_dummy_hook;

unknown's avatar
unknown committed
650 651 652
/* replication parameters, if master_host is not NULL, we are a slave */
uint report_port= MYSQL_PORT;
ulong master_retry_count=0;
653
char *master_info_file;
unknown's avatar
unknown committed
654
char *relay_log_info_file, *report_user, *report_password, *report_host;
unknown's avatar
unknown committed
655
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
656
char *opt_logname, *opt_slow_logname;
unknown's avatar
unknown committed
657 658 659 660

/* Static variables */

static bool kill_in_progress, segfaulted;
661 662 663 664
#ifdef HAVE_STACK_TRACE_ON_SEGV
static my_bool opt_do_pstack;
#endif /* HAVE_STACK_TRACE_ON_SEGV */
static my_bool opt_bootstrap, opt_myisam_log;
unknown's avatar
unknown committed
665
static int cleanup_done;
666
static ulong opt_specialflag;
667
static char *opt_update_logname, *opt_binlog_index_name;
668
char *mysql_home_ptr, *pidfile_name_ptr;
Marc Alff's avatar
Marc Alff committed
669
/** Initial command line arguments (count), after load_defaults().*/
unknown's avatar
WL#2936  
unknown committed
670
static int defaults_argc;
Marc Alff's avatar
Marc Alff committed
671 672 673 674 675 676 677 678
/**
  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
679
static char **defaults_argv;
Marc Alff's avatar
Marc Alff committed
680 681 682 683
/** 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
684 685
static char *opt_bin_logname;

686 687 688
int orig_argc;
char **orig_argv;

Marc Alff's avatar
Marc Alff committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 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 826 827 828 829 830 831 832 833 834 835 836 837 838
/*
  Since buffered_option_error_reporter is only used currently
  for parsing performance schema options, this code is not needed
  when the performance schema is not compiled in.
*/
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
/**
  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:
    sql_print_information("Buffered information: %s\n", m_message.c_ptr_safe());
    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()
{
  init_alloc_root(&m_root, 1024, 0);
}

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;

/**
  Error reporter that buffer log messages.
  @param level          log message level
  @param format         log message format string
*/
void buffered_option_error_reporter(enum loglevel level, const char *format, ...)
{
  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);
}
#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */

unknown's avatar
unknown committed
839
static my_socket unix_sock,ip_sock;
unknown's avatar
unknown committed
840
struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
unknown's avatar
unknown committed
841

unknown's avatar
unknown committed
842 843 844
#ifndef EMBEDDED_LIBRARY
struct passwd *user_info;
static pthread_t select_thread;
unknown's avatar
unknown committed
845
static uint thr_kill_signal;
unknown's avatar
unknown committed
846 847
#endif

unknown's avatar
unknown committed
848 849
/* OS specific variables */

unknown's avatar
unknown committed
850 851 852
#ifdef __WIN__
#undef	 getpid
#include <process.h>
unknown's avatar
unknown committed
853

Marc Alff's avatar
Marc Alff committed
854
static mysql_cond_t COND_handler_count;
unknown's avatar
unknown committed
855 856 857 858 859
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
860
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
861
static HANDLE hEventShutdown;
862
static char shutdown_event_name[40];
unknown's avatar
unknown committed
863
#include "nt_servc.h"
unknown's avatar
unknown committed
864
static	 NTService  Service;	      ///< Service object for WinNT
unknown's avatar
unknown committed
865 866 867
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */

Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
868
#ifdef _WIN32
869
static char pipe_name[512];
unknown's avatar
unknown committed
870 871 872
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
unknown's avatar
unknown committed
873
#endif
unknown's avatar
unknown committed
874

unknown's avatar
unknown committed
875
#ifndef EMBEDDED_LIBRARY
876
bool mysqld_embedded=0;
unknown's avatar
unknown committed
877
#else
878
bool mysqld_embedded=1;
unknown's avatar
unknown committed
879 880
#endif

881 882
static my_bool plugins_are_initialized= FALSE;

unknown's avatar
unknown committed
883 884 885 886
#ifndef DBUG_OFF
static const char* default_dbug_option;
#endif
#ifdef HAVE_LIBWRAP
887
const char *libwrapName= NULL;
888 889
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
unknown's avatar
unknown committed
890 891 892 893 894 895 896
#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;
897
my_bool opt_enable_shared_memory;
898
HANDLE smem_event_connect_request= 0;
unknown's avatar
unknown committed
899 900
#endif

unknown's avatar
unknown committed
901 902
scheduler_functions thread_scheduler;

903 904 905 906
my_bool opt_use_ssl  = 0;
char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
     *opt_ssl_cipher= NULL, *opt_ssl_key= NULL;

unknown's avatar
unknown committed
907
#ifdef HAVE_OPENSSL
908
#include <openssl/crypto.h>
unknown's avatar
unknown committed
909
#ifndef HAVE_YASSL
910 911
typedef struct CRYPTO_dynlock_value
{
Marc Alff's avatar
Marc Alff committed
912
  mysql_rwlock_t lock;
913 914 915 916 917 918 919 920
} 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
921
#endif
unknown's avatar
unknown committed
922
char *des_key_file;
unknown's avatar
unknown committed
923
struct st_VioSSLFd *ssl_acceptor_fd;
unknown's avatar
unknown committed
924 925
#endif /* HAVE_OPENSSL */

926 927 928 929 930
/**
  Number of currently active user connections. The variable is protected by
  LOCK_connection_count.
*/
uint connection_count= 0;
unknown's avatar
unknown committed
931 932 933

/* Function declarations */

934
pthread_handler_t signal_hand(void *arg);
935
static int mysql_init_variables(void);
Marc Alff's avatar
Marc Alff committed
936 937 938
extern "C" void option_error_reporter(enum loglevel level, const char *format, ...);
static int get_options(int *argc_ptr, char ***argv_ptr);
static bool add_terminator(DYNAMIC_ARRAY *options);
939
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
940
static void set_server_version(void);
941
static int init_thread_environment();
unknown's avatar
unknown committed
942
static char *get_relative_path(const char *path);
943
static int fix_paths(void);
944 945 946 947
void handle_connections_sockets();
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg);
#endif
948
pthread_handler_t kill_server_thread(void *arg);
Marc Alff's avatar
Marc Alff committed
949
static void bootstrap(MYSQL_FILE *file);
unknown's avatar
unknown committed
950
static bool read_init_file(char *file_name);
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
951
#ifdef _WIN32
952
pthread_handler_t handle_connections_namedpipes(void *arg);
unknown's avatar
unknown committed
953
#endif
954
#ifdef HAVE_SMEM
955
pthread_handler_t handle_connections_shared_memory(void *arg);
956
#endif
957
pthread_handler_t handle_slave(void *arg);
unknown's avatar
unknown committed
958
static void clean_up(bool print_message);
959 960 961
static int test_if_case_insensitive(const char *dir_name);

#ifndef EMBEDDED_LIBRARY
962
static void usage(void);
963 964
static void start_signal_handler(void);
static void close_server_sock();
unknown's avatar
unknown committed
965
static void clean_up_mutexes(void);
966
static void wait_for_signal_thread_to_end(void);
967
static void create_pid_file();
Sergey Vojtovich's avatar
Sergey Vojtovich committed
968
static void mysqld_exit(int exit_code) __attribute__((noreturn));
969
static void end_ssl();
970 971
#endif

972 973

#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
/****************************************************************************
** 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 */
990
#if !defined(__WIN__) && !defined(__NETWARE__)
unknown's avatar
unknown committed
991 992
  DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
                      (ulong) select_thread));
Marc Alff's avatar
Marc Alff committed
993
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
994 995 996 997 998 999

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

unknown's avatar
unknown committed
1002
#ifndef DONT_USE_THR_ALARM
1003
    if (pthread_kill(select_thread, thr_client_alarm))
unknown's avatar
unknown committed
1004 1005
      break;					// allready dead
#endif
1006
    set_timespec(abstime, 2);
1007
    for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
unknown's avatar
unknown committed
1008
    {
Marc Alff's avatar
Marc Alff committed
1009 1010
      error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
                                  &abstime);
unknown's avatar
unknown committed
1011 1012 1013 1014 1015
      if (error != EINTR)
	break;
    }
#ifdef EXTRA_DEBUG
    if (error != 0 && !count++)
Marc Alff's avatar
Marc Alff committed
1016
      sql_print_error("Got error %d from mysql_cond_timedwait", error);
unknown's avatar
unknown committed
1017
#endif
unknown's avatar
unknown committed
1018
    close_server_sock();
unknown's avatar
unknown committed
1019
  }
Marc Alff's avatar
Marc Alff committed
1020
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1021 1022 1023 1024 1025
#endif /* __WIN__ */


  /* Abort listening to new connections */
  DBUG_PRINT("quit",("Closing sockets"));
unknown's avatar
Merge  
unknown committed
1026
  if (!opt_disable_networking )
unknown's avatar
unknown committed
1027 1028 1029
  {
    if (ip_sock != INVALID_SOCKET)
    {
1030
      (void) shutdown(ip_sock, SHUT_RDWR);
unknown's avatar
unknown committed
1031 1032 1033 1034
      (void) closesocket(ip_sock);
      ip_sock= INVALID_SOCKET;
    }
  }
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1035
#ifdef _WIN32
unknown's avatar
unknown committed
1036
  if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
unknown's avatar
unknown committed
1037
  {
unknown's avatar
merge  
unknown committed
1038
    HANDLE temp;
unknown's avatar
Merge  
unknown committed
1039
    DBUG_PRINT("quit", ("Closing named pipes") );
1040

unknown's avatar
merge  
unknown committed
1041
    /* Create connection to the handle named pipe handler to break the loop */
1042
    if ((temp = CreateFile(pipe_name,
unknown's avatar
merge  
unknown committed
1043 1044 1045 1046 1047 1048 1049
			   GENERIC_READ | GENERIC_WRITE,
			   0,
			   NULL,
			   OPEN_EXISTING,
			   0,
			   NULL )) != INVALID_HANDLE_VALUE)
    {
1050
      WaitNamedPipe(pipe_name, 1000);
unknown's avatar
merge  
unknown committed
1051 1052 1053 1054 1055 1056
      DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
      SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
      CancelIo(temp);
      DisconnectNamedPipe(temp);
      CloseHandle(temp);
    }
unknown's avatar
unknown committed
1057 1058 1059 1060 1061
  }
#endif
#ifdef HAVE_SYS_UN_H
  if (unix_sock != INVALID_SOCKET)
  {
1062
    (void) shutdown(unix_sock, SHUT_RDWR);
unknown's avatar
unknown committed
1063
    (void) closesocket(unix_sock);
1064
    (void) unlink(mysqld_unix_port);
unknown's avatar
unknown committed
1065 1066 1067
    unix_sock= INVALID_SOCKET;
  }
#endif
1068
  end_thr_alarm(0);			 // Abort old alarms.
unknown's avatar
unknown committed
1069

1070 1071 1072 1073 1074
  /*
    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
1075 1076

  THD *tmp;
Marc Alff's avatar
Marc Alff committed
1077
  mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1078 1079 1080 1081 1082 1083

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

unknown's avatar
unknown committed
1088
    tmp->killed= THD::KILL_CONNECTION;
unknown's avatar
unknown committed
1089
    thread_scheduler.post_kill_notification(tmp);
unknown's avatar
unknown committed
1090 1091 1092
    if (tmp->mysys_var)
    {
      tmp->mysys_var->abort=1;
Marc Alff's avatar
Marc Alff committed
1093
      mysql_mutex_lock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1094
      if (tmp->mysys_var->current_cond)
unknown's avatar
unknown committed
1095
      {
Marc Alff's avatar
Marc Alff committed
1096 1097 1098
        mysql_mutex_lock(tmp->mysys_var->current_mutex);
        mysql_cond_broadcast(tmp->mysys_var->current_cond);
        mysql_mutex_unlock(tmp->mysys_var->current_mutex);
unknown's avatar
unknown committed
1099
      }
Marc Alff's avatar
Marc Alff committed
1100
      mysql_mutex_unlock(&tmp->mysys_var->mutex);
unknown's avatar
unknown committed
1101 1102
    }
  }
Marc Alff's avatar
Marc Alff committed
1103
  mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1104

1105
  Events::deinit();
1106 1107
  end_slave();

unknown's avatar
unknown committed
1108
  if (thread_count)
1109
    sleep(2);					// Give threads time to die
unknown's avatar
unknown committed
1110

1111 1112 1113 1114 1115
  /*
    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
1116 1117 1118 1119

  for (;;)
  {
    DBUG_PRINT("quit",("Locking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1120
    mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
unknown's avatar
unknown committed
1121 1122 1123
    if (!(tmp=threads.get()))
    {
      DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1124
      mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1125 1126 1127
      break;
    }
#ifndef __bsdi__				// Bug in BSDI kernel
1128
    if (tmp->vio_ok())
unknown's avatar
unknown committed
1129
    {
1130
      if (global_system_variables.log_warnings)
1131
        sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1132
                          tmp->thread_id,
1133 1134
                          (tmp->main_security_ctx.user ?
                           tmp->main_security_ctx.user : ""));
1135
      close_connection(tmp,0,0);
unknown's avatar
unknown committed
1136 1137 1138
    }
#endif
    DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
Marc Alff's avatar
Marc Alff committed
1139
    mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1140 1141 1142
  }
  /* 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
1143
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
1144 1145
  while (thread_count)
  {
Marc Alff's avatar
Marc Alff committed
1146
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
unknown's avatar
unknown committed
1147 1148
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
1149
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
1150

1151
  close_active_mi();
unknown's avatar
unknown committed
1152 1153 1154 1155
  DBUG_PRINT("quit",("close_connections thread"));
  DBUG_VOID_RETURN;
}

1156

1157
static void close_server_sock()
unknown's avatar
unknown committed
1158
{
1159
#ifdef HAVE_CLOSE_SERVER_SOCK
unknown's avatar
unknown committed
1160
  DBUG_ENTER("close_server_sock");
1161 1162 1163
  my_socket tmp_sock;
  tmp_sock=ip_sock;
  if (tmp_sock != INVALID_SOCKET)
unknown's avatar
unknown committed
1164 1165
  {
    ip_sock=INVALID_SOCKET;
1166
    DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
Konstantin Osipov's avatar
Konstantin Osipov committed
1167
    (void) shutdown(tmp_sock, SHUT_RDWR);
unknown's avatar
unknown committed
1168
#if defined(__NETWARE__)
1169
    /*
unknown's avatar
unknown committed
1170 1171
      The following code is disabled for normal systems as it causes MySQL
      to hang on AIX 4.3 during shutdown
1172
    */
1173
    DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
Konstantin Osipov's avatar
Konstantin Osipov committed
1174
    (void) closesocket(tmp_sock);
1175
#endif
unknown's avatar
unknown committed
1176
  }
1177 1178
  tmp_sock=unix_sock;
  if (tmp_sock != INVALID_SOCKET)
unknown's avatar
unknown committed
1179
  {
1180
    unix_sock=INVALID_SOCKET;
1181
    DBUG_PRINT("info",("calling shutdown on unix socket"));
Konstantin Osipov's avatar
Konstantin Osipov committed
1182
    (void) shutdown(tmp_sock, SHUT_RDWR);
unknown's avatar
unknown committed
1183
#if defined(__NETWARE__)
unknown's avatar
unknown committed
1184
    /*
1185 1186
      The following code is disabled for normal systems as it may cause MySQL
      to hang on AIX 4.3 during shutdown
unknown's avatar
unknown committed
1187 1188
    */
    DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
Konstantin Osipov's avatar
Konstantin Osipov committed
1189
    (void) closesocket(tmp_sock);
unknown's avatar
unknown committed
1190
#endif
Konstantin Osipov's avatar
Konstantin Osipov committed
1191
    (void) unlink(mysqld_unix_port);
unknown's avatar
unknown committed
1192 1193 1194
  }
  DBUG_VOID_RETURN;
#endif
1195
}
unknown's avatar
unknown committed
1196

1197 1198
#endif /*EMBEDDED_LIBRARY*/

1199

unknown's avatar
unknown committed
1200 1201 1202 1203
void kill_mysql(void)
{
  DBUG_ENTER("kill_mysql");

1204
#if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
1205 1206
  abort_loop=1;					// Break connection loops
  close_server_sock();				// Force accept to wake up
1207
#endif
unknown's avatar
unknown committed
1208

unknown's avatar
unknown committed
1209
#if defined(__WIN__)
unknown's avatar
unknown committed
1210
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
1211 1212 1213 1214 1215
  {
    if (!SetEvent(hEventShutdown))
    {
      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
    }
1216 1217 1218 1219 1220 1221
    /*
      or:
      HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
      SetEvent(hEventShutdown);
      CloseHandle(hEvent);
    */
unknown's avatar
unknown committed
1222
  }
unknown's avatar
unknown committed
1223
#endif
unknown's avatar
unknown committed
1224
#elif defined(HAVE_PTHREAD_KILL)
1225
  if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
unknown's avatar
unknown committed
1226 1227 1228 1229
  {
    DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
  }
#elif !defined(SIGNALS_DONT_BREAK_READ)
1230
  kill(current_pid, MYSQL_KILL_SIGNAL);
unknown's avatar
unknown committed
1231
#endif
unknown's avatar
unknown committed
1232 1233 1234
  DBUG_PRINT("quit",("After pthread_kill"));
  shutdown_in_progress=1;			// Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ
1235
  if (!kill_in_progress)
unknown's avatar
unknown committed
1236 1237
  {
    pthread_t tmp;
unknown's avatar
unknown committed
1238
    abort_loop=1;
Marc Alff's avatar
Marc Alff committed
1239 1240 1241
    if (mysql_thread_create(0, /* Not instrumented */
                            &tmp, &connection_attrib, kill_server_thread,
                            (void*) 0))
1242
      sql_print_error("Can't create thread to kill server");
unknown's avatar
unknown committed
1243
  }
1244
#endif
unknown's avatar
unknown committed
1245
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1246 1247
}

unknown's avatar
unknown committed
1248 1249
/**
  Force server down. Kill all connections and threads and exit.
1250

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

unknown's avatar
unknown committed
1253
  @note
1254 1255 1256 1257
    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
1258

1259
#if defined(__NETWARE__)
unknown's avatar
unknown committed
1260
extern "C" void kill_server(int sig_ptr)
1261
#define RETURN_FROM_KILL_SERVER return
unknown's avatar
unknown committed
1262
#elif !defined(__WIN__)
unknown's avatar
unknown committed
1263
static void *kill_server(void *sig_ptr)
1264
#define RETURN_FROM_KILL_SERVER return 0
unknown's avatar
unknown committed
1265 1266
#else
static void __cdecl kill_server(int sig_ptr)
1267
#define RETURN_FROM_KILL_SERVER return
unknown's avatar
unknown committed
1268 1269 1270
#endif
{
  DBUG_ENTER("kill_server");
1271
#ifndef EMBEDDED_LIBRARY
unknown's avatar
Merge  
unknown committed
1272
  int sig=(int) (long) sig_ptr;			// This is passed a int
1273
  // if there is a signal during the kill in progress, ignore the other
unknown's avatar
unknown committed
1274
  if (kill_in_progress)				// Safety
1275 1276
  {
    DBUG_LEAVE;
unknown's avatar
unknown committed
1277
    RETURN_FROM_KILL_SERVER;
1278
  }
unknown's avatar
unknown committed
1279 1280
  kill_in_progress=TRUE;
  abort_loop=1;					// This should be set
1281
  if (sig != 0) // 0 is not a valid signal number
1282
    my_sigset(sig, SIG_IGN);                    /* purify inspected */
unknown's avatar
unknown committed
1283
  if (sig == MYSQL_KILL_SIGNAL || sig == 0)
1284
    sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN),my_progname);
unknown's avatar
unknown committed
1285
  else
1286
    sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
unknown's avatar
unknown committed
1287

1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
#if defined(HAVE_SMEM) && defined(__WIN__)    
  /*    
   Send event to smem_event_connect_request for aborting    
   */    
  if (!SetEvent(smem_event_connect_request))    
  {      
	  DBUG_PRINT("error",
		("Got error: %ld from SetEvent of smem_event_connect_request",
		 GetLastError()));    
  }
#endif  
  
unknown's avatar
unknown committed
1300
  close_connections();
1301 1302
  if (sig != MYSQL_KILL_SIGNAL &&
      sig != 0)
unknown's avatar
unknown committed
1303 1304
    unireg_abort(1);				/* purecov: inspected */
  else
1305
    unireg_end();
unknown's avatar
Merge  
unknown committed
1306

1307
  /* purecov: begin deadcode */
unknown's avatar
unknown committed
1308
#ifdef __NETWARE__
unknown's avatar
unknown committed
1309
  if (!event_flag)
unknown's avatar
Merge  
unknown committed
1310
    pthread_join(select_thread, NULL);		// wait for main thread
unknown's avatar
unknown committed
1311
#endif /* __NETWARE__ */
1312

1313
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
1314
  my_thread_end();
1315 1316
  pthread_exit(0);
  /* purecov: end */
unknown's avatar
unknown committed
1317

1318 1319 1320 1321 1322
  RETURN_FROM_KILL_SERVER;                      // Avoid compiler warnings

#else /* EMBEDDED_LIBRARY*/

  DBUG_LEAVE;
unknown's avatar
unknown committed
1323
  RETURN_FROM_KILL_SERVER;
1324 1325

#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1326 1327 1328
}


unknown's avatar
unknown committed
1329
#if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
1330
pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
1331 1332 1333
{
  my_thread_init();				// Initialize new thread
  kill_server(0);
1334 1335 1336
  /* purecov: begin deadcode */
  my_thread_end();
  pthread_exit(0);
unknown's avatar
unknown committed
1337
  return 0;
1338
  /* purecov: end */
unknown's avatar
unknown committed
1339 1340 1341
}
#endif

1342

1343
extern "C" sig_handler print_signal_warning(int sig)
unknown's avatar
unknown committed
1344
{
unknown's avatar
unknown committed
1345
  if (global_system_variables.log_warnings)
1346
    sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
unknown's avatar
unknown committed
1347
#ifdef DONT_REMEMBER_SIGNAL
1348
  my_sigset(sig,print_signal_warning);		/* int. thread system calls */
unknown's avatar
unknown committed
1349
#endif
1350
#if !defined(__WIN__) && !defined(__NETWARE__)
unknown's avatar
unknown committed
1351 1352 1353 1354 1355
  if (sig == SIGALRM)
    alarm(2);					/* reschedule alarm */
#endif
}

unknown's avatar
unknown committed
1356
#ifndef EMBEDDED_LIBRARY
1357

Guilhem Bichot's avatar
Guilhem Bichot committed
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
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
1370 1371
/**
  cleanup all memory and end program nicely.
unknown's avatar
unknown committed
1372

1373 1374 1375
    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
1376

unknown's avatar
unknown committed
1377 1378 1379
  @note
    This function never returns.
*/
1380
void unireg_end(void)
unknown's avatar
unknown committed
1381
{
unknown's avatar
unknown committed
1382
  clean_up(1);
unknown's avatar
unknown committed
1383
  my_thread_end();
1384
#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
1385 1386
  exit(0);
#else
unknown's avatar
unknown committed
1387
  pthread_exit(0);				// Exit is in main thread
1388
#endif
unknown's avatar
unknown committed
1389 1390
}

Sergey Vojtovich's avatar
Sergey Vojtovich committed
1391

1392
extern "C" void unireg_abort(int exit_code)
unknown's avatar
unknown committed
1393
{
1394
  DBUG_ENTER("unireg_abort");
1395

1396 1397
  if (opt_help)
    usage();
unknown's avatar
unknown committed
1398 1399
  if (exit_code)
    sql_print_error("Aborting\n");
1400
  clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1401
  DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
Sergey Vojtovich's avatar
Sergey Vojtovich committed
1402 1403 1404 1405 1406
  mysqld_exit(exit_code);
}

static void mysqld_exit(int exit_code)
{
1407 1408 1409 1410 1411
  /*
    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.
  */
1412
  wait_for_signal_thread_to_end();
Sergey Vojtovich's avatar
Sergey Vojtovich committed
1413
  mysql_audit_finalize();
unknown's avatar
unknown committed
1414
  clean_up_mutexes();
Marc Alff's avatar
Marc Alff committed
1415
  clean_up_error_log_mutex();
unknown's avatar
unknown committed
1416
  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
unknown's avatar
unknown committed
1417 1418
  exit(exit_code); /* purecov: inspected */
}
1419

Sergey Vojtovich's avatar
Sergey Vojtovich committed
1420
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
1421

1422
void clean_up(bool print_message)
unknown's avatar
unknown committed
1423 1424 1425 1426
{
  DBUG_PRINT("exit",("clean_up"));
  if (cleanup_done++)
    return; /* purecov: inspected */
unknown's avatar
unknown committed
1427

1428
  stop_handle_manager();
1429 1430
  release_ddl_log();

unknown's avatar
unknown committed
1431 1432 1433 1434 1435
  /*
    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
1436 1437 1438

  logger.cleanup_base();

1439
  injector::free_instance();
unknown's avatar
unknown committed
1440 1441
  mysql_bin_log.cleanup();

unknown's avatar
SCRUM  
unknown committed
1442
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
1443 1444
  if (use_slave_mask)
    bitmap_free(&slave_error_mask);
1445
#endif
1446
  my_tz_free();
unknown's avatar
unknown committed
1447
  my_database_names_free();
unknown's avatar
SCRUM:  
unknown committed
1448
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
1449
  servers_free(1);
unknown's avatar
unknown committed
1450 1451
  acl_free(1);
  grant_free();
unknown's avatar
SCRUM:  
unknown committed
1452
#endif
unknown's avatar
unknown committed
1453
  query_cache_destroy();
unknown's avatar
unknown committed
1454 1455 1456
  hostname_cache_free();
  item_user_lock_free();
  lex_free();				/* Free some memory */
1457
  item_create_cleanup();
unknown's avatar
unknown committed
1458
  if (!opt_noacl)
1459
  {
1460
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
1461
    udf_free();
1462
#endif
1463
  }
Konstantin Osipov's avatar
Konstantin Osipov committed
1464
  table_def_start_shutdown();
1465
  plugin_shutdown();
1466
  ha_end();
unknown's avatar
Merge  
unknown committed
1467 1468
  if (tc_log)
    tc_log->close();
He Zhenxing's avatar
He Zhenxing committed
1469
  delegates_destroy();
1470
  xid_cache_free();
Konstantin Osipov's avatar
Konstantin Osipov committed
1471 1472
  table_def_free();
  mdl_destroy();
1473
  key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
1474
  multi_keycache_free();
1475
  free_status_vars();
1476
  end_thr_alarm(1);			/* Free allocated memory */
1477
  my_free_open_file_info();
unknown's avatar
unknown committed
1478 1479
  if (defaults_argv)
    free_defaults(defaults_argv);
unknown's avatar
unknown committed
1480
  free_tmpdir(&mysql_tmpdir_list);
1481
  x_free(opt_bin_logname);
unknown's avatar
unknown committed
1482
  bitmap_free(&temp_pool);
unknown's avatar
unknown committed
1483
  free_max_user_conn();
unknown's avatar
SCRUM  
unknown committed
1484
#ifdef HAVE_REPLICATION
1485
  end_slave_list();
1486
#endif
unknown's avatar
unknown committed
1487 1488
  delete binlog_filter;
  delete rpl_filter;
unknown's avatar
unknown committed
1489
#ifndef EMBEDDED_LIBRARY
1490
  end_ssl();
unknown's avatar
unknown committed
1491
#endif
1492
  vio_end();
unknown's avatar
unknown committed
1493
#ifdef USE_REGEX
unknown's avatar
unknown committed
1494
  my_regex_end();
unknown's avatar
unknown committed
1495
#endif
Ingo Struewing's avatar
Ingo Struewing committed
1496 1497 1498 1499
#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
1500

1501
#if !defined(EMBEDDED_LIBRARY)
1502
  if (!opt_bootstrap)
Marc Alff's avatar
Marc Alff committed
1503
    mysql_file_delete(key_file_pid, pidfile_name, MYF(0)); // This may not always exist
unknown's avatar
unknown committed
1504
#endif
1505
  if (print_message && my_default_lc_messages && server_start_time)
1506 1507
    sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
  cleanup_errmsgs();
unknown's avatar
unknown committed
1508
  thread_scheduler.end();
unknown's avatar
Merge  
unknown committed
1509
  finish_client_errs();
1510
  DBUG_PRINT("quit", ("Error messages freed"));
unknown's avatar
unknown committed
1511
  /* Tell main we are ready */
unknown's avatar
unknown committed
1512
  logger.cleanup_end();
1513
  my_atomic_rwlock_destroy(&global_query_id_lock);
1514
  my_atomic_rwlock_destroy(&thread_running_lock);
Marc Alff's avatar
Marc Alff committed
1515
  mysql_mutex_lock(&LOCK_thread_count);
1516
  DBUG_PRINT("quit", ("got thread count lock"));
unknown's avatar
unknown committed
1517
  ready_to_exit=1;
unknown's avatar
unknown committed
1518
  /* do the broadcast inside the lock to ensure that my_end() is not called */
Marc Alff's avatar
Marc Alff committed
1519 1520
  mysql_cond_broadcast(&COND_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
1521
  sys_var_end();
unknown's avatar
unknown committed
1522

unknown's avatar
unknown committed
1523 1524 1525 1526
  /*
    The following lines may never be executed as the main thread may have
    killed us
  */
1527
  DBUG_PRINT("quit", ("done with cleanup"));
unknown's avatar
unknown committed
1528 1529 1530
} /* clean_up */


1531 1532
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
1533
/**
1534
  This is mainly needed when running with purify, but it's still nice to
unknown's avatar
unknown committed
1535
  know that all child threads have died when mysqld exits.
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
*/
static void wait_for_signal_thread_to_end()
{
#ifndef __NETWARE__
  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++)
  {
1547
    if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) != ESRCH)
1548 1549 1550 1551 1552 1553 1554
      break;
    my_sleep(100);				// Give it time to die
  }
#endif
}


unknown's avatar
unknown committed
1555 1556
static void clean_up_mutexes()
{
Marc Alff's avatar
Marc Alff committed
1557 1558
  mysql_mutex_destroy(&LOCK_mysql_create_db);
  mysql_mutex_destroy(&LOCK_lock_db);
Marc Alff's avatar
Marc Alff committed
1559
  mysql_rwlock_destroy(&LOCK_grant);
Marc Alff's avatar
Marc Alff committed
1560
  mysql_mutex_destroy(&LOCK_open);
Marc Alff's avatar
Marc Alff committed
1561
  mysql_mutex_destroy(&LOCK_thread_count);
Marc Alff's avatar
Marc Alff committed
1562
  mysql_mutex_destroy(&LOCK_mapped_file);
Marc Alff's avatar
Marc Alff committed
1563 1564 1565 1566
  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
1567 1568 1569 1570
  mysql_mutex_destroy(&LOCK_manager);
  mysql_mutex_destroy(&LOCK_crypt);
  mysql_mutex_destroy(&LOCK_user_conn);
  mysql_mutex_destroy(&LOCK_connection_count);
1571
  Events::destroy_mutexes();
1572
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
1573
  mysql_mutex_destroy(&LOCK_des_key_file);
unknown's avatar
unknown committed
1574
#ifndef HAVE_YASSL
1575
  for (int i= 0; i < CRYPTO_num_locks(); ++i)
1576
    mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
1577
  OPENSSL_free(openssl_stdlocks);
1578 1579
#endif
#endif
1580
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
  mysql_mutex_destroy(&LOCK_rpl_status);
  mysql_cond_destroy(&COND_rpl_status);
#endif
  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);
  mysql_mutex_destroy(&LOCK_global_read_lock);
  mysql_mutex_destroy(&LOCK_uuid_generator);
  mysql_mutex_destroy(&LOCK_prepared_stmt_count);
  mysql_mutex_destroy(&LOCK_error_messages);
Marc Alff's avatar
Marc Alff committed
1593
  mysql_cond_destroy(&COND_thread_count);
Marc Alff's avatar
Marc Alff committed
1594
  mysql_cond_destroy(&COND_refresh);
Marc Alff's avatar
Marc Alff committed
1595
  mysql_cond_destroy(&COND_global_read_lock);
Marc Alff's avatar
Marc Alff committed
1596 1597
  mysql_cond_destroy(&COND_thread_cache);
  mysql_cond_destroy(&COND_flush_thread_cache);
Marc Alff's avatar
Marc Alff committed
1598
  mysql_cond_destroy(&COND_manager);
unknown's avatar
unknown committed
1599
}
1600 1601 1602
#endif /*EMBEDDED_LIBRARY*/


unknown's avatar
unknown committed
1603 1604 1605 1606
/****************************************************************************
** Init IP and UNIX socket
****************************************************************************/

unknown's avatar
WL#2936  
unknown committed
1607
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1608 1609 1610
static void set_ports()
{
  char	*env;
1611
  if (!mysqld_port && !opt_disable_networking)
unknown's avatar
unknown committed
1612
  {					// Get port if not from commandline
1613
    mysqld_port= MYSQL_PORT;
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625

    /*
      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
1626
    struct  servent *serv_ptr;
1627 1628
    if ((serv_ptr= getservbyname("mysql", "tcp")))
      mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
1629
#endif
unknown's avatar
unknown committed
1630
    if ((env = getenv("MYSQL_TCP_PORT")))
1631
      mysqld_port= (uint) atoi(env);		/* purecov: inspected */
unknown's avatar
unknown committed
1632
  }
1633
  if (!mysqld_unix_port)
unknown's avatar
unknown committed
1634 1635
  {
#ifdef __WIN__
1636
    mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
unknown's avatar
unknown committed
1637
#else
1638
    mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
unknown's avatar
unknown committed
1639 1640
#endif
    if ((env = getenv("MYSQL_UNIX_PORT")))
1641
      mysqld_unix_port= env;			/* purecov: inspected */
unknown's avatar
unknown committed
1642 1643 1644 1645 1646
  }
}

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

1647
static struct passwd *check_user(const char *user)
unknown's avatar
unknown committed
1648
{
1649
#if !defined(__WIN__) && !defined(__NETWARE__)
1650
  struct passwd *tmp_user_info;
1651
  uid_t user_id= geteuid();
unknown's avatar
unknown committed
1652

1653
  // Don't bother if we aren't superuser
1654
  if (user_id)
unknown's avatar
unknown committed
1655 1656
  {
    if (user)
1657
    {
1658 1659 1660 1661
      /* 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) &&
1662
	  global_system_variables.log_warnings)
1663 1664
        sql_print_warning(
                    "One can only use the --user switch if running as root\n");
unknown's avatar
unknown committed
1665
      /* purecov: end */
1666
    }
1667
    return NULL;
unknown's avatar
unknown committed
1668
  }
1669
  if (!user)
unknown's avatar
unknown committed
1670 1671 1672
  {
    if (!opt_bootstrap)
    {
unknown's avatar
merged  
unknown committed
1673
      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
1674 1675
      unireg_abort(1);
    }
1676
    return NULL;
unknown's avatar
unknown committed
1677
  }
1678
  /* purecov: begin tested */
unknown's avatar
unknown committed
1679
  if (!strcmp(user,"root"))
unknown's avatar
merged  
unknown committed
1680
    return NULL;                        // Avoid problem with dynamic libraries
unknown's avatar
unknown committed
1681

1682
  if (!(tmp_user_info= getpwnam(user)))
unknown's avatar
unknown committed
1683
  {
1684
    // Allow a numeric uid to be used
unknown's avatar
unknown committed
1685
    const char *pos;
unknown's avatar
merged  
unknown committed
1686 1687
    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
    if (*pos)                                   // Not numeric id
1688
      goto err;
1689
    if (!(tmp_user_info= getpwuid(atoi(user))))
1690
      goto err;
unknown's avatar
unknown committed
1691
  }
unknown's avatar
unknown committed
1692 1693
  return tmp_user_info;
  /* purecov: end */
1694 1695

err:
unknown's avatar
merged  
unknown committed
1696
  sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
1697
  unireg_abort(1);
1698 1699 1700 1701 1702 1703 1704 1705 1706

#ifdef PR_SET_DUMPABLE
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* inform kernel that process is dumpable */
    (void) prctl(PR_SET_DUMPABLE, 1);
  }
#endif

unknown's avatar
merged  
unknown committed
1707 1708
#endif
  return NULL;
1709 1710
}

1711
static void set_user(const char *user, struct passwd *user_info_arg)
1712
{
1713
  /* purecov: begin tested */
1714
#if !defined(__WIN__) && !defined(__NETWARE__)
1715
  DBUG_ASSERT(user_info_arg != 0);
unknown's avatar
unknown committed
1716
#ifdef HAVE_INITGROUPS
1717 1718 1719 1720 1721 1722 1723
  /*
    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.
  */
  calling_initgroups= TRUE;
1724
  initgroups((char*) user, user_info_arg->pw_gid);
1725
  calling_initgroups= FALSE;
unknown's avatar
unknown committed
1726
#endif
1727
  if (setgid(user_info_arg->pw_gid) == -1)
1728 1729 1730
  {
    sql_perror("setgid");
    unireg_abort(1);
unknown's avatar
unknown committed
1731
  }
1732
  if (setuid(user_info_arg->pw_uid) == -1)
unknown's avatar
unknown committed
1733 1734 1735 1736 1737
  {
    sql_perror("setuid");
    unireg_abort(1);
  }
#endif
unknown's avatar
unknown committed
1738
  /* purecov: end */
unknown's avatar
unknown committed
1739 1740
}

unknown's avatar
merged  
unknown committed
1741

1742
static void set_effective_user(struct passwd *user_info_arg)
1743
{
1744
#if !defined(__WIN__) && !defined(__NETWARE__)
1745 1746
  DBUG_ASSERT(user_info_arg != 0);
  if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
1747
  {
1748
    sql_perror("setregid");
1749
    unireg_abort(1);
unknown's avatar
merged  
unknown committed
1750
  }
1751
  if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
1752
  {
1753
    sql_perror("setreuid");
1754 1755 1756 1757 1758 1759
    unireg_abort(1);
  }
#endif
}


unknown's avatar
unknown committed
1760
/** Change root user if started with @c --chroot . */
unknown's avatar
unknown committed
1761 1762
static void set_root(const char *path)
{
1763
#if !defined(__WIN__) && !defined(__NETWARE__)
unknown's avatar
unknown committed
1764 1765 1766 1767 1768
  if (chroot(path) == -1)
  {
    sql_perror("chroot");
    unireg_abort(1);
  }
1769
  my_setwd("/", MYF(0));
unknown's avatar
unknown committed
1770 1771 1772
#endif
}

1773

unknown's avatar
unknown committed
1774
static void network_init(void)
unknown's avatar
unknown committed
1775 1776 1777 1778
{
#ifdef HAVE_SYS_UN_H
  struct sockaddr_un	UNIXaddr;
#endif
1779
  int	arg;
1780 1781 1782 1783
  int   ret;
  uint  waited;
  uint  this_wait;
  uint  retry;
1784
  char port_buf[NI_MAXSERV];
unknown's avatar
unknown committed
1785
  DBUG_ENTER("network_init");
1786
  LINT_INIT(ret);
unknown's avatar
unknown committed
1787

unknown's avatar
unknown committed
1788 1789 1790
  if (thread_scheduler.init())
    unireg_abort(1);			/* purecov: inspected */

unknown's avatar
unknown committed
1791 1792
  set_ports();

1793
  if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
unknown's avatar
unknown committed
1794
  {
1795 1796 1797
    struct addrinfo *ai, *a;
    struct addrinfo hints;
    int error;
1798
    DBUG_PRINT("general",("IP Socket is %d",mysqld_port));
1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809

    bzero(&hints, sizeof (hints));
    hints.ai_flags= AI_PASSIVE;
    hints.ai_socktype= SOCK_STREAM;
    hints.ai_family= AF_UNSPEC;

    my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port);
    error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai);
    if (error != 0)
    {
      DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error));
1810
      sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
1811 1812 1813 1814 1815 1816 1817 1818 1819 1820
      unireg_abort(1);				/* purecov: tested */
    }

    for (a= ai; a != NULL; a= a->ai_next)
    {
      ip_sock= socket(a->ai_family, a->ai_socktype, a->ai_protocol);
      if (ip_sock != INVALID_SOCKET)
        break;
    }

unknown's avatar
unknown committed
1821 1822 1823
    if (ip_sock == INVALID_SOCKET)
    {
      DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
1824
      sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
unknown's avatar
unknown committed
1825 1826
      unireg_abort(1);				/* purecov: tested */
    }
1827 1828 1829 1830 1831 1832

#ifndef __WIN__
    /*
      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.
    */
1833
    arg= 1;
unknown's avatar
unknown committed
1834
    (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
unknown's avatar
unknown committed
1835
#endif /* __WIN__ */
1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853

#ifdef IPV6_V6ONLY
     /*
       For interoperability with older clients, IPv6 socket should
       listen on both IPv6 and IPv4 wildcard addresses.
       Turn off IPV6_V6ONLY option.

       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;
      (void) setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                sizeof(arg));
    }
#endif
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863
    /*
      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=#).
    */
    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
    {
1864
      if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
1865
          (socket_errno != SOCKET_EADDRINUSE) ||
1866 1867 1868 1869 1870 1871
          (waited >= mysqld_port_timeout))
        break;
      sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);
      this_wait= retry * retry / 3 + 1;
      sleep(this_wait);
    }
1872
    freeaddrinfo(ai);
1873
    if (ret < 0)
unknown's avatar
unknown committed
1874 1875
    {
      DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
unknown's avatar
unknown committed
1876
      sql_perror("Can't start server: Bind on TCP/IP port");
1877
      sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
unknown's avatar
unknown committed
1878 1879
      unireg_abort(1);
    }
1880
    if (listen(ip_sock,(int) back_log) < 0)
unknown's avatar
unknown committed
1881
    {
unknown's avatar
unknown committed
1882
      sql_perror("Can't start server: listen() on TCP/IP port");
1883
      sql_print_error("listen() on TCP/IP failed with error %d",
unknown's avatar
unknown committed
1884
		      socket_errno);
unknown's avatar
unknown committed
1885 1886
      unireg_abort(1);
    }
unknown's avatar
unknown committed
1887
  }
1888

Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
1889
#ifdef _WIN32
unknown's avatar
unknown committed
1890
  /* create named pipe */
1891
  if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
unknown's avatar
unknown committed
1892
      opt_enable_named_pipe)
unknown's avatar
unknown committed
1893
  {
1894
    strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
1895
	     mysqld_unix_port, NullS);
1896 1897
    bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
    bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
1898
    if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
1899
				      SECURITY_DESCRIPTOR_REVISION))
unknown's avatar
unknown committed
1900 1901 1902 1903 1904 1905 1906 1907 1908
    {
      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
1909
    saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
unknown's avatar
unknown committed
1910 1911
    saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
    saPipeSecurity.bInheritHandle = FALSE;
1912
    if ((hPipe= CreateNamedPipe(pipe_name,
1913
				PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
1914 1915 1916 1917 1918 1919 1920 1921
				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
1922 1923 1924 1925 1926 1927 1928
      {
	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 );
1929
	sql_perror((char *)lpMsgBuf);
unknown's avatar
Merge  
unknown committed
1930
	LocalFree(lpMsgBuf);
unknown's avatar
unknown committed
1931 1932 1933 1934 1935
	unireg_abort(1);
      }
  }
#endif

1936
#if defined(HAVE_SYS_UN_H)
unknown's avatar
unknown committed
1937 1938 1939
  /*
  ** Create the UNIX socket
  */
1940
  if (mysqld_unix_port[0] && !opt_bootstrap)
unknown's avatar
unknown committed
1941
  {
1942
    DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
unknown's avatar
unknown committed
1943

unknown's avatar
unknown committed
1944 1945
    if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
    {
1946
      sql_print_error("The socket file path is too long (> %u): %s",
unknown's avatar
unknown committed
1947
                      (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unknown's avatar
unknown committed
1948 1949
      unireg_abort(1);
    }
1950
    if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
unknown's avatar
unknown committed
1951 1952 1953 1954 1955 1956
    {
      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
      unireg_abort(1);				/* purecov: inspected */
    }
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
1957 1958
    strmov(UNIXaddr.sun_path, mysqld_unix_port);
    (void) unlink(mysqld_unix_port);
1959
    arg= 1;
unknown's avatar
unknown committed
1960 1961 1962 1963 1964 1965 1966
    (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
		      sizeof(arg));
    umask(0);
    if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
	     sizeof(UNIXaddr)) < 0)
    {
      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
1967
      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
unknown's avatar
unknown committed
1968 1969 1970 1971
      unireg_abort(1);					/* purecov: tested */
    }
    umask(((~my_umask) & 0666));
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
1972
    (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
unknown's avatar
unknown committed
1973
#endif
1974
    if (listen(unix_sock,(int) back_log) < 0)
1975
      sql_print_warning("listen() on Unix socket failed with error %d",
unknown's avatar
unknown committed
1976
		      socket_errno);
unknown's avatar
unknown committed
1977 1978 1979 1980 1981 1982
  }
#endif
  DBUG_PRINT("info",("server started"));
  DBUG_VOID_RETURN;
}

1983
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
1984

1985

1986
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
1987 1988
/**
  Close a connection.
1989

unknown's avatar
unknown committed
1990 1991 1992
  @param thd		Thread handle
  @param errcode	Error code to print to console
  @param lock	        1 if we have have to lock LOCK_thread_count
1993

unknown's avatar
unknown committed
1994
  @note
1995 1996
    For the connection that is doing shutdown, this is called twice
*/
1997
void close_connection(THD *thd, uint errcode, bool lock)
unknown's avatar
unknown committed
1998
{
1999
  st_vio *vio;
unknown's avatar
unknown committed
2000 2001
  DBUG_ENTER("close_connection");
  DBUG_PRINT("enter",("fd: %s  error: '%s'",
2002 2003
		      thd->net.vio ? vio_description(thd->net.vio) :
		      "(not connected)",
2004
		      errcode ? ER_DEFAULT(errcode) : ""));
unknown's avatar
unknown committed
2005
  if (lock)
Marc Alff's avatar
Marc Alff committed
2006
    mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
2007 2008
  thd->killed= THD::KILL_CONNECTION;
  if ((vio= thd->net.vio) != 0)
unknown's avatar
unknown committed
2009 2010
  {
    if (errcode)
Marc Alff's avatar
Marc Alff committed
2011
      net_send_error(thd, errcode,
2012
                     ER_DEFAULT(errcode), NULL); /* purecov: inspected */
unknown's avatar
unknown committed
2013 2014 2015
    vio_close(vio);			/* vio is freed in delete thd */
  }
  if (lock)
Marc Alff's avatar
Marc Alff committed
2016
    mysql_mutex_unlock(&LOCK_thread_count);
2017 2018 2019 2020 2021
  MYSQL_CONNECTION_DONE((int) errcode, thd->thread_id);
  if (MYSQL_CONNECTION_DONE_ENABLED())
  {
    sleep(0); /* Workaround to avoid tailcall optimisation */
  }
unknown's avatar
unknown committed
2022 2023
  DBUG_VOID_RETURN;
}
2024 2025
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
2026

unknown's avatar
unknown committed
2027 2028
/** Called when a thread is aborted. */
/* ARGSUSED */
2029
extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
unknown's avatar
unknown committed
2030 2031 2032
{
  THD *thd=current_thd;
  DBUG_ENTER("end_thread_signal");
2033
  if (thd && ! thd->bootstrap)
2034 2035
  {
    statistic_increment(killed_threads, &LOCK_status);
unknown's avatar
unknown committed
2036
    thread_scheduler.end_thread(thd,0);		/* purecov: inspected */
2037
  }
unknown's avatar
unknown committed
2038 2039 2040 2041
  DBUG_VOID_RETURN;				/* purecov: deadcode */
}


unknown's avatar
unknown committed
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053
/*
  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
2054
{
unknown's avatar
unknown committed
2055 2056
  DBUG_ENTER("unlink_thd");
  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
unknown's avatar
unknown committed
2057
  thd->cleanup();
2058

Marc Alff's avatar
Marc Alff committed
2059
  mysql_mutex_lock(&LOCK_connection_count);
2060
  --connection_count;
Marc Alff's avatar
Marc Alff committed
2061
  mysql_mutex_unlock(&LOCK_connection_count);
2062

Marc Alff's avatar
Marc Alff committed
2063
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
2064 2065
  thread_count--;
  delete thd;
unknown's avatar
unknown committed
2066 2067 2068
  DBUG_VOID_RETURN;
}

2069

unknown's avatar
unknown committed
2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
/*
  Store thread in cache for reuse by new connections

  SYNOPSIS
    cache_thread()

  NOTES
    LOCK_thread_count has to be locked

  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()
{
Marc Alff's avatar
Marc Alff committed
2088
  mysql_mutex_assert_owner(&LOCK_thread_count);
unknown's avatar
unknown committed
2089
  if (cached_thread_count < thread_cache_size &&
2090
      ! abort_loop && !kill_cached_threads)
unknown's avatar
unknown committed
2091 2092
  {
    /* Don't kill the thread, just put it in cache for reuse */
unknown's avatar
unknown committed
2093
    DBUG_PRINT("info", ("Adding thread to cache"));
unknown's avatar
unknown committed
2094 2095
    cached_thread_count++;
    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
Marc Alff's avatar
Marc Alff committed
2096
      mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count);
unknown's avatar
unknown committed
2097 2098
    cached_thread_count--;
    if (kill_cached_threads)
Marc Alff's avatar
Marc Alff committed
2099
      mysql_cond_signal(&COND_flush_thread_cache);
unknown's avatar
unknown committed
2100 2101
    if (wake_thread)
    {
unknown's avatar
unknown committed
2102
      THD *thd;
unknown's avatar
unknown committed
2103
      wake_thread--;
unknown's avatar
unknown committed
2104
      thd= thread_cache.get();
2105
      thd->thread_stack= (char*) &thd;          // For store_globals
unknown's avatar
unknown committed
2106
      (void) thd->store_globals();
2107 2108 2109 2110 2111 2112
      /*
        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;
2113
      thd->thr_create_utime= my_micro_time();
2114
      threads.append(thd);
unknown's avatar
unknown committed
2115
      return(1);
unknown's avatar
unknown committed
2116 2117
    }
  }
unknown's avatar
unknown committed
2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
  return(0);
}


/*
  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);
  if (put_in_cache)
    put_in_cache= cache_thread();
Marc Alff's avatar
Marc Alff committed
2147
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
2148 2149
  if (put_in_cache)
    DBUG_RETURN(0);                             // Thread is reused
unknown's avatar
unknown committed
2150

2151
  /* It's safe to broadcast outside a lock (COND... is not deleted here) */
unknown's avatar
unknown committed
2152
  DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
2153
  DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2154
  my_thread_end();
Marc Alff's avatar
Marc Alff committed
2155
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
2156 2157

  pthread_exit(0);
2158
  return 0;                                     // Avoid compiler warnings
unknown's avatar
unknown committed
2159 2160 2161 2162 2163
}


void flush_thread_cache()
{
Marc Alff's avatar
Marc Alff committed
2164
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
2165 2166 2167
  kill_cached_threads++;
  while (cached_thread_count)
  {
Marc Alff's avatar
Marc Alff committed
2168 2169
    mysql_cond_broadcast(&COND_thread_cache);
    mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count);
unknown's avatar
unknown committed
2170 2171
  }
  kill_cached_threads--;
Marc Alff's avatar
Marc Alff committed
2172
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
2173 2174 2175 2176
}


#ifdef THREAD_SPECIFIC_SIGPIPE
unknown's avatar
unknown committed
2177 2178 2179 2180 2181 2182
/**
  Aborts a thread nicely. Comes here on SIGPIPE.

  @todo
    One should have to fix that thr_alarm know about this thread too.
*/
2183
extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
unknown's avatar
unknown committed
2184 2185 2186 2187
{
  THD *thd=current_thd;
  DBUG_ENTER("abort_thread");
  if (thd)
unknown's avatar
Merge  
unknown committed
2188
    thd->killed= THD::KILL_CONNECTION;
unknown's avatar
unknown committed
2189 2190 2191 2192
  DBUG_VOID_RETURN;
}
#endif

unknown's avatar
unknown committed
2193

unknown's avatar
unknown committed
2194
/******************************************************************************
2195 2196 2197
  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
2198 2199
******************************************************************************/

2200
#if defined(__WIN__)
2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214


/*
  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
2215
#ifndef EMBEDDED_LIBRARY
2216 2217 2218 2219 2220 2221 2222 2223
  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.
     */
2224
#ifndef EMBEDDED_LIBRARY
2225 2226 2227
     if(hEventShutdown)
       kill_mysql();
     else
2228
#endif
2229 2230 2231
       sql_print_warning("CTRL-C ignored during startup");
     DBUG_RETURN(TRUE);
  }
unknown's avatar
unknown committed
2232
#endif
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
  DBUG_RETURN(FALSE);
}




#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
/*
  Wait for debugger to attach and break into debugger. If debugger is not attached,
  resume after timeout.
*/
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
  {
2294
    my_set_exception_pointers(ex_pointers);
2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313
    handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode);
  }
  __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
2314 2315
static void init_signals(void)
{
2316 2317
  if(opt_console)
    SetConsoleCtrlHandler(console_event_handler,TRUE);
2318

2319
    /* Avoid MessageBox()es*/
2320 2321 2322 2323 2324 2325
  _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);
2326 2327 2328 2329 2330 2331 2332 2333

   /*
     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)
   */
2334 2335
  SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
                               | SEM_NOOPENFILEERRORBOX);
2336
  SetUnhandledExceptionFilter(my_unhandler_exception_filter);
unknown's avatar
unknown committed
2337 2338
}

unknown's avatar
unknown committed
2339

2340
static void start_signal_handler(void)
2341
{
2342
#ifndef EMBEDDED_LIBRARY
2343 2344 2345
  // Save vm id of this process
  if (!opt_bootstrap)
    create_pid_file();
2346
#endif /* EMBEDDED_LIBRARY */
2347
}
unknown's avatar
unknown committed
2348

unknown's avatar
unknown committed
2349

unknown's avatar
unknown committed
2350 2351
static void check_data_home(const char *path)
{}
2352

unknown's avatar
unknown committed
2353

unknown's avatar
unknown committed
2354 2355
#elif defined(__NETWARE__)

unknown's avatar
unknown committed
2356
/// down server event callback.
unknown's avatar
unknown committed
2357 2358
void mysql_down_server_cb(void *, void *)
{
unknown's avatar
Merge  
unknown committed
2359
  event_flag= TRUE;
unknown's avatar
unknown committed
2360 2361 2362
  kill_server(0);
}

unknown's avatar
unknown committed
2363

unknown's avatar
unknown committed
2364
/// destroy callback resources.
unknown's avatar
unknown committed
2365
void mysql_cb_destroy(void *)
unknown's avatar
Merge  
unknown committed
2366 2367
{
  UnRegisterEventNotification(eh);  // cleanup down event notification
unknown's avatar
unknown committed
2368
  NX_UNWRAP_INTERFACE(ref);
unknown's avatar
Merge  
unknown committed
2369 2370
  /* Deregister NSS volume deactivation event */
  NX_UNWRAP_INTERFACE(refneb);
unknown's avatar
unknown committed
2371
  if (neb_consumer_id)
2372
    UnRegisterConsumer(neb_consumer_id, NULL);
unknown's avatar
unknown committed
2373 2374
}

unknown's avatar
unknown committed
2375

unknown's avatar
unknown committed
2376
/// initialize callbacks.
unknown's avatar
unknown committed
2377 2378 2379 2380
void mysql_cb_init()
{
  // register for down server event
  void *handle = getnlmhandle();
unknown's avatar
unknown committed
2381 2382
  rtag_t rt= AllocateResourceTag(handle, "MySQL Down Server Callback",
                                 EventSignature);
unknown's avatar
unknown committed
2383
  NX_WRAP_INTERFACE((void *)mysql_down_server_cb, 2, (void **)&ref);
unknown's avatar
unknown committed
2384 2385 2386 2387 2388 2389 2390 2391
  eh= RegisterForEventNotification(rt, EVENT_PRE_DOWN_SERVER,
                                   EVENT_PRIORITY_APPLICATION,
                                   NULL, ref, NULL);

  /*
    Register for volume deactivation event
    Wrap the callback function, as it is called by non-LibC thread
  */
2392
  (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
unknown's avatar
unknown committed
2393 2394
  registerwithneb();

unknown's avatar
unknown committed
2395 2396 2397
  NXVmRegisterExitHandler(mysql_cb_destroy, NULL);  // clean-up
}

unknown's avatar
unknown committed
2398

unknown's avatar
unknown committed
2399
/** To get the name of the NetWare volume having MySQL data folder. */
2400
static void getvolumename()
unknown's avatar
unknown committed
2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
{
  char *p;
  /*
    We assume that data path is already set.
    If not it won't come here. Terminate after volume name
  */
  if ((p= strchr(mysql_real_data_home, ':')))
    strmake(datavolname, mysql_real_data_home,
            (uint) (p - mysql_real_data_home));
}


unknown's avatar
unknown committed
2413 2414
/**
  Registering with NEB for NSS Volume Deactivation event.
unknown's avatar
unknown committed
2415 2416
*/

2417
static void registerwithneb()
unknown's avatar
unknown committed
2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465
{

  ConsumerRegistrationInfo reg_info;
    
  /* Clear NEB registration structure */
  bzero((char*) &reg_info, sizeof(struct ConsumerRegistrationInfo));

  /* Fill the NEB consumer information structure */
  reg_info.CRIVersion= 1;  	            // NEB version
  /* NEB Consumer name */
  reg_info.CRIConsumerName= (BYTE *) "MySQL Database Server";
  /* Event of interest */
  reg_info.CRIEventName= (BYTE *) "NSS.ChangeVolState.Enter";
  reg_info.CRIUserParameter= NULL;	    // Consumer Info
  reg_info.CRIEventFlags= 0;	            // Event flags
  /* Consumer NLM handle */
  reg_info.CRIOwnerID= (LoadDefinitionStructure *)getnlmhandle();
  reg_info.CRIConsumerESR= NULL;	    // No consumer ESR required
  reg_info.CRISecurityToken= 0;	            // No security token for the event
  reg_info.CRIConsumerFlags= 0;             // SMP_ENABLED_BIT;	
  reg_info.CRIFilterName= 0;	            // No event filtering
  reg_info.CRIFilterDataLength= 0;          // No filtering data
  reg_info.CRIFilterData= 0;	            // No filtering data
  /* Callback function for the event */
  (void *)reg_info.CRIConsumerCallback= (void *) refneb;
  reg_info.CRIOrder= 0;	                    // Event callback order
  reg_info.CRIConsumerType= CHECK_CONSUMER; // Consumer type

  /* Register for the event with NEB */
  if (RegisterConsumer(&reg_info))
  {
    consoleprintf("Failed to register for NSS Volume Deactivation event \n");
    return;
  }
  /* This ID is required for deregistration */
  neb_consumer_id= reg_info.CRIConsumerID;

  /* Get MySQL data volume name, stored in global variable datavolname */
  getvolumename();

  /*
    Get the NSS volume ID of the MySQL Data volume.
    Volume ID is stored in a global variable
  */
  getvolumeID((BYTE*) datavolname);	
}


unknown's avatar
unknown committed
2466 2467
/**
  Callback for NSS Volume Deactivation event.
unknown's avatar
unknown committed
2468
*/
2469

unknown's avatar
unknown committed
2470 2471 2472
ulong neb_event_callback(struct EventBlock *eblock)
{
  EventChangeVolStateEnter_s *voldata;
2473 2474
  extern bool nw_panic;

unknown's avatar
unknown committed
2475 2476 2477
  voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData;

  /* Deactivation of a volume */
unknown's avatar
unknown committed
2478 2479 2480
  if ((voldata->oldState == zVOLSTATE_ACTIVE &&
       voldata->newState == zVOLSTATE_DEACTIVE ||
       voldata->newState == zVOLSTATE_MAINTENANCE))
unknown's avatar
unknown committed
2481 2482 2483 2484 2485 2486 2487 2488
  {
    /*
      Ensure that we bring down MySQL server only for MySQL data
      volume deactivation
    */
    if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t)))
    {
      consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server \n");
unknown's avatar
unknown committed
2489
      event_flag= TRUE;
2490
      nw_panic = TRUE;
2491
      event_flag= TRUE;
unknown's avatar
unknown committed
2492 2493 2494 2495 2496 2497 2498 2499 2500
      kill_server(0);
    }
  }
  return 0;
}


#define ADMIN_VOL_PATH					"_ADMIN:/Volumes/"

unknown's avatar
unknown committed
2501 2502 2503
/**
  Function to get NSS volume ID of the MySQL data.
*/
2504
static void getvolumeID(BYTE *volumeName)
unknown's avatar
unknown committed
2505 2506 2507 2508 2509 2510 2511
{
  char path[zMAX_FULL_NAME];
  Key_t rootKey= 0, fileKey= 0;
  QUAD getInfoMask;
  zInfo_s info;
  STATUS status;

2512
  /* Get the root key */
unknown's avatar
unknown committed
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548
  if ((status= zRootKey(0, &rootKey)) != zOK)
  {
    consoleprintf("\nGetNSSVolumeProperties - Failed to get root key, status: %d\n.", (int) status);
    goto exit;
  }

  /*
    Get the file key. This is the key to the volume object in the
    NSS admin volumes directory.
  */

  strxmov(path, (const char *) ADMIN_VOL_PATH, (const char *) volumeName,
          NullS);
  if ((status= zOpen(rootKey, zNSS_TASK, zNSPACE_LONG|zMODE_UTF8, 
                     (BYTE *) path, zRR_READ_ACCESS, &fileKey)) != zOK)
  {
    consoleprintf("\nGetNSSVolumeProperties - Failed to get file, status: %d\n.", (int) status);
    goto exit;
  }

  getInfoMask= zGET_IDS | zGET_VOLUME_INFO ;
  if ((status= zGetInfo(fileKey, getInfoMask, sizeof(info), 
                        zINFO_VERSION_A, &info)) != zOK)
  {
    consoleprintf("\nGetNSSVolumeProperties - Failed in zGetInfo, status: %d\n.", (int) status);
    goto exit;
  }

  /* Copy the data to global variable */
  datavolid.timeLow= info.vol.volumeID.timeLow;
  datavolid.timeMid= info.vol.volumeID.timeMid;
  datavolid.timeHighAndVersion= info.vol.volumeID.timeHighAndVersion;
  datavolid.clockSeqHighAndReserved= info.vol.volumeID.clockSeqHighAndReserved;
  datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
  /* This is guranteed to be 6-byte length (but sizeof() would be better) */
  memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
unknown's avatar
Merge  
unknown committed
2549

unknown's avatar
unknown committed
2550 2551 2552 2553 2554 2555 2556 2557
exit:
  if (rootKey)
    zClose(rootKey);
  if (fileKey)
    zClose(fileKey);
}


unknown's avatar
unknown committed
2558 2559 2560 2561 2562 2563 2564 2565
static void init_signals(void)
{
  int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT};

  for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
    signal(signals[i], kill_server);
  mysql_cb_init();  // initialize callbacks

2566
}
unknown's avatar
unknown committed
2567

2568

unknown's avatar
unknown committed
2569 2570 2571 2572
static void start_signal_handler(void)
{
  // Save vm id of this process
  if (!opt_bootstrap)
2573
    create_pid_file();
unknown's avatar
unknown committed
2574 2575 2576 2577
  // no signal handler
}


unknown's avatar
unknown committed
2578 2579
/**
  Warn if the data is on a Traditional volume.
unknown's avatar
unknown committed
2580

unknown's avatar
unknown committed
2581
  @note
unknown's avatar
unknown committed
2582 2583
    Already done by mysqld_safe
*/
unknown's avatar
unknown committed
2584 2585

static void check_data_home(const char *path)
2586 2587 2588
{
}

2589
#endif /*__WIN__ || __NETWARE */
unknown's avatar
unknown committed
2590

unknown's avatar
unknown committed
2591 2592
#ifdef HAVE_LINUXTHREADS
#define UNSAFE_DEFAULT_LINUX_THREADS 200
2593
#endif
2594

unknown's avatar
unknown committed
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604

#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


2605
extern "C" sig_handler handle_segfault(int sig)
2606
{
2607 2608
  time_t curr_time;
  struct tm tm;
unknown's avatar
unknown committed
2609
  THD *thd=current_thd;
2610

2611 2612 2613 2614 2615 2616
  /*
    Strictly speaking, one needs a mutex here
    but since we have got SIGSEGV already, things are a mess
    so not having the mutex is not as bad as possibly using a buggy
    mutex - so we keep things simple
  */
2617
  if (segfaulted)
unknown's avatar
unknown committed
2618
  {
2619
    fprintf(stderr, "Fatal " SIGNAL_FMT " while backtracing\n", sig);
unknown's avatar
unknown committed
2620 2621
    exit(1);
  }
2622

2623
  segfaulted = 1;
2624

2625
  curr_time= my_time(0);
2626 2627
  localtime_r(&curr_time, &tm);

2628
  fprintf(stderr,"\
2629
%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
unknown's avatar
unknown committed
2630
This could be because you hit a bug. It is also possible that this binary\n\
unknown's avatar
unknown committed
2631
or one of the libraries it was linked against is corrupt, improperly built,\n\
unknown's avatar
unknown committed
2632
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
2633 2634
          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
          tm.tm_hour, tm.tm_min, tm.tm_sec,
unknown's avatar
unknown committed
2635 2636 2637 2638
	  sig);
  fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
unknown's avatar
unknown committed
2639
and this may fail.\n\n");
2640
  fprintf(stderr, "key_buffer_size=%lu\n",
unknown's avatar
unknown committed
2641
          (ulong) dflt_key_cache->key_cache_mem_size);
unknown's avatar
unknown committed
2642 2643
  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
  fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
unknown's avatar
unknown committed
2644
  fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads);
Konstantin Osipov's avatar
Konstantin Osipov committed
2645 2646
  fprintf(stderr, "thread_count=%u\n", thread_count);
  fprintf(stderr, "connection_count=%u\n", connection_count);
unknown's avatar
unknown committed
2647
  fprintf(stderr, "It is possible that mysqld could use up to \n\
unknown's avatar
unknown committed
2648
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\
unknown's avatar
unknown committed
2649
bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
2650
		     (global_system_variables.read_buff_size +
unknown's avatar
unknown committed
2651
		      global_system_variables.sortbuff_size) *
unknown's avatar
unknown committed
2652 2653
		     thread_scheduler.max_threads +
                     max_connections * sizeof(THD)) / 1024);
unknown's avatar
unknown committed
2654
  fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
2655

2656
#if defined(HAVE_LINUXTHREADS)
unknown's avatar
unknown committed
2657 2658 2659 2660
  if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
  {
    fprintf(stderr, "\
You seem to be running 32-bit Linux and have %d concurrent connections.\n\
unknown's avatar
unknown committed
2661 2662
If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
unknown's avatar
unknown committed
2663
the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
unknown's avatar
unknown committed
2664 2665 2666
	    thread_count);
  }
#endif /* HAVE_LINUXTHREADS */
unknown's avatar
unknown committed
2667

unknown's avatar
unknown committed
2668
#ifdef HAVE_STACKTRACE
2669
  if (!(test_flags & TEST_NO_STACKTRACE))
unknown's avatar
unknown committed
2670
  {
unknown's avatar
unknown committed
2671
    fprintf(stderr,"thd: 0x%lx\n",(long) thd);
2672 2673 2674
    fprintf(stderr,"\
Attempting backtrace. You can use the following information to find out\n\
where mysqld died. If you see no messages after this, something went\n\
2675
terribly wrong...\n");  
2676 2677
    my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
                        my_thread_stack_size);
unknown's avatar
unknown committed
2678
  }
unknown's avatar
unknown committed
2679 2680
  if (thd)
  {
unknown's avatar
unknown committed
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698
    const char *kreason= "UNKNOWN";
    switch (thd->killed) {
    case THD::NOT_KILLED:
      kreason= "NOT_KILLED";
      break;
    case THD::KILL_BAD_DATA:
      kreason= "KILL_BAD_DATA";
      break;
    case THD::KILL_CONNECTION:
      kreason= "KILL_CONNECTION";
      break;
    case THD::KILL_QUERY:
      kreason= "KILL_QUERY";
      break;
    case THD::KILLED_NO_VALUE:
      kreason= "KILLED_NO_VALUE";
      break;
    }
unknown's avatar
unknown committed
2699 2700
    fprintf(stderr, "Trying to get some variables.\n\
Some pointers may be invalid and cause the dump to abort...\n");
2701
    my_safe_print_str("thd->query", thd->query(), 1024);
unknown's avatar
unknown committed
2702
    fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
unknown's avatar
unknown committed
2703
    fprintf(stderr, "thd->killed=%s\n", kreason);
unknown's avatar
unknown committed
2704 2705
  }
  fprintf(stderr, "\
unknown's avatar
unknown committed
2706
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains\n\
unknown's avatar
unknown committed
2707
information that should help you find out what is causing the crash.\n");
2708
  fflush(stderr);
unknown's avatar
unknown committed
2709 2710
#endif /* HAVE_STACKTRACE */

2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721
#ifdef HAVE_INITGROUPS
  if (calling_initgroups)
    fprintf(stderr, "\n\
This crash occured while the server was calling initgroups(). This is\n\
often due to the use of a mysqld that is statically linked against glibc\n\
and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
mysqld that is not statically linked.\n");
#endif

2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
#ifdef HAVE_NPTL
  if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
    fprintf(stderr,"\n\
You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
You should either build a dynamically-linked binary, or force LinuxThreads\n\
to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
the documentation for your distribution on how to do that.\n");
#endif
  
2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742
  if (locked_in_memory)
  {
    fprintf(stderr, "\n\
The \"--memlock\" argument, which was enabled, uses system calls that are\n\
unreliable and unstable on some operating systems and operating-system\n\
versions (notably, some versions of Linux).  This crash could be due to use\n\
of those buggy OS calls.  You should consider whether you really need the\n\
\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
bugs.\n");
  }

2743
#ifdef HAVE_WRITE_CORE
2744 2745 2746 2747
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    fprintf(stderr, "Writing a core file\n");
    fflush(stderr);
2748
    my_write_core(sig);
2749
  }
2750 2751 2752 2753
#endif

#ifndef __WIN__
  /* On Windows, do not terminate, but pass control to exception filter */
2754
  exit(1);
2755
#endif
2756 2757
}

2758
#if !defined(__WIN__) && !defined(__NETWARE__)
unknown's avatar
unknown committed
2759 2760 2761 2762 2763 2764
#ifndef SA_RESETHAND
#define SA_RESETHAND 0
#endif
#ifndef SA_NODEFER
#define SA_NODEFER 0
#endif
2765

2766 2767
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
2768 2769 2770
static void init_signals(void)
{
  sigset_t set;
2771
  struct sigaction sa;
unknown's avatar
unknown committed
2772 2773
  DBUG_ENTER("init_signals");

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

unknown's avatar
unknown committed
2776
  if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
unknown's avatar
unknown committed
2777
  {
unknown's avatar
unknown committed
2778 2779 2780 2781
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
    sigemptyset(&sa.sa_mask);
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);

2782
#ifdef HAVE_STACKTRACE
2783
    my_init_stacktrace();
2784
#endif
unknown's avatar
unknown committed
2785 2786 2787
#if defined(__amiga__)
    sa.sa_handler=(void(*)())handle_segfault;
#else
unknown's avatar
unknown committed
2788
    sa.sa_handler=handle_segfault;
unknown's avatar
unknown committed
2789
#endif
unknown's avatar
unknown committed
2790
    sigaction(SIGSEGV, &sa, NULL);
2791
    sigaction(SIGABRT, &sa, NULL);
unknown's avatar
unknown committed
2792
#ifdef SIGBUS
unknown's avatar
unknown committed
2793
    sigaction(SIGBUS, &sa, NULL);
unknown's avatar
unknown committed
2794
#endif
unknown's avatar
unknown committed
2795
    sigaction(SIGILL, &sa, NULL);
2796
    sigaction(SIGFPE, &sa, NULL);
unknown's avatar
unknown committed
2797
  }
2798 2799 2800 2801 2802

#ifdef HAVE_GETRLIMIT
  if (test_flags & TEST_CORE_ON_SIGNAL)
  {
    /* Change limits so that we will get a core file */
2803
    STRUCT_RLIMIT rl;
2804
    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
unknown's avatar
unknown committed
2805
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
2806
      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");
2807 2808
  }
#endif
unknown's avatar
unknown committed
2809
  (void) sigemptyset(&set);
2810
  my_sigset(SIGPIPE,SIG_IGN);
unknown's avatar
unknown committed
2811
  sigaddset(&set,SIGPIPE);
2812
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
2813 2814
  sigaddset(&set,SIGQUIT);
  sigaddset(&set,SIGHUP);
2815 2816
#endif
  sigaddset(&set,SIGTERM);
2817 2818

  /* Fix signals if blocked by parents (can happen on Mac OS X) */
unknown's avatar
unknown committed
2819
  sigemptyset(&sa.sa_mask);
2820 2821 2822 2823 2824 2825
  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
2826 2827 2828
#ifdef SIGTSTP
  sigaddset(&set,SIGTSTP);
#endif
unknown's avatar
unknown committed
2829 2830
  if (thd_lib_detected != THD_LIB_LT)
    sigaddset(&set,THR_SERVER_ALARM);
2831
  if (test_flags & TEST_SIGINT)
2832
  {
2833
    my_sigset(thr_kill_signal, end_thread_signal);
2834 2835 2836
    // May be SIGINT
    sigdelset(&set, thr_kill_signal);
  }
2837 2838
  else
    sigaddset(&set,SIGINT);
2839 2840
  sigprocmask(SIG_SETMASK,&set,NULL);
  pthread_sigmask(SIG_SETMASK,&set,NULL);
2841 2842 2843 2844 2845 2846 2847 2848 2849
  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
2850 2851 2852 2853 2854

  (void) pthread_attr_init(&thr_attr);
#if !defined(HAVE_DEC_3_2_THREADS)
  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
  (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
2855
#if defined(__ia64__) || defined(__ia64)
2856 2857 2858 2859
  /*
    Peculiar things with ia64 platforms - it seems we only have half the
    stack size in reality, so we have to double it here
  */
2860
  pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2);
2861
#else
2862
  pthread_attr_setstacksize(&thr_attr,my_thread_stack_size);
2863
#endif
unknown's avatar
unknown committed
2864 2865
#endif

Marc Alff's avatar
Marc Alff committed
2866
  mysql_mutex_lock(&LOCK_thread_count);
Marc Alff's avatar
Marc Alff committed
2867 2868
  if ((error= mysql_thread_create(key_thread_signal_hand,
                                  &signal_thread, &thr_attr, signal_hand, 0)))
unknown's avatar
unknown committed
2869 2870 2871 2872 2873
  {
    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
		    error,errno);
    exit(1);
  }
Marc Alff's avatar
Marc Alff committed
2874 2875
  mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
2876 2877 2878 2879 2880 2881

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


unknown's avatar
unknown committed
2882
/** This threads handles all signals and alarms. */
unknown's avatar
unknown committed
2883
/* ARGSUSED */
2884
pthread_handler_t signal_hand(void *arg __attribute__((unused)))
unknown's avatar
unknown committed
2885 2886 2887 2888 2889
{
  sigset_t set;
  int sig;
  my_thread_init();				// Init new thread
  DBUG_ENTER("signal_hand");
unknown's avatar
unknown committed
2890 2891
  signal_thread_in_use= 1;

unknown's avatar
unknown committed
2892 2893
  /*
    Setup alarm handler
2894 2895
    This should actually be '+ max_number_of_slaves' instead of +10,
    but the +10 should be quite safe.
unknown's avatar
unknown committed
2896
  */
unknown's avatar
unknown committed
2897
  init_thr_alarm(thread_scheduler.max_threads +
2898
		 global_system_variables.max_insert_delayed_threads + 10);
2899
  if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
2900 2901 2902 2903 2904
  {
    (void) sigemptyset(&set);			// Setup up SIGINT for debug
    (void) sigaddset(&set,SIGINT);		// For debugging
    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
  }
unknown's avatar
unknown committed
2905 2906 2907 2908
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND
  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
#endif
2909
#ifndef IGNORE_SIGHUP_SIGQUIT
unknown's avatar
unknown committed
2910 2911
  (void) sigaddset(&set,SIGQUIT);
  (void) sigaddset(&set,SIGHUP);
2912 2913
#endif
  (void) sigaddset(&set,SIGTERM);
unknown's avatar
unknown committed
2914 2915 2916
  (void) sigaddset(&set,SIGTSTP);

  /* Save pid to this process (or thread on Linux) */
2917
  if (!opt_bootstrap)
2918 2919
    create_pid_file();

2920 2921 2922 2923 2924 2925 2926
#ifdef HAVE_STACK_TRACE_ON_SEGV
  if (opt_do_pstack)
  {
    sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid());
    pstack_install_segv_action(pstack_file_name);
  }
#endif /* HAVE_STACK_TRACE_ON_SEGV */
unknown's avatar
unknown committed
2927

2928 2929 2930 2931 2932
  /*
    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
2933
    should not be any other mysql_cond_signal() calls.
2934
  */
Marc Alff's avatar
Marc Alff committed
2935 2936 2937
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
2938

2939
  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
unknown's avatar
unknown committed
2940 2941 2942 2943 2944
  for (;;)
  {
    int error;					// Used when debugging
    if (shutdown_in_progress && !abort_loop)
    {
2945
      sig= SIGTERM;
unknown's avatar
unknown committed
2946 2947 2948 2949 2950
      error=0;
    }
    else
      while ((error=my_sigwait(&set,&sig)) == EINTR) ;
    if (cleanup_done)
2951
    {
2952
      DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
2953
      my_thread_end();
unknown's avatar
unknown committed
2954
      signal_thread_in_use= 0;
2955
      DBUG_LEAVE;                               // Must match DBUG_ENTER()
unknown's avatar
unknown committed
2956
      pthread_exit(0);				// Safety
2957
      return 0;                                 // Avoid compiler warnings
2958
    }
unknown's avatar
unknown committed
2959 2960 2961 2962 2963
    switch (sig) {
    case SIGTERM:
    case SIGQUIT:
    case SIGKILL:
#ifdef EXTRA_DEBUG
2964
      sql_print_information("Got signal %d to shutdown mysqld",sig);
unknown's avatar
unknown committed
2965
#endif
2966
      /* switch to the old log message processing */
2967 2968
      logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
                          opt_log ? LOG_FILE:LOG_NONE);
unknown's avatar
unknown committed
2969 2970 2971 2972 2973 2974
      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
      if (!abort_loop)
      {
	abort_loop=1;				// mark abort for threads
#ifdef USE_ONE_SIGNAL_HAND
	pthread_t tmp;
Marc Alff's avatar
Marc Alff committed
2975 2976 2977
        if (mysql_thread_create(0, /* Not instrumented */
                                &tmp, &connection_attrib, kill_server_thread,
                                (void*) &sig))
2978
	  sql_print_error("Can't create thread to kill server");
unknown's avatar
unknown committed
2979
#else
unknown's avatar
unknown committed
2980
	kill_server((void*) sig);	// MIT THREAD has a alarm thread
unknown's avatar
unknown committed
2981 2982 2983 2984
#endif
      }
      break;
    case SIGHUP:
unknown's avatar
unknown committed
2985 2986
      if (!abort_loop)
      {
unknown's avatar
unknown committed
2987
        bool not_used;
unknown's avatar
Merge  
unknown committed
2988
	mysql_print_status();		// Print some debug info
unknown's avatar
unknown committed
2989 2990
	reload_acl_and_cache((THD*) 0,
			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
unknown's avatar
Merge  
unknown committed
2991
			      REFRESH_GRANT |
unknown's avatar
unknown committed
2992
			      REFRESH_THREADS | REFRESH_HOSTS),
unknown's avatar
unknown committed
2993
			     (TABLE_LIST*) 0, &not_used); // Flush logs
unknown's avatar
unknown committed
2994
      }
2995
      /* reenable logs after the options were reloaded */
2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007
      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
3008 3009 3010 3011 3012 3013 3014 3015
      break;
#ifdef USE_ONE_SIGNAL_HAND
    case THR_SERVER_ALARM:
      process_alarm(sig);			// Trigger alarms.
      break;
#endif
    default:
#ifdef EXTRA_DEBUG
3016
      sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
unknown's avatar
unknown committed
3017 3018 3019 3020 3021 3022 3023
#endif
      break;					/* purecov: tested */
    }
  }
  return(0);					/* purecov: deadcode */
}

unknown's avatar
unknown committed
3024
static void check_data_home(const char *path)
unknown's avatar
unknown committed
3025
{}
unknown's avatar
unknown committed
3026

3027
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
3028 3029 3030
#endif	/* __WIN__*/


unknown's avatar
unknown committed
3031
/**
unknown's avatar
Merge  
unknown committed
3032
  All global error messages are sent here where the first one is stored
unknown's avatar
unknown committed
3033
  for the client.
unknown's avatar
unknown committed
3034 3035
*/
/* ARGSUSED */
Marc Alff's avatar
Marc Alff committed
3036
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3037

Marc Alff's avatar
Marc Alff committed
3038
void my_message_sql(uint error, const char *str, myf MyFlags)
unknown's avatar
unknown committed
3039
{
Marc Alff's avatar
Marc Alff committed
3040
  THD *thd= current_thd;
unknown's avatar
unknown committed
3041
  DBUG_ENTER("my_message_sql");
unknown's avatar
Merge  
unknown committed
3042
  DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
3043 3044

  DBUG_ASSERT(str != NULL);
unknown's avatar
Merge  
unknown committed
3045
  /*
3046 3047 3048 3049 3050 3051
    An error should have a valid error number (!= 0), so it can be caught
    in stored procedures by SQL exception handlers.
    Calling my_error() with error == 0 is a bug.
    Remaining known places to fix:
    - storage/myisam/mi_create.c, my_printf_error()
    TODO:
unknown's avatar
Merge  
unknown committed
3052 3053
    DBUG_ASSERT(error != 0);
  */
3054 3055 3056 3057 3058 3059 3060 3061

  if (error == 0)
  {
    /* At least, prevent new abuse ... */
    DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
    error= ER_UNKNOWN_ERROR;
  }

Sergey Vojtovich's avatar
Sergey Vojtovich committed
3062 3063
  mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);

Marc Alff's avatar
Marc Alff committed
3064
  if (thd)
unknown's avatar
unknown committed
3065
  {
Marc Alff's avatar
Marc Alff committed
3066 3067 3068 3069 3070 3071
    if (MyFlags & ME_FATALERROR)
      thd->is_fatal_error= 1;
    (void) thd->raise_condition(error,
                                NULL,
                                MYSQL_ERROR::WARN_LEVEL_ERROR,
                                str);
unknown's avatar
unknown committed
3072
  }
unknown's avatar
unknown committed
3073
  if (!thd || MyFlags & ME_NOREFRESH)
unknown's avatar
unknown committed
3074
    sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
Marc Alff's avatar
Marc Alff committed
3075
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
3076 3077
}

3078

3079
#ifndef EMBEDDED_LIBRARY
3080 3081 3082 3083
extern "C" void *my_str_malloc_mysqld(size_t size);
extern "C" void my_str_free_mysqld(void *ptr);

void *my_str_malloc_mysqld(size_t size)
3084 3085 3086 3087 3088
{
  return my_malloc(size, MYF(MY_FAE));
}


3089
void my_str_free_mysqld(void *ptr)
3090
{
3091
  my_free((uchar*)ptr, MYF(MY_FAE));
3092
}
3093
#endif /* EMBEDDED_LIBRARY */
3094 3095


unknown's avatar
unknown committed
3096 3097
#ifdef __WIN__

3098
pthread_handler_t handle_shutdown(void *arg)
unknown's avatar
unknown committed
3099 3100 3101 3102 3103 3104
{
  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
3105
#if !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
3106
  if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
3107
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
3108 3109 3110 3111 3112
     kill_server(MYSQL_KILL_SIGNAL);
  return 0;
}
#endif

3113
const char *load_default_groups[]= {
3114
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
3115 3116
"mysql_cluster",
#endif
unknown's avatar
Merge  
unknown committed
3117 3118
"mysqld","server", MYSQL_BASE_VERSION, 0, 0};

3119
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
3120 3121
static const int load_default_groups_sz=
sizeof(load_default_groups)/sizeof(load_default_groups[0]);
unknown's avatar
Merge  
unknown committed
3122
#endif
unknown's avatar
unknown committed
3123

unknown's avatar
unknown committed
3124

unknown's avatar
unknown committed
3125 3126
/**
  Initialize one of the global date/time format variables.
3127

unknown's avatar
unknown committed
3128 3129
  @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
3130

unknown's avatar
unknown committed
3131
  @retval
3132
    0 ok
unknown's avatar
unknown committed
3133
  @retval
3134 3135 3136
    1 error
*/

unknown's avatar
unknown committed
3137
static bool init_global_datetime_format(timestamp_type format_type,
3138
                                        DATE_TIME_FORMAT *format)
3139
{
3140 3141 3142 3143 3144
  /*
    Get command line option
    format->format.str is already set by my_getopt
  */
  format->format.length= strlen(format->format.str);
3145

3146
  if (parse_date_time_format(format_type, format))
3147
  {
3148 3149 3150
    fprintf(stderr, "Wrong date/time format specifier: %s\n",
            format->format.str);
    return true;
3151
  }
3152
  return false;
3153 3154
}

unknown's avatar
unknown committed
3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225
SHOW_VAR com_status_vars[]= {
  {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
  {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), 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},
  {"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},
  {"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},
  {"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},
  {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
  {"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
3226
  {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3227 3228 3229 3230 3231 3232 3233
  {"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},
  {"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},
Marc Alff's avatar
Marc Alff committed
3234
  {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269
  {"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},
  {"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_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
  {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
  {"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},
  {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
  {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
  {"show_new_master",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), 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
3270 3271
  {"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},
3272
  {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287
  {"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},
  {"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},
  {"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},
  {"slave_start",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
  {"slave_stop",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
  {"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
3288
  {"stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
  {"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},
  {"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},
3302
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
3303
};
3304

3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316
/**
  Create the name of the default general log file
  
  @param[IN] buff    Location for building new string.
  @param[IN] log_ext The extension for the file (e.g .log)
  @returns Pointer to a new string containing the name
*/
static inline char *make_default_log_name(char *buff,const char* log_ext)
{
  return make_log_name(buff, default_logfile_name, log_ext);
}

Marc Alff's avatar
Marc Alff committed
3317
static int init_common_variables()
unknown's avatar
unknown committed
3318
{
3319
  char buff[FN_REFLEN];
unknown's avatar
unknown committed
3320
  umask(((~my_umask) & 0666));
unknown's avatar
Merge  
unknown committed
3321
  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
unknown's avatar
unknown committed
3322 3323
  tzset();			// Set tzname

unknown's avatar
SCRUM  
unknown committed
3324
  max_system_variables.pseudo_thread_id= (ulong)~0;
3325
  server_start_time= flush_status_time= my_time(0);
3326 3327
  rpl_filter= new Rpl_filter;
  binlog_filter= new Rpl_filter;
unknown's avatar
unknown committed
3328
  if (!rpl_filter || !binlog_filter)
3329 3330
  {
    sql_perror("Could not allocate replication and binlog filters");
3331
    return 1;
3332 3333
  }

3334 3335
  if (init_thread_environment() ||
      mysql_init_variables())
unknown's avatar
unknown committed
3336
    return 1;
unknown's avatar
unknown committed
3337

unknown's avatar
unknown committed
3338 3339 3340
#ifdef HAVE_TZNAME
  {
    struct tm tm_tmp;
3341
    localtime_r(&server_start_time,&tm_tmp);
3342 3343 3344 3345
    strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
            sizeof(system_time_zone)-1);

 }
unknown's avatar
unknown committed
3346
#endif
3347
  /*
unknown's avatar
unknown committed
3348
    We set SYSTEM time zone as reasonable default and
3349 3350 3351 3352 3353
    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
3354

unknown's avatar
unknown committed
3355
  /*
3356
    Init mutexes for the global MYSQL_BIN_LOG objects.
unknown's avatar
unknown committed
3357
    As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3358 3359
    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
3360 3361
  */
  mysql_bin_log.init_pthread_objects();
3362

3363 3364 3365 3366 3367
  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
  {
    strmake(glob_hostname, STRING_WITH_LEN("localhost"));
    sql_print_warning("gethostname failed, using '%s' as hostname",
                      glob_hostname);
3368
    strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
3369 3370
  }
  else
3371 3372 3373 3374
    strmake(default_logfile_name, glob_hostname, 
	    sizeof(default_logfile_name)-5);

  strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name)-5);
3375
  strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
unknown's avatar
unknown committed
3376

3377 3378 3379 3380 3381 3382 3383 3384
  /*
    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.
  */
Guilhem Bichot's avatar
Guilhem Bichot committed
3385
  default_storage_engine= const_cast<char *>("MyISAM");
3386

3387 3388 3389
  /*
    Add server status variables to the dynamic list of
    status variables that is shown by SHOW STATUS.
3390
    Later, in plugin_init, and mysql_install_plugin
3391 3392 3393 3394 3395
    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
3396 3397 3398 3399 3400
#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
3401
    There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
unknown's avatar
unknown committed
3402 3403 3404 3405 3406 3407 3408 3409
    (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
3410
      Com_stmt_reprepare       => com_stmt_reprepare
unknown's avatar
unknown committed
3411 3412 3413
      Com_stmt_reset           => com_stmt_reset
      Com_stmt_send_long_data  => com_stmt_send_long_data

3414 3415 3416
    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
3417
  */
3418
  compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
unknown's avatar
unknown committed
3419
                     SQLCOM_END + 8);
unknown's avatar
unknown committed
3420 3421
#endif

Marc Alff's avatar
Marc Alff committed
3422
  if (get_options(&remaining_argc, &remaining_argv))
3423
    return 1;
3424 3425
  set_server_version();

unknown's avatar
unknown committed
3426 3427 3428
  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
3429 3430 3431 3432
#ifdef HAVE_LARGE_PAGES
  /* Initialize large page size */
  if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
  {
3433 3434
      DBUG_PRINT("info", ("Large page set, large_page_size = %d",
                 opt_large_page_size));
unknown's avatar
Merge  
unknown committed
3435 3436 3437
      my_use_large_pages= 1;
      my_large_page_size= opt_large_page_size;
  }
3438 3439 3440 3441 3442 3443 3444 3445
  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
3446
#endif /* HAVE_LARGE_PAGES */
3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463
#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;
   int max_desired_page_size;
3464
   int max_page_size;
3465
   if (opt_super_large_pages)
3466
     max_page_size= SUPER_LARGE_PAGESIZE;
3467
   else
3468
     max_page_size= LARGE_PAGESIZE;
3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497
   nelem = getpagesizes(NULL, 0);
   if (nelem > 0)
   {
     size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
     if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
     {
       size_t i, max_page_size= 0;
       for (i= 0; i < nelem; i++)
       {
         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
3498

unknown's avatar
unknown committed
3499 3500
  /* connections and databases needs lots of files */
  {
3501
    uint files, wanted_files, max_open_files;
3502

3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517
    /* MyISAM requires two file handles per table. */
    wanted_files= 10+max_connections+table_cache_size*2;
    /*
      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).
    */
    max_open_files= max(max(wanted_files, max_connections*5),
                        open_files_limit);
    files= my_set_max_open_files(max_open_files);
3518 3519

    if (files < wanted_files)
unknown's avatar
unknown committed
3520
    {
3521 3522
      if (!open_files_limit)
      {
3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536
        /*
          If we have requested too much file handles than we bring
          max_connections in supported bounds.
        */
        max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
                                     max_connections);
        /*
          Decrease table_cache_size according to max_connections, but
          not below TABLE_OPEN_CACHE_MIN.  Outer min() ensures that we
          never increase table_cache_size automatically (that could
          happen if max_connections is decreased above).
        */
        table_cache_size= (ulong) min(max((files-10-max_connections)/2,
                                          TABLE_OPEN_CACHE_MIN),
unknown's avatar
unknown committed
3537
                                      table_cache_size);
3538 3539 3540
	DBUG_PRINT("warning",
		   ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
		    files, max_connections, table_cache_size));
unknown's avatar
unknown committed
3541
	if (global_system_variables.log_warnings)
3542
	  sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
3543 3544
			files, max_connections, table_cache_size);
      }
unknown's avatar
unknown committed
3545
      else if (global_system_variables.log_warnings)
3546
	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
3547
    }
unknown's avatar
unknown committed
3548
    open_files_limit= files;
unknown's avatar
unknown committed
3549 3550
  }
  unireg_init(opt_specialflag); /* Set up extern variabels */
3551 3552 3553 3554 3555 3556 3557
  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;
3558 3559
  if (init_errmessage())	/* Read error messages from file */
    return 1;
3560
  init_client_errs();
unknown's avatar
unknown committed
3561
  lex_init();
3562 3563
  if (item_create_init())
    return 1;
unknown's avatar
unknown committed
3564 3565 3566
  item_init();
  mysys_uses_curses=0;
#ifdef USE_REGEX
unknown's avatar
unknown committed
3567
  my_regex_init(&my_charset_latin1);
unknown's avatar
unknown committed
3568
#endif
3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
  /*
    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;
  }

3596 3597
  if (default_collation_name)
  {
unknown's avatar
unknown committed
3598 3599
    CHARSET_INFO *default_collation;
    default_collation= get_charset_by_name(default_collation_name, MYF(0));
unknown's avatar
unknown committed
3600 3601
    if (!default_collation)
    {
3602
      sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
unknown's avatar
unknown committed
3603 3604 3605
      return 1;
    }
    if (!my_charset_same(default_charset_info, default_collation))
3606
    {
3607
      sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
3608 3609 3610 3611 3612 3613
		      default_collation_name,
		      default_charset_info->csname);
      return 1;
    }
    default_charset_info= default_collation;
  }
3614 3615 3616 3617
  /* 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;
3618
  global_system_variables.character_set_results= default_charset_info;
3619
  global_system_variables.character_set_client=  default_charset_info;
unknown's avatar
unknown committed
3620 3621 3622 3623 3624 3625
  if (!(character_set_filesystem= 
        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;

3626 3627 3628
  if (!(my_default_lc_time_names=
        my_locale_by_name(lc_time_names_name)))
  {
unknown's avatar
unknown committed
3629
    sql_print_error("Unknown locale: '%s'", lc_time_names_name);
3630 3631 3632
    return 1;
  }
  global_system_variables.lc_time_names= my_default_lc_time_names;
3633

3634 3635 3636 3637 3638
  /* check log options and issue warnings if needed */
  if (opt_log && opt_logname && !(log_output_options & LOG_FILE) &&
      !(log_output_options & LOG_NONE))
    sql_print_warning("Although a path was specified for the "
                      "--log option, log tables are used. "
unknown's avatar
unknown committed
3639
                      "To enable logging to files use the --log-output option.");
3640 3641 3642 3643

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

3647 3648 3649 3650 3651 3652
#define FIX_LOG_VAR(VAR, ALT)                                   \
  if (!VAR || !*VAR)                                            \
  {                                                             \
    x_free(VAR); /* it could be an allocated empty string "" */ \
    VAR= my_strdup(ALT, MYF(0));                                \
  }
3653

3654 3655 3656 3657
  FIX_LOG_VAR(opt_logname,
              make_default_log_name(buff, ".log"));
  FIX_LOG_VAR(opt_slow_logname,
              make_default_log_name(buff, "-slow.log"));
3658

Ingo Struewing's avatar
Ingo Struewing committed
3659 3660 3661 3662 3663 3664
#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) */

3665
#if (ENABLE_TEMP_POOL)
unknown's avatar
unknown committed
3666
  if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
3667
    return 1;
3668 3669 3670 3671
#else
  use_temp_pool= 0;
#endif

unknown's avatar
unknown committed
3672
  if (my_database_names_init())
unknown's avatar
unknown committed
3673 3674
    return 1;

3675 3676 3677 3678 3679 3680
  /*
    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));
3681 3682
  lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
  if (!lower_case_table_names && lower_case_file_system == 1)
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711
  {
    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 &&
           !(lower_case_file_system=
             (test_if_case_insensitive(mysql_real_data_home) == 1)))
  {
    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;
  }
3712 3713 3714 3715 3716
  else
  {
    lower_case_file_system=
      (test_if_case_insensitive(mysql_real_data_home) == 1);
  }
3717 3718 3719 3720 3721 3722

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

unknown's avatar
unknown committed
3723 3724
  return 0;
}
unknown's avatar
unknown committed
3725

3726 3727

static int init_thread_environment()
unknown's avatar
unknown committed
3728
{
Marc Alff's avatar
Marc Alff committed
3729 3730 3731 3732
  mysql_mutex_init(key_LOCK_mysql_create_db,
                   &LOCK_mysql_create_db, MY_MUTEX_INIT_SLOW);
  mysql_mutex_init(key_LOCK_lock_db, &LOCK_lock_db, MY_MUTEX_INIT_SLOW);
  mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
3733
  mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
3734
  mysql_mutex_init(key_LOCK_mapped_file, &LOCK_mapped_file, MY_MUTEX_INIT_SLOW);
Marc Alff's avatar
Marc Alff committed
3735
  mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
Marc Alff's avatar
Marc Alff committed
3736
  mysql_mutex_init(key_LOCK_delayed_insert,
Marc Alff's avatar
Marc Alff committed
3737 3738 3739 3740 3741
                   &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
3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760
  mysql_mutex_init(key_LOCK_manager,
                   &LOCK_manager, MY_MUTEX_INIT_FAST);
  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);
  mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
                    &LOCK_system_variables_hash);
  mysql_mutex_init(key_LOCK_global_read_lock,
                   &LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
  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);
  mysql_mutex_init(key_LOCK_uuid_generator,
                   &LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
  mysql_mutex_init(key_LOCK_connection_count,
                   &LOCK_connection_count, MY_MUTEX_INIT_FAST);
3761
#ifdef HAVE_OPENSSL
Marc Alff's avatar
Marc Alff committed
3762 3763
  mysql_mutex_init(key_LOCK_des_key_file,
                   &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
unknown's avatar
unknown committed
3764 3765 3766 3767
#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)
3768
    mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
unknown's avatar
unknown committed
3769 3770 3771 3772 3773 3774
  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
3775
#endif
Marc Alff's avatar
Marc Alff committed
3776 3777 3778
  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
3779
  mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
Marc Alff's avatar
Marc Alff committed
3780
  mysql_cond_init(key_COND_refresh, &COND_refresh, NULL);
Marc Alff's avatar
Marc Alff committed
3781
  mysql_cond_init(key_COND_global_read_lock, &COND_global_read_lock, NULL);
Marc Alff's avatar
Marc Alff committed
3782 3783
  mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
  mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
Marc Alff's avatar
Marc Alff committed
3784
  mysql_cond_init(key_COND_manager, &COND_manager, NULL);
unknown's avatar
SCRUM  
unknown committed
3785
#ifdef HAVE_REPLICATION
Marc Alff's avatar
Marc Alff committed
3786 3787
  mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
  mysql_cond_init(key_COND_rpl_status, &COND_rpl_status, NULL);
3788
#endif
Marc Alff's avatar
Marc Alff committed
3789 3790 3791
  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
3792
  sp_cache_init();
3793
#ifdef HAVE_EVENT_SCHEDULER
3794
  Events::init_mutexes();
3795
#endif
unknown's avatar
unknown committed
3796 3797 3798 3799 3800
  /* 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
3801

unknown's avatar
unknown committed
3802 3803 3804 3805 3806 3807 3808 3809 3810
  if (pthread_key_create(&THR_THD,NULL) ||
      pthread_key_create(&THR_MALLOC,NULL))
  {
    sql_print_error("Can't create thread-keys");
    return 1;
  }
  return 0;
}

3811

unknown's avatar
unknown committed
3812
#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
3813 3814 3815 3816 3817 3818 3819 3820 3821
static unsigned long openssl_id_function()
{ 
  return (unsigned long) pthread_self();
} 


static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
{ 
  openssl_lock_t *lock= new openssl_lock_t;
3822
  mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
3823 3824 3825 3826 3827 3828 3829
  return lock;
}


static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file, 
				    int line)
{
3830
  mysql_rwlock_destroy(&lock->lock);
3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
  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);
}


static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, 
			 int line)
{
  int err;
  char const *what;

  switch (mode) {
  case CRYPTO_LOCK|CRYPTO_READ:
    what = "read lock";
3856
    err= mysql_rwlock_rdlock(&lock->lock);
3857 3858 3859
    break;
  case CRYPTO_LOCK|CRYPTO_WRITE:
    what = "write lock";
3860
    err= mysql_rwlock_wrlock(&lock->lock);
3861 3862 3863 3864
    break;
  case CRYPTO_UNLOCK|CRYPTO_READ:
  case CRYPTO_UNLOCK|CRYPTO_WRITE:
    what = "unlock";
3865
    err= mysql_rwlock_unlock(&lock->lock);
3866 3867 3868 3869 3870 3871 3872 3873
    break;
  default:
    /* Unknown locking mode. */
    sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
    abort();
  }
  if (err) 
  {
3874
    sql_print_error("Fatal: can't %s OpenSSL lock", what);
3875 3876 3877 3878 3879 3880
    abort();
  }
}
#endif /* HAVE_OPENSSL */


3881 3882
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
3883 3884
static void init_ssl()
{
unknown's avatar
unknown committed
3885 3886 3887
#ifdef HAVE_OPENSSL
  if (opt_use_ssl)
  {
3888 3889
    enum enum_ssl_init_error error= SSL_INITERR_NOERROR;

3890 3891 3892
    /* 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,
3893
					  opt_ssl_cipher, &error);
unknown's avatar
Merge  
unknown committed
3894
    DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
unknown's avatar
unknown committed
3895
    if (!ssl_acceptor_fd)
3896
    {
3897
      sql_print_warning("Failed to setup SSL");
3898
      sql_print_warning("SSL error: %s", sslGetErrString(error));
unknown's avatar
unknown committed
3899
      opt_use_ssl = 0;
3900
      have_ssl= SHOW_OPTION_DISABLED;
3901 3902 3903 3904
    }
  }
  else
  {
3905
    have_ssl= SHOW_OPTION_DISABLED;
unknown's avatar
unknown committed
3906
  }
unknown's avatar
unknown committed
3907 3908
  if (des_key_file)
    load_des_key_file(des_key_file);
unknown's avatar
unknown committed
3909
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
3910
}
unknown's avatar
unknown committed
3911

3912

3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923
static void end_ssl()
{
#ifdef HAVE_OPENSSL
  if (ssl_acceptor_fd)
  {
    free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
    ssl_acceptor_fd= 0;
  }
#endif /* HAVE_OPENSSL */
}

3924
#endif /* EMBEDDED_LIBRARY */
3925

3926

unknown's avatar
unknown committed
3927 3928
static int init_server_components()
{
3929
  FILE *reopen;
3930
  DBUG_ENTER("init_server_components");
unknown's avatar
unknown committed
3931 3932 3933 3934
  /*
    We need to call each of these following functions to ensure that
    all things are initialized so that unireg_abort() doesn't fail
  */
3935 3936
  mdl_init();
  if (table_def_init() | hostname_cache_init())
3937
    unireg_abort(1);
unknown's avatar
unknown committed
3938

3939
  query_cache_set_min_res_unit(query_cache_min_res_unit);
unknown's avatar
unknown committed
3940
  query_cache_init();
unknown's avatar
unknown committed
3941
  query_cache_resize(query_cache_size);
3942
  randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
3943
  setup_fpu();
unknown's avatar
unknown committed
3944
  init_thr_lock();
unknown's avatar
SCRUM  
unknown committed
3945
#ifdef HAVE_REPLICATION
3946
  init_slave_list();
3947
#endif
unknown's avatar
unknown committed
3948

3949 3950
  /* Setup logs */

3951 3952 3953 3954 3955 3956
  /*
    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.
  */
  if (opt_error_log && !opt_help)
3957 3958
  {
    if (!log_error_file_ptr[0])
3959
      fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
3960 3961 3962 3963 3964
                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);
    if (!log_error_file[0])
3965
      opt_error_log= 0;                         // Too long file name
3966 3967 3968 3969 3970
    else
    {
#ifndef EMBEDDED_LIBRARY
      if (freopen(log_error_file, "a+", stdout))
#endif
3971
      {
3972
        reopen= freopen(log_error_file, "a+", stderr);
3973 3974
        setbuf(stderr, NULL);
      }
3975 3976 3977
    }
  }

Konstantin Osipov's avatar
Konstantin Osipov committed
3978 3979 3980
  proc_info_hook= (const char *(*)(void *, const char *, const char *,
                                   const char *, const unsigned int))
                  set_thd_proc_info;
Marc Alff's avatar
Marc Alff committed
3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
#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 */

unknown's avatar
WL#3201  
unknown committed
3993 3994 3995 3996 3997 3998
  if (xid_cache_init())
  {
    sql_print_error("Out of memory");
    unireg_abort(1);
  }

He Zhenxing's avatar
He Zhenxing committed
3999 4000 4001 4002 4003 4004 4005
  /* initialize delegates for extension observers */
  if (delegates_init())
  {
    sql_print_error("Initialize extension delegates failed");
    unireg_abort(1);
  }

unknown's avatar
unknown committed
4006
  /* need to configure logging before initializing storage engines */
unknown's avatar
unknown committed
4007
  if (opt_update_log)
unknown's avatar
unknown committed
4008
  {
unknown's avatar
Merge  
unknown committed
4009 4010 4011 4012
    /*
      Update log is removed since 5.0. But we still accept the option.
      The idea is if the user already uses the binlog and the update log,
      we completely ignore any option/variable related to the update log, like
unknown's avatar
unknown committed
4013 4014
      if the update log did not exist. But if the user uses only the update
      log, then we translate everything into binlog for him (with warnings).
unknown's avatar
Merge  
unknown committed
4015 4016 4017
      Implementation of the above :
      - If mysqld is started with --log-update and --log-bin,
      ignore --log-update (print a warning), push a warning when SQL_LOG_UPDATE
4018
      is used,
unknown's avatar
Merge  
unknown committed
4019 4020 4021 4022
      This will completely ignore SQL_LOG_UPDATE
      - If mysqld is started with --log-update only,
      change it to --log-bin (with the filename passed to log-update,
      plus '-bin') (print a warning), push a warning when SQL_LOG_UPDATE is
4023
      used.
unknown's avatar
Merge  
unknown committed
4024 4025 4026
      This will translate SQL_LOG_UPDATE to SQL_LOG_BIN.
    */
    if (opt_bin_log)
unknown's avatar
unknown committed
4027
    {
unknown's avatar
Merge  
unknown committed
4028 4029 4030 4031 4032 4033 4034 4035 4036 4037
      opt_sql_bin_update= 0;
      sql_print_error("The update log is no longer supported by MySQL in \
version 5.0 and above. It is replaced by the binary log.");
    }
    else
    {
      opt_sql_bin_update= 1;
      opt_bin_log= 1;
      if (opt_update_logname)
      {
unknown's avatar
unknown committed
4038
        /* as opt_bin_log==0, no need to free opt_bin_logname */
unknown's avatar
Merge  
unknown committed
4039
        if (!(opt_bin_logname= my_strdup(opt_update_logname, MYF(MY_WME))))
4040 4041 4042 4043
        {
          sql_print_error("Out of memory");
          return EXIT_OUT_OF_MEMORY;
        }
unknown's avatar
Merge  
unknown committed
4044 4045 4046 4047 4048 4049 4050 4051
        sql_print_error("The update log is no longer supported by MySQL in \
version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
with --log-bin='%s' instead.",opt_bin_logname);
      }
      else
        sql_print_error("The update log is no longer supported by MySQL in \
version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
with --log-bin instead.");
unknown's avatar
unknown committed
4052
    }
4053
  }
unknown's avatar
Merge  
unknown committed
4054
  if (opt_log_slave_updates && !opt_bin_log)
unknown's avatar
unknown committed
4055
  {
4056
    sql_print_warning("You need to use --log-bin to make "
4057
                    "--log-slave-updates work.");
4058
  }
4059 4060 4061
  if (!opt_bin_log && binlog_format_used)
    sql_print_warning("You need to use --log-bin to make "
                      "--binlog-format work.");
4062

4063
  /* Check that we have not let the format to unspecified at this point */
4064
  DBUG_ASSERT((uint)global_system_variables.binlog_format <=
4065
              array_elements(binlog_format_names)-1);
4066

unknown's avatar
unknown committed
4067
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
4068 4069
  if (opt_log_slave_updates && replicate_same_server_id)
  {
4070 4071 4072
    if (opt_bin_log)
    {
      sql_print_error("using --replicate-same-server-id in conjunction with \
unknown's avatar
unknown committed
4073 4074
--log-slave-updates is impossible, it would lead to infinite loops in this \
server.");
4075 4076 4077 4078 4079 4080
      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
4081
  }
unknown's avatar
unknown committed
4082
#endif
4083

unknown's avatar
Merge  
unknown committed
4084
  if (opt_bin_log)
unknown's avatar
unknown committed
4085
  {
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106
    /* Reports an error and aborts, if the --log-bin's path 
       is a directory.*/
    if (opt_bin_logname && 
        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
4107 4108 4109 4110
    char buf[FN_REFLEN];
    const char *ln;
    ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
    if (!opt_bin_logname && !opt_binlog_index_name)
unknown's avatar
unknown committed
4111 4112
    {
      /*
unknown's avatar
Merge  
unknown committed
4113 4114 4115 4116 4117
        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.
unknown's avatar
unknown committed
4118
      */
unknown's avatar
Merge  
unknown committed
4119 4120 4121 4122 4123
      sql_print_warning("No argument was provided to --log-bin, and "
                        "--log-bin-index was not used; so replication "
                        "may break when this MySQL server acts as a "
                        "master and has his hostname changed!! Please "
                        "use '--log-bin=%s' to avoid this problem.", ln);
unknown's avatar
unknown committed
4124
    }
unknown's avatar
Merge  
unknown committed
4125
    if (ln == buf)
unknown's avatar
unknown committed
4126
    {
unknown's avatar
Merge  
unknown committed
4127 4128
      my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR));
      opt_bin_logname=my_strdup(buf, MYF(0));
unknown's avatar
unknown committed
4129
    }
4130
    if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
unknown's avatar
unknown committed
4131 4132 4133
    {
      unireg_abort(1);
    }
unknown's avatar
unknown committed
4134 4135
  }

4136 4137 4138 4139 4140 4141 4142
  /* call ha_init_key_cache() on all key caches to init them */
  process_key_caches(&ha_init_key_cache);

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

Marc Alff's avatar
Marc Alff committed
4143
  if (plugin_init(&remaining_argc, remaining_argv,
4144 4145 4146 4147 4148
                  (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
                  (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
  {
    sql_print_error("Failed to initialize plugins.");
    unireg_abort(1);
unknown's avatar
unknown committed
4149
  }
4150
  plugins_are_initialized= TRUE;  /* Don't separate from init function */
unknown's avatar
unknown committed
4151

4152 4153 4154 4155 4156 4157
  have_csv= plugin_status(STRING_WITH_LEN("csv"),
                          MYSQL_STORAGE_ENGINE_PLUGIN);
  have_ndbcluster= plugin_status(STRING_WITH_LEN("ndbcluster"),
                                 MYSQL_STORAGE_ENGINE_PLUGIN);
  have_partitioning= plugin_status(STRING_WITH_LEN("partition"),
                                   MYSQL_STORAGE_ENGINE_PLUGIN);
unknown's avatar
WL#2936  
unknown committed
4158 4159

  /* we do want to exit if there are any other unknown options */
Marc Alff's avatar
Marc Alff committed
4160
  if (remaining_argc > 1)
unknown's avatar
WL#2936  
unknown committed
4161 4162
  {
    int ho_error;
unknown's avatar
unknown committed
4163
    struct my_option no_opts[]=
unknown's avatar
WL#2936  
unknown committed
4164 4165 4166 4167 4168
    {
      {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
4169
      that there are unprocessed options.
unknown's avatar
WL#2936  
unknown committed
4170 4171
    */
    my_getopt_skip_unknown= 0;
unknown's avatar
unknown committed
4172

Marc Alff's avatar
Marc Alff committed
4173
    if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
4174
                                  mysqld_get_one_option)))
unknown's avatar
WL#2936  
unknown committed
4175
      unireg_abort(ho_error);
Marc Alff's avatar
Marc Alff committed
4176 4177 4178
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
4179
    my_getopt_skip_unknown= TRUE;
unknown's avatar
unknown committed
4180

Marc Alff's avatar
Marc Alff committed
4181
    if (remaining_argc > 1)
unknown's avatar
WL#2936  
unknown committed
4182 4183
    {
      fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n"
unknown's avatar
unknown committed
4184
              "Use --verbose --help to get a list of available options\n",
Marc Alff's avatar
Marc Alff committed
4185
              my_progname, remaining_argv[1]);
unknown's avatar
WL#2936  
unknown committed
4186 4187
      unireg_abort(1);
    }
unknown's avatar
unknown committed
4188 4189
  }

4190 4191 4192
  if (opt_help)
    unireg_abort(0);

unknown's avatar
WL#2936  
unknown committed
4193
  /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
4194 4195
  if (!DEFAULT_ERRMSGS[0][0])
    unireg_abort(1);  
unknown's avatar
WL#2936  
unknown committed
4196

unknown's avatar
unknown committed
4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224
  /* We have to initialize the storage engines before CSV logging */
  if (ha_init())
  {
    sql_print_error("Can't init databases");
    unireg_abort(1);
  }

#ifdef WITH_CSV_STORAGE_ENGINE
  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
WL#2936  
unknown committed
4225 4226
    LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
    if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
unknown's avatar
unknown committed
4227
    {
4228
      /* purecov: begin inspected */
unknown's avatar
unknown committed
4229 4230
      sql_print_error("CSV engine is not present, falling back to the "
                      "log files");
unknown's avatar
unknown committed
4231
      log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
4232
      /* purecov: end */
unknown's avatar
unknown committed
4233 4234 4235 4236 4237 4238 4239 4240 4241 4242
    }

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

4243
  /*
4244
    Set the default storage engine
4245
  */
4246 4247 4248 4249 4250 4251
  LEX_STRING name= { default_storage_engine, strlen(default_storage_engine) };
  plugin_ref plugin;
  handlerton *hton;
  if ((plugin= ha_resolve_by_name(0, &name)))
    hton= plugin_data(plugin, handlerton*);
  else
4252
  {
4253 4254 4255 4256 4257 4258 4259
    sql_print_error("Unknown/unsupported storage engine: %s",
                    default_storage_engine);
    unireg_abort(1);
  }
  if (!ha_storage_engine_is_enabled(hton))
  {
    if (!opt_bootstrap)
4260
    {
4261 4262
      sql_print_error("Default storage engine (%s) is not available",
                      default_storage_engine);
4263 4264
      unireg_abort(1);
    }
4265 4266 4267 4268 4269 4270 4271 4272 4273 4274
    DBUG_ASSERT(global_system_variables.table_plugin);
  }
  else
  {
    /*
      Need to unlock as global_system_variables.table_plugin
      was acquired during plugin_init()
    */
    plugin_unlock(0, global_system_variables.table_plugin);
    global_system_variables.table_plugin= plugin;
4275 4276
  }

unknown's avatar
unknown committed
4277 4278 4279 4280
  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
4281

unknown's avatar
unknown committed
4282
  if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
unknown's avatar
Merge  
unknown committed
4283 4284 4285 4286 4287
  {
    sql_print_error("Can't init tc log");
    unireg_abort(1);
  }

unknown's avatar
unknown committed
4288 4289 4290 4291 4292
  if (ha_recover(0))
  {
    unireg_abort(1);
  }

unknown's avatar
Merge  
unknown committed
4293
  if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
4294
                                        WRITE_CACHE, 0, max_binlog_size, 0, TRUE))
unknown's avatar
unknown committed
4295
    unireg_abort(1);
unknown's avatar
Merge  
unknown committed
4296 4297 4298

#ifdef HAVE_REPLICATION
  if (opt_bin_log && expire_logs_days)
unknown's avatar
unknown committed
4299
  {
4300
    time_t purge_time= server_start_time - expire_logs_days*24*60*60;
unknown's avatar
Merge  
unknown committed
4301 4302
    if (purge_time >= 0)
      mysql_bin_log.purge_logs_before_date(purge_time);
unknown's avatar
unknown committed
4303
  }
unknown's avatar
Merge  
unknown committed
4304
#endif
unknown's avatar
unknown committed
4305 4306 4307 4308
#ifdef __NETWARE__
  /* Increasing stacksize of threads on NetWare */
  pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
#endif
unknown's avatar
Merge  
unknown committed
4309 4310 4311

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

unknown's avatar
unknown committed
4313
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
4314
  if (locked_in_memory && !getuid())
4315
  {
4316
    if (setreuid((uid_t)-1, 0) == -1)
4317
    {                        // this should never happen
4318
      sql_perror("setreuid");
4319 4320
      unireg_abort(1);
    }
4321 4322
    if (mlockall(MCL_CURRENT))
    {
4323
      if (global_system_variables.log_warnings)
4324
	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
unknown's avatar
unknown committed
4325
      locked_in_memory= 0;
4326
    }
4327 4328
    if (user_info)
      set_user(mysqld_user, user_info);
4329
  }
unknown's avatar
merged  
unknown committed
4330
  else
4331
#endif
unknown's avatar
merged  
unknown committed
4332
    locked_in_memory=0;
4333

4334
  ft_init_stopwords();
unknown's avatar
unknown committed
4335

unknown's avatar
unknown committed
4336
  init_max_user_conn();
4337
  init_update_queries();
4338
  DBUG_RETURN(0);
unknown's avatar
unknown committed
4339
}
unknown's avatar
unknown committed
4340

4341

4342
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
4343

unknown's avatar
unknown committed
4344 4345 4346
static void create_shutdown_thread()
{
#ifdef __WIN__
4347 4348
  hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
  pthread_t hThread;
Marc Alff's avatar
Marc Alff committed
4349 4350
  if (mysql_thread_create(key_thread_handle_shutdown,
                          &hThread, &connection_attrib, handle_shutdown, 0))
4351
    sql_print_warning("Can't create thread to handle shutdown requests");
unknown's avatar
unknown committed
4352

4353 4354
  // On "Stop Service" we have to do regular shutdown
  Service.SetShutdownEvent(hEventShutdown);
unknown's avatar
unknown committed
4355
#endif /* __WIN__ */
unknown's avatar
unknown committed
4356
}
unknown's avatar
unknown committed
4357

4358
#endif /* EMBEDDED_LIBRARY */
4359 4360


Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
4361
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
4362
static void handle_connections_methods()
unknown's avatar
unknown committed
4363
{
4364 4365
  pthread_t hThread;
  DBUG_ENTER("handle_connections_methods");
unknown's avatar
unknown committed
4366
  if (hPipe == INVALID_HANDLE_VALUE &&
4367 4368
      (!have_tcpip || opt_disable_networking) &&
      !opt_enable_shared_memory)
unknown's avatar
unknown committed
4369
  {
unknown's avatar
unknown committed
4370
    sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
4371
    unireg_abort(1);				// Will not return
unknown's avatar
unknown committed
4372
  }
4373

Marc Alff's avatar
Marc Alff committed
4374 4375
  mysql_mutex_lock(&LOCK_thread_count);
  mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
4376 4377
  handler_count=0;
  if (hPipe != INVALID_HANDLE_VALUE)
unknown's avatar
unknown committed
4378
  {
4379
    handler_count++;
Marc Alff's avatar
Marc Alff committed
4380 4381 4382
    if (mysql_thread_create(key_thread_handle_con_namedpipes,
                            &hThread, &connection_attrib,
                            handle_connections_namedpipes, 0))
unknown's avatar
unknown committed
4383
    {
4384
      sql_print_warning("Can't create thread to handle named pipes");
4385 4386 4387 4388 4389 4390
      handler_count--;
    }
  }
  if (have_tcpip && !opt_disable_networking)
  {
    handler_count++;
Marc Alff's avatar
Marc Alff committed
4391 4392 4393
    if (mysql_thread_create(key_thread_handle_con_sockets,
                            &hThread, &connection_attrib,
                            handle_connections_sockets_thread, 0))
4394
    {
4395
      sql_print_warning("Can't create thread to handle TCP/IP");
4396 4397 4398 4399 4400 4401 4402
      handler_count--;
    }
  }
#ifdef HAVE_SMEM
  if (opt_enable_shared_memory)
  {
    handler_count++;
Marc Alff's avatar
Marc Alff committed
4403 4404 4405
    if (mysql_thread_create(key_thread_handle_con_sharedmem,
                            &hThread, &connection_attrib,
                            handle_connections_shared_memory, 0))
4406
    {
4407
      sql_print_warning("Can't create thread to handle shared memory");
4408
      handler_count--;
unknown's avatar
unknown committed
4409 4410
    }
  }
4411
#endif 
unknown's avatar
unknown committed
4412

4413
  while (handler_count > 0)
Marc Alff's avatar
Marc Alff committed
4414 4415
    mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
4416 4417
  DBUG_VOID_RETURN;
}
4418 4419 4420

void decrement_handler_count()
{
Marc Alff's avatar
Marc Alff committed
4421
  mysql_mutex_lock(&LOCK_thread_count);
4422
  handler_count--;
Marc Alff's avatar
Marc Alff committed
4423 4424
  mysql_cond_signal(&COND_handler_count);
  mysql_mutex_unlock(&LOCK_thread_count);
4425
  my_thread_end();
4426 4427 4428
}
#else
#define decrement_handler_count()
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
4429
#endif /* defined(_WIN32) || defined(HAVE_SMEM) */
4430 4431


4432
#ifndef EMBEDDED_LIBRARY
4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469
#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

unknown's avatar
unknown committed
4470 4471 4472
#ifdef __WIN__
int win_main(int argc, char **argv)
#else
4473
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
4474 4475
#endif
{
Marc Alff's avatar
Marc Alff committed
4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 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 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597
  /*
    Perform basic thread library and malloc initialization,
    to be able to read defaults files and parse options.
  */
  my_progname= argv[0];
  if (my_basic_init())
  {
    fprintf(stderr, "my_basic_init() failed.");
    return 1;
  }

  orig_argc= argc;
  orig_argv= argv;
  if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
    return 1;
  defaults_argc= argc;
  defaults_argv= argv;
  remaining_argc= argc;
  remaining_argv= argv;

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

  sys_var_init();

#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  /*
    The performance schema needs to be initialized as early as possible,
    before to-be-instrumented objects of the server are initialized.
  */
  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);
  sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
  add_terminator(&all_early_options);

  /*
    Logs generated while parsing the command line
    options are buffered and printed later.
  */
  buffered_logs.init();
  my_getopt_error_reporter= buffered_option_error_reporter;

  ho_error= handle_options(&remaining_argc, &remaining_argv,
                           (my_option*)(all_early_options.buffer), NULL);
  delete_dynamic(&all_early_options);
  if (ho_error == 0)
  {
    /* Add back the program name handle_options removes */
    remaining_argc++;
    remaining_argv--;
    if (pfs_param.m_enabled)
    {
      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
      {
        buffered_logs.buffer(INFORMATION_LEVEL,
                             "Performance schema enabled.");
      }
    }
    else
    {
      buffered_logs.buffer(INFORMATION_LEVEL,
                           "Performance schema disabled (reason: start parameters).");
    }
  }
#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)
    PSI_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION);

  if (PSI_server)
  {
    /*
      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 */
    PSI_thread *psi= PSI_server->new_thread(key_thread_main, NULL, 0);
    if (psi)
      PSI_server->set_thread(psi);

    /*
      Now that some instrumentation is in place,
      recreate objects which were initialised early,
      so that they are instrumented as well.
    */
    my_thread_basic_global_reinit();
  }
#endif /* HAVE_PSI_INTERFACE */

  my_init();                                   // init my_sys library & pthreads
  init_error_log_mutex();
4598

4599 4600 4601 4602 4603 4604 4605
  /* Set signal used to kill MySQL */
#if defined(SIGUSR2)
  thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
#else
  thr_kill_signal= SIGINT;
#endif

Sergey Vojtovich's avatar
Sergey Vojtovich committed
4606 4607 4608
  /* Initialize audit interface globals. Audit plugins are inited later. */
  mysql_audit_initialize();

4609 4610 4611 4612 4613 4614
  /*
    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
4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636
#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
4637
#ifdef _CUSTOMSTARTUPCONFIG_
unknown's avatar
unknown committed
4638 4639 4640
  if (_cust_check_startup())
  {
    / * _cust_check_startup will report startup failure error * /
unknown's avatar
Merge  
unknown committed
4641
    exit(1);
unknown's avatar
unknown committed
4642 4643
  }
#endif
unknown's avatar
unknown committed
4644

4645
#ifdef	__WIN__
unknown's avatar
unknown committed
4646 4647 4648 4649
  /*
    Before performing any socket operation (like retrieving hostname
    in init_common_variables we have to call WSAStartup
  */
4650 4651 4652 4653
  {
    WSADATA WsaData;
    if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
    {
unknown's avatar
unknown committed
4654
      /* errors are not read yet, so we use english text here */
4655
      my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
Marc Alff's avatar
Marc Alff committed
4656 4657
      /* Not enough initializations for unireg_abort() */
      return 1;
4658 4659 4660 4661
    }
  }
#endif /* __WIN__ */

Marc Alff's avatar
Marc Alff committed
4662
  if (init_common_variables())
4663
    unireg_abort(1);				// Will do exit
unknown's avatar
unknown committed
4664 4665

  init_signals();
4666
#if defined(__ia64__) || defined(__ia64)
4667 4668 4669 4670
  /*
    Peculiar things with ia64 platforms - it seems we only have half the
    stack size in reality, so we have to double it here
  */
4671
  pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2);
4672
#else
4673
  pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size);
4674
#endif
4675 4676 4677 4678 4679
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
  {
    /* Retrieve used stack size;  Needed for checking stack overflows */
    size_t stack_size= 0;
    pthread_attr_getstacksize(&connection_attrib, &stack_size);
4680 4681 4682
#if defined(__ia64__) || defined(__ia64)
    stack_size/= 2;
#endif
4683
    /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
4684
    if (stack_size && stack_size < my_thread_stack_size)
4685 4686
    {
      if (global_system_variables.log_warnings)
unknown's avatar
unknown committed
4687
	sql_print_warning("Asked for %lu thread stack, but got %ld",
4688
			  my_thread_stack_size, (long) stack_size);
4689
#if defined(__ia64__) || defined(__ia64)
4690
      my_thread_stack_size= stack_size*2;
4691
#else
4692
      my_thread_stack_size= stack_size;
4693
#endif
4694 4695 4696
    }
  }
#endif
4697 4698 4699 4700
#ifdef __NETWARE__
  /* Increasing stacksize of threads on NetWare */
  pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
#endif
unknown's avatar
unknown committed
4701

4702
  (void) thr_setconcurrency(concurrency);	// 10 by default
unknown's avatar
unknown committed
4703

4704 4705
  select_thread=pthread_self();
  select_thread_in_use=1;
unknown's avatar
unknown committed
4706 4707 4708 4709 4710 4711

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

4712 4713 4714 4715
#ifndef DBUG_OFF
  test_lc_time_sz();
#endif

unknown's avatar
unknown committed
4716 4717 4718
  /*
    We have enough space for fiddling with the argv, continue
  */
unknown's avatar
unknown committed
4719
  check_data_home(mysql_real_data_home);
unknown's avatar
WL#2936  
unknown committed
4720
  if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help)
unknown's avatar
unknown committed
4721
    unireg_abort(1);				/* purecov: inspected */
unknown's avatar
unknown committed
4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732

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

unknown's avatar
unknown committed
4733 4734
  if (opt_bin_log && !server_id)
  {
4735
    server_id= 1;
unknown's avatar
unknown committed
4736
#ifdef EXTRA_DEBUG
4737 4738 4739 4740
    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.");
4741
#endif
unknown's avatar
unknown committed
4742 4743 4744
  }

  if (init_server_components())
unknown's avatar
unknown committed
4745
    unireg_abort(1);
unknown's avatar
unknown committed
4746

4747
  init_ssl();
unknown's avatar
unknown committed
4748 4749
  network_init();

unknown's avatar
unknown committed
4750 4751 4752
#ifdef __WIN__
  if (!opt_console)
  {
4753 4754
    freopen(log_error_file,"a+",stdout);
    freopen(log_error_file,"a+",stderr);
4755
    setbuf(stderr, NULL);
unknown's avatar
unknown committed
4756
    FreeConsole();				// Remove window
4757
  }
unknown's avatar
unknown committed
4758 4759
#endif

4760 4761 4762 4763 4764 4765
  /*
   Initialize my_str_malloc() and my_str_free()
  */
  my_str_malloc= &my_str_malloc_mysqld;
  my_str_free= &my_str_free_mysqld;

unknown's avatar
unknown committed
4766 4767 4768 4769
  /*
    init signals & alarm
    After this we can't quit by a simple unireg_abort
  */
4770
  error_handler_hook= my_message_sql;
unknown's avatar
unknown committed
4771
  start_signal_handler();				// Creates pidfile
4772

4773
  if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
4774
      my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
unknown's avatar
unknown committed
4775 4776 4777
  {
    abort_loop=1;
    select_thread_in_use=0;
unknown's avatar
unknown committed
4778 4779 4780
#ifndef __NETWARE__
    (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
#endif /* __NETWARE__ */
4781

unknown's avatar
unknown committed
4782
    if (!opt_bootstrap)
Marc Alff's avatar
Marc Alff committed
4783
      mysql_file_delete(key_file_pid, pidfile_name, MYF(MY_WME)); // Not needed anymore
4784

4785
    if (unix_sock != INVALID_SOCKET)
4786
      unlink(mysqld_unix_port);
unknown's avatar
unknown committed
4787 4788
    exit(1);
  }
4789

unknown's avatar
unknown committed
4790
  if (!opt_noacl)
4791
    (void) grant_init();
unknown's avatar
unknown committed
4792

unknown's avatar
unknown committed
4793 4794 4795
  if (!opt_bootstrap)
    servers_init(0);

unknown's avatar
unknown committed
4796
  if (!opt_noacl)
4797 4798
  {
#ifdef HAVE_DLOPEN
unknown's avatar
unknown committed
4799 4800
    udf_init();
#endif
4801
  }
4802

4803
  init_status_vars();
unknown's avatar
unknown committed
4804 4805
  if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
    opt_skip_slave_start= 1;
4806 4807 4808 4809 4810 4811 4812 4813 4814 4815
  /*
    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);
  }
4816

Marc Alff's avatar
Marc Alff committed
4817 4818 4819 4820 4821 4822 4823
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
  initialize_performance_schema_acl(opt_bootstrap);
  check_performance_schema();
#endif

  initialize_information_schema_acl();

4824 4825 4826 4827 4828
  execute_ddl_log_recovery();

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

unknown's avatar
unknown committed
4829 4830
  if (opt_bootstrap)
  {
4831
    select_thread_in_use= 0;                    // Allow 'kill' to work
Marc Alff's avatar
Marc Alff committed
4832
    bootstrap(mysql_stdin);
unknown's avatar
Merge  
unknown committed
4833
    unireg_abort(bootstrap_error ? 1 : 0);
unknown's avatar
unknown committed
4834
  }
4835
  if (opt_init_file && *opt_init_file)
unknown's avatar
unknown committed
4836 4837 4838 4839
  {
    if (read_init_file(opt_init_file))
      unireg_abort(1);
  }
unknown's avatar
unknown committed
4840

unknown's avatar
unknown committed
4841
  create_shutdown_thread();
4842
  start_handle_manager();
unknown's avatar
unknown committed
4843

4844
  sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version,
unknown's avatar
merged  
unknown committed
4845
                        ((unix_sock == INVALID_SOCKET) ? (char*) ""
unknown's avatar
Merge  
unknown committed
4846
                                                       : mysqld_unix_port),
unknown's avatar
merged  
unknown committed
4847
                         mysqld_port,
unknown's avatar
Merge  
unknown committed
4848
                         MYSQL_COMPILATION_COMMENT);
4849 4850 4851
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetRunning();
#endif
unknown's avatar
unknown committed
4852

unknown's avatar
unknown committed
4853 4854

  /* Signal threads waiting for server to be started */
Marc Alff's avatar
Marc Alff committed
4855
  mysql_mutex_lock(&LOCK_server_started);
unknown's avatar
unknown committed
4856
  mysqld_server_started= 1;
Marc Alff's avatar
Marc Alff committed
4857 4858
  mysql_cond_signal(&COND_server_started);
  mysql_mutex_unlock(&LOCK_server_started);
unknown's avatar
unknown committed
4859

4860
#if defined(_WIN32) || defined(HAVE_SMEM)
4861
  handle_connections_methods();
unknown's avatar
unknown committed
4862
#else
4863 4864
  handle_connections_sockets();
#endif /* _WIN32 || HAVE_SMEM */
unknown's avatar
unknown committed
4865 4866

  /* (void) pthread_attr_destroy(&connection_attrib); */
4867
  
unknown's avatar
unknown committed
4868 4869 4870
  DBUG_PRINT("quit",("Exiting main thread"));

#ifndef __WIN__
unknown's avatar
unknown committed
4871
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
4872 4873
  sql_print_error("Before Lock_thread_count");
#endif
Marc Alff's avatar
Marc Alff committed
4874
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
4875
  DBUG_PRINT("quit", ("Got thread_count mutex"));
unknown's avatar
unknown committed
4876
  select_thread_in_use=0;			// For close_connections
Marc Alff's avatar
Marc Alff committed
4877 4878
  mysql_mutex_unlock(&LOCK_thread_count);
  mysql_cond_broadcast(&COND_thread_count);
unknown's avatar
unknown committed
4879
#ifdef EXTRA_DEBUG2
unknown's avatar
unknown committed
4880 4881
  sql_print_error("After lock_thread_count");
#endif
unknown's avatar
merge  
unknown committed
4882
#endif /* __WIN__ */
4883

unknown's avatar
unknown committed
4884
  /* Wait until cleanup is done */
Marc Alff's avatar
Marc Alff committed
4885
  mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
4886
  while (!ready_to_exit)
Marc Alff's avatar
Marc Alff committed
4887 4888
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
merge  
unknown committed
4889 4890

#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
merge  
unknown committed
4891 4892 4893 4894
  if (Service.IsNT() && start_mode)
    Service.Stop();
  else
  {
unknown's avatar
Cleanup  
unknown committed
4895
    Service.SetShutdownEvent(0);
unknown's avatar
merge  
unknown committed
4896 4897 4898
    if (hEventShutdown)
      CloseHandle(hEventShutdown);
  }
unknown's avatar
unknown committed
4899
#endif
unknown's avatar
unknown committed
4900
  clean_up(1);
Marc Alff's avatar
Marc Alff committed
4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912
#ifdef HAVE_PSI_INTERFACE
  /*
    Disable the instrumentation, to avoid recording events
    during the shutdown.
  */
  if (PSI_server)
  {
    PSI_server->delete_current_thread();
    PSI_server= NULL;
  }
  shutdown_performance_schema();
#endif
Sergey Vojtovich's avatar
Sergey Vojtovich committed
4913
  mysqld_exit(0);
unknown's avatar
unknown committed
4914 4915
}

Sergey Vojtovich's avatar
Sergey Vojtovich committed
4916
#endif /* !EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
4917

unknown's avatar
SCRUM  
unknown committed
4918

4919 4920 4921 4922 4923
/****************************************************************************
  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
4924
#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
unknown's avatar
unknown committed
4925 4926
int mysql_service(void *p)
{
4927 4928 4929 4930
  if (use_opt_args)
    win_main(opt_argc, opt_argv);
  else
    win_main(Service.my_argc, Service.my_argv);
unknown's avatar
unknown committed
4931 4932 4933
  return 0;
}

4934 4935 4936 4937 4938 4939 4940 4941

/* 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
4942 4943
    return strmake(to, from, length-1);
  return strxnmov(to, length-1, "\"", from, "\"", NullS);
4944 4945 4946
}


unknown's avatar
unknown committed
4947 4948
/**
  Handle basic handling of services, like installation and removal.
4949

unknown's avatar
unknown committed
4950 4951 4952 4953 4954 4955 4956
  @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

  @retval
4957
    0		option handled
unknown's avatar
unknown committed
4958
  @retval
4959
    1		Could not handle option
unknown's avatar
unknown committed
4960
*/
4961

4962 4963 4964 4965 4966
static bool
default_service_handling(char **argv,
			 const char *servicename,
			 const char *displayname,
			 const char *file_path,
unknown's avatar
Merge  
unknown committed
4967 4968
			 const char *extra_opt,
			 const char *account_name)
4969
{
4970
  char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
4971
  const char *opt_delim;
4972
  end= path_and_service + sizeof(path_and_service)-3;
4973 4974 4975 4976 4977

  /* We have to quote filename if it contains spaces */
  pos= add_quoted_string(path_and_service, file_path, end);
  if (*extra_opt)
  {
4978 4979 4980 4981 4982
    /* 
     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.  
    */
4983
    *pos++= ' ';
4984 4985 4986
    if (opt_delim= strchr(extra_opt, '='))
    {
      size_t length= ++opt_delim - extra_opt;
4987
      pos= strnmov(pos, extra_opt, length);
4988 4989 4990 4991 4992
    }
    else
      opt_delim= extra_opt;
    
    pos= add_quoted_string(pos, opt_delim, end);
4993
  }
4994 4995
  /* We must have servicename last */
  *pos++= ' ';
unknown's avatar
unknown committed
4996
  (void) add_quoted_string(pos, servicename, end);
4997

4998 4999
  if (Service.got_service_option(argv, "install"))
  {
unknown's avatar
Merge  
unknown committed
5000 5001
    Service.Install(1, servicename, displayname, path_and_service,
                    account_name);
5002 5003 5004 5005
    return 0;
  }
  if (Service.got_service_option(argv, "install-manual"))
  {
unknown's avatar
Merge  
unknown committed
5006 5007
    Service.Install(0, servicename, displayname, path_and_service,
                    account_name);
5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018
    return 0;
  }
  if (Service.got_service_option(argv, "remove"))
  {
    Service.Remove(servicename);
    return 0;
  }
  return 1;
}


5019
int mysqld_main(int argc, char **argv)
unknown's avatar
unknown committed
5020
{
unknown's avatar
unknown committed
5021 5022 5023 5024
  /*
    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
5025
  */
5026
  int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
unknown's avatar
Merge  
unknown committed
5027 5028
                                                  "MySQLShutdown"), 10);

5029 5030 5031
  /* Must be initialized early for comparison of service name */
  system_charset_info= &my_charset_utf8_general_ci;

unknown's avatar
unknown committed
5032
  if (Service.GetOS())	/* true NT family */
unknown's avatar
unknown committed
5033
  {
unknown's avatar
unknown committed
5034
    char file_path[FN_REFLEN];
5035
    my_path(file_path, argv[0], "");		      /* Find name in path */
unknown's avatar
unknown committed
5036 5037
    fn_format(file_path,argv[0],file_path,"",
	      MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
unknown's avatar
unknown committed
5038

unknown's avatar
unknown committed
5039
    if (argc == 2)
5040
    {
5041
      if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
unknown's avatar
Merge  
unknown committed
5042
				   file_path, "", NULL))
5043
	return 0;
unknown's avatar
unknown committed
5044
      if (Service.IsService(argv[1]))        /* Start an optional service */
unknown's avatar
unknown committed
5045
      {
unknown's avatar
unknown committed
5046 5047 5048 5049 5050 5051
	/*
	  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.
	*/
5052
	if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
5053
	  load_default_groups[load_default_groups_sz-2]= argv[1];
unknown's avatar
unknown committed
5054
        start_mode= 1;
5055
        Service.Init(argv[1], mysql_service);
unknown's avatar
unknown committed
5056 5057 5058 5059
        return 0;
      }
    }
    else if (argc == 3) /* install or remove any optional service */
unknown's avatar
unknown committed
5060
    {
unknown's avatar
Merge  
unknown committed
5061 5062
      if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
                                    NULL))
5063 5064
	return 0;
      if (Service.IsService(argv[2]))
unknown's avatar
unknown committed
5065
      {
5066 5067 5068 5069
	/*
	  mysqld was started as
	  mysqld --defaults-file=my_path\my.ini service-name
	*/
5070
	use_opt_args=1;
5071
	opt_argc= 2;				// Skip service-name
5072 5073
	opt_argv=argv;
	start_mode= 1;
5074
	if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
5075
	  load_default_groups[load_default_groups_sz-2]= argv[2];
5076
	Service.Init(argv[2], mysql_service);
5077
	return 0;
unknown's avatar
unknown committed
5078 5079
      }
    }
unknown's avatar
Merge  
unknown committed
5080
    else if (argc == 4 || argc == 5)
5081 5082
    {
      /*
unknown's avatar
Merge  
unknown committed
5083 5084 5085 5086 5087
        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.)
5088
      */
unknown's avatar
Merge  
unknown committed
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103
      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;
5104
    }
unknown's avatar
unknown committed
5105
    else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
unknown's avatar
unknown committed
5106
    {
unknown's avatar
unknown committed
5107 5108 5109
      /* start the default service */
      start_mode= 1;
      Service.Init(MYSQL_SERVICENAME, mysql_service);
unknown's avatar
unknown committed
5110 5111 5112
      return 0;
    }
  }
unknown's avatar
unknown committed
5113
  /* Start as standalone server */
unknown's avatar
unknown committed
5114 5115 5116 5117 5118 5119 5120 5121
  Service.my_argc=argc;
  Service.my_argv=argv;
  mysql_service(NULL);
  return 0;
}
#endif


unknown's avatar
unknown committed
5122
/**
5123 5124 5125
  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.
*/
5126

Marc Alff's avatar
Marc Alff committed
5127
static void bootstrap(MYSQL_FILE *file)
unknown's avatar
unknown committed
5128
{
5129
  DBUG_ENTER("bootstrap");
5130

5131
  THD *thd= new THD;
unknown's avatar
unknown committed
5132
  thd->bootstrap=1;
unknown's avatar
unknown committed
5133
  my_net_init(&thd->net,(st_vio*) 0);
unknown's avatar
unknown committed
5134
  thd->max_client_packet_length= thd->net.max_packet;
5135
  thd->security_ctx->master_access= ~(ulong)0;
unknown's avatar
unknown committed
5136
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
unknown's avatar
unknown committed
5137
  thread_count++;
5138
  in_bootstrap= TRUE;
5139 5140

  bootstrap_file=file;
unknown's avatar
unknown committed
5141
#ifndef EMBEDDED_LIBRARY			// TODO:  Enable this
Marc Alff's avatar
Marc Alff committed
5142 5143 5144
  if (mysql_thread_create(key_thread_bootstrap,
                          &thd->real_id, &connection_attrib, handle_bootstrap,
                          (void*) thd))
5145
  {
5146
    sql_print_warning("Can't create thread to handle bootstrap");
unknown's avatar
Merge  
unknown committed
5147 5148
    bootstrap_error=-1;
    DBUG_VOID_RETURN;
5149 5150
  }
  /* Wait for thread to die */
Marc Alff's avatar
Marc Alff committed
5151
  mysql_mutex_lock(&LOCK_thread_count);
5152
  while (in_bootstrap)
5153
  {
Marc Alff's avatar
Marc Alff committed
5154
    mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
5155 5156
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
Marc Alff's avatar
Marc Alff committed
5157
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
5158 5159
#else
  thd->mysql= 0;
Marc Alff's avatar
Marc Alff committed
5160
  do_handle_bootstrap(thd);
unknown's avatar
unknown committed
5161 5162
#endif

unknown's avatar
Merge  
unknown committed
5163
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
5164 5165
}

5166

unknown's avatar
unknown committed
5167 5168
static bool read_init_file(char *file_name)
{
Marc Alff's avatar
Marc Alff committed
5169
  MYSQL_FILE *file;
unknown's avatar
unknown committed
5170 5171
  DBUG_ENTER("read_init_file");
  DBUG_PRINT("enter",("name: %s",file_name));
Marc Alff's avatar
Marc Alff committed
5172 5173
  if (!(file= mysql_file_fopen(key_file_init, file_name,
                               O_RDONLY, MYF(MY_WME))))
5174
    DBUG_RETURN(TRUE);
unknown's avatar
Merge  
unknown committed
5175
  bootstrap(file);
Marc Alff's avatar
Marc Alff committed
5176
  mysql_file_fclose(file, MYF(MY_WME));
5177
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
5178 5179 5180
}


5181
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
5182 5183 5184 5185 5186 5187 5188 5189 5190 5191

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

unknown's avatar
unknown committed
5193 5194
void handle_connection_in_main_thread(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
5195
  mysql_mutex_assert_owner(&LOCK_thread_count);
unknown's avatar
unknown committed
5196 5197
  thread_cache_size=0;			// Safety
  threads.append(thd);
Marc Alff's avatar
Marc Alff committed
5198
  mysql_mutex_unlock(&LOCK_thread_count);
5199
  thd->start_utime= my_micro_time();
Marc Alff's avatar
Marc Alff committed
5200
  do_handle_one_connection(thd);
unknown's avatar
unknown committed
5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214
}


/*
  Scheduler that uses one thread per connection
*/

void create_thread_to_handle_connection(THD *thd)
{
  if (cached_thread_count > wake_thread)
  {
    /* Get thread from cache */
    thread_cache.append(thd);
    wake_thread++;
Marc Alff's avatar
Marc Alff committed
5215
    mysql_cond_signal(&COND_thread_cache);
unknown's avatar
unknown committed
5216 5217 5218
  }
  else
  {
5219
    char error_message_buff[MYSQL_ERRMSG_SIZE];
unknown's avatar
unknown committed
5220 5221 5222 5223 5224
    /* Create new thread to handle connection */
    int error;
    thread_created++;
    threads.append(thd);
    DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
5225
    thd->prior_thr_create_utime= thd->start_utime= my_micro_time();
Marc Alff's avatar
Marc Alff committed
5226 5227 5228 5229
    if ((error= mysql_thread_create(key_thread_one_connection,
                                    &thd->real_id, &connection_attrib,
                                    handle_one_connection,
                                    (void*) thd)))
unknown's avatar
unknown committed
5230
    {
Ingo Struewing's avatar
Ingo Struewing committed
5231
      /* purecov: begin inspected */
unknown's avatar
unknown committed
5232 5233 5234 5235 5236
      DBUG_PRINT("error",
                 ("Can't create thread to handle request (error %d)",
                  error));
      thread_count--;
      thd->killed= THD::KILL_CONNECTION;			// Safety
Marc Alff's avatar
Marc Alff committed
5237
      mysql_mutex_unlock(&LOCK_thread_count);
5238

Marc Alff's avatar
Marc Alff committed
5239
      mysql_mutex_lock(&LOCK_connection_count);
5240
      --connection_count;
Marc Alff's avatar
Marc Alff committed
5241
      mysql_mutex_unlock(&LOCK_connection_count);
5242

unknown's avatar
unknown committed
5243
      statistic_increment(aborted_connects,&LOCK_status);
5244 5245 5246
      /* Can't use my_error() since store_globals has not been called. */
      my_snprintf(error_message_buff, sizeof(error_message_buff),
                  ER(ER_CANT_CREATE_THREAD), error);
Marc Alff's avatar
Marc Alff committed
5247
      net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
Marc Alff's avatar
Marc Alff committed
5248
      mysql_mutex_lock(&LOCK_thread_count);
unknown's avatar
unknown committed
5249 5250
      close_connection(thd,0,0);
      delete thd;
Marc Alff's avatar
Marc Alff committed
5251
      mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
5252 5253 5254 5255
      return;
      /* purecov: end */
    }
  }
Marc Alff's avatar
Marc Alff committed
5256
  mysql_mutex_unlock(&LOCK_thread_count);
unknown's avatar
unknown committed
5257 5258 5259 5260
  DBUG_PRINT("info",("Thread created"));
}


unknown's avatar
unknown committed
5261
/**
5262 5263 5264 5265 5266 5267
  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
5268
    In single-threaded mode (\#define ONE_THREAD) connection will be
5269 5270
    handled inside this function.

unknown's avatar
unknown committed
5271
  @param[in,out] thd    Thread handle of future thread.
5272 5273
*/

unknown's avatar
unknown committed
5274 5275 5276 5277
static void create_new_thread(THD *thd)
{
  DBUG_ENTER("create_new_thread");

5278 5279 5280 5281 5282
  /*
    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
5283
  mysql_mutex_lock(&LOCK_connection_count);
5284 5285

  if (connection_count >= max_connections + 1 || abort_loop)
unknown's avatar
unknown committed
5286
  {
Marc Alff's avatar
Marc Alff committed
5287
    mysql_mutex_unlock(&LOCK_connection_count);
5288

unknown's avatar
unknown committed
5289
    DBUG_PRINT("error",("Too many connections"));
5290
    close_connection(thd, ER_CON_COUNT_ERROR, 1);
unknown's avatar
unknown committed
5291 5292 5293
    delete thd;
    DBUG_VOID_RETURN;
  }
5294 5295 5296

  ++connection_count;

5297 5298 5299
  if (connection_count > max_used_connections)
    max_used_connections= connection_count;

Marc Alff's avatar
Marc Alff committed
5300
  mysql_mutex_unlock(&LOCK_connection_count);
5301 5302 5303

  /* Start a new thread to handle connection. */

Marc Alff's avatar
Marc Alff committed
5304
  mysql_mutex_lock(&LOCK_thread_count);
5305

5306 5307 5308 5309 5310
  /*
    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
5311
  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
unknown's avatar
unknown committed
5312

5313 5314
  thread_count++;

unknown's avatar
unknown committed
5315
  thread_scheduler.add_connection(thd);
5316

unknown's avatar
unknown committed
5317 5318
  DBUG_VOID_RETURN;
}
5319 5320
#endif /* EMBEDDED_LIBRARY */

unknown's avatar
unknown committed
5321

unknown's avatar
unknown committed
5322 5323 5324 5325
#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
{
  /* hack to get around signals ignored in syscalls for problem OS's */
unknown's avatar
unknown committed
5326 5327 5328 5329
  if (
#if !defined(__NETWARE__)
      unix_sock == INVALID_SOCKET ||
#endif
5330
      (!opt_disable_networking && ip_sock == INVALID_SOCKET))
unknown's avatar
unknown committed
5331 5332
  {
    select_thread_in_use = 0;
unknown's avatar
unknown committed
5333 5334
    /* The following call will never return */
    kill_server(IF_NETWARE(MYSQL_KILL_SIGNAL, (void*) MYSQL_KILL_SIGNAL));
unknown's avatar
unknown committed
5335 5336 5337 5338 5339 5340
  }
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
#else
#define MAYBE_BROKEN_SYSCALL
#endif
unknown's avatar
unknown committed
5341 5342 5343

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

5344
#ifndef EMBEDDED_LIBRARY
5345

5346
void handle_connections_sockets()
unknown's avatar
unknown committed
5347 5348 5349 5350
{
  my_socket sock,new_sock;
  uint error_count=0;
  THD *thd;
5351
  struct sockaddr_storage cAddr;
5352
  int ip_flags=0,socket_flags=0,flags,retval;
unknown's avatar
unknown committed
5353
  st_vio *vio_tmp;
5354 5355 5356 5357 5358 5359 5360 5361
#ifdef HAVE_POLL
  int socket_count= 0;
  struct pollfd fds[2]; // for ip_sock and unix_sock
#else
  fd_set readFDs,clientFDs;
  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
#endif

unknown's avatar
unknown committed
5362 5363 5364 5365
  DBUG_ENTER("handle_connections_sockets");

  LINT_INIT(new_sock);

5366
#ifndef HAVE_POLL
unknown's avatar
unknown committed
5367
  FD_ZERO(&clientFDs);
5368 5369
#endif

unknown's avatar
unknown committed
5370 5371
  if (ip_sock != INVALID_SOCKET)
  {
5372 5373 5374 5375 5376
#ifdef HAVE_POLL
    fds[socket_count].fd= ip_sock;
    fds[socket_count].events= POLLIN;
    socket_count++;
#else
unknown's avatar
unknown committed
5377
    FD_SET(ip_sock,&clientFDs);
5378
#endif    
unknown's avatar
unknown committed
5379 5380 5381 5382 5383
#ifdef HAVE_FCNTL
    ip_flags = fcntl(ip_sock, F_GETFL, 0);
#endif
  }
#ifdef HAVE_SYS_UN_H
5384 5385 5386 5387 5388
#ifdef HAVE_POLL
  fds[socket_count].fd= unix_sock;
  fds[socket_count].events= POLLIN;
  socket_count++;
#else
unknown's avatar
unknown committed
5389
  FD_SET(unix_sock,&clientFDs);
5390
#endif
unknown's avatar
unknown committed
5391
#ifdef HAVE_FCNTL
unknown's avatar
unknown committed
5392
  socket_flags=fcntl(unix_sock, F_GETFL, 0);
unknown's avatar
unknown committed
5393
#endif
unknown's avatar
unknown committed
5394 5395 5396
#endif

  DBUG_PRINT("general",("Waiting for connections."));
unknown's avatar
unknown committed
5397
  MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
5398 5399
  while (!abort_loop)
  {
5400 5401
#ifdef HAVE_POLL
    retval= poll(fds, socket_count, -1);
unknown's avatar
unknown committed
5402
#else
5403 5404 5405 5406 5407 5408
    readFDs=clientFDs;

    retval= select((int) max_used_connection,&readFDs,0,0,0);
#endif

    if (retval < 0)
unknown's avatar
unknown committed
5409
    {
unknown's avatar
unknown committed
5410
      if (socket_errno != SOCKET_EINTR)
unknown's avatar
unknown committed
5411 5412
      {
	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
unknown's avatar
unknown committed
5413
	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
unknown's avatar
unknown committed
5414
      }
unknown's avatar
unknown committed
5415
      MAYBE_BROKEN_SYSCALL
unknown's avatar
unknown committed
5416 5417
      continue;
    }
5418

unknown's avatar
unknown committed
5419
    if (abort_loop)
unknown's avatar
unknown committed
5420 5421
    {
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
5422
      break;
unknown's avatar
unknown committed
5423
    }
unknown's avatar
unknown committed
5424

5425
    /* Is this a new connection request ? */
5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440
#ifdef HAVE_POLL
    for (int i= 0; i < socket_count; ++i) 
    {
      if (fds[i].revents & POLLIN)
      {
        sock= fds[i].fd;
#ifdef HAVE_FCNTL
        flags= fcntl(sock, F_GETFL, 0);
#else
        flags= 0;
#endif // HAVE_FCNTL
        break;
      }
    }
#else  // HAVE_POLL
unknown's avatar
unknown committed
5441 5442 5443 5444 5445 5446 5447
#ifdef HAVE_SYS_UN_H
    if (FD_ISSET(unix_sock,&readFDs))
    {
      sock = unix_sock;
      flags= socket_flags;
    }
    else
5448
#endif // HAVE_SYS_UN_H
unknown's avatar
unknown committed
5449 5450 5451 5452
    {
      sock = ip_sock;
      flags= ip_flags;
    }
5453
#endif // HAVE_POLL
unknown's avatar
unknown committed
5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466

#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
    {
#if defined(O_NONBLOCK)
      fcntl(sock, F_SETFL, flags | O_NONBLOCK);
#elif defined(O_NDELAY)
      fcntl(sock, F_SETFL, flags | O_NDELAY);
#endif
    }
#endif /* NO_FCNTL_NONBLOCK */
    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
    {
5467 5468 5469
      size_socket length= sizeof(struct sockaddr_storage);
      new_sock= accept(sock, (struct sockaddr *)(&cAddr),
                       &length);
unknown's avatar
unknown committed
5470 5471 5472 5473 5474 5475 5476
#ifdef __NETWARE__ 
      // TODO: temporary fix, waiting for TCP/IP fix - DEFECT000303149
      if ((new_sock == INVALID_SOCKET) && (socket_errno == EINVAL))
      {
        kill_server(SIGTERM);
      }
#endif
unknown's avatar
unknown committed
5477 5478
      if (new_sock != INVALID_SOCKET ||
	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
unknown's avatar
unknown committed
5479
	break;
unknown's avatar
unknown committed
5480
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492
#if !defined(NO_FCNTL_NONBLOCK)
      if (!(test_flags & TEST_BLOCKING))
      {
	if (retry == MAX_ACCEPT_RETRY - 1)
	  fcntl(sock, F_SETFL, flags);		// Try without O_NONBLOCK
      }
#endif
    }
#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
      fcntl(sock, F_SETFL, flags);
#endif
unknown's avatar
unknown committed
5493
    if (new_sock == INVALID_SOCKET)
unknown's avatar
unknown committed
5494 5495 5496
    {
      if ((error_count++ & 255) == 0)		// This can happen often
	sql_perror("Error in accept");
unknown's avatar
unknown committed
5497
      MAYBE_BROKEN_SYSCALL;
unknown's avatar
unknown committed
5498
      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
unknown's avatar
unknown committed
5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509
	sleep(1);				// Give other threads some time
      continue;
    }

#ifdef HAVE_LIBWRAP
    {
      if (sock == ip_sock)
      {
	struct request_info req;
	signal(SIGCHLD, SIG_DFL);
	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
5510 5511
	my_fromhost(&req);
	if (!my_hosts_access(&req))
unknown's avatar
unknown committed
5512
	{
unknown's avatar
unknown committed
5513 5514 5515 5516 5517
	  /*
	    This may be stupid but refuse() includes an exit(0)
	    which we surely don't want...
	    clean_exit() - same stupid thing ...
	  */
5518
	  syslog(deny_severity, "refused connect from %s",
5519
		 my_eval_client(&req));
unknown's avatar
unknown committed
5520

unknown's avatar
unknown committed
5521 5522 5523 5524 5525 5526
	  /*
	    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
5527 5528 5529
	  if (req.sink)
	    ((void (*)(int))req.sink)(req.fd);

5530
	  (void) shutdown(new_sock, SHUT_RDWR);
unknown's avatar
unknown committed
5531 5532 5533 5534 5535 5536 5537 5538 5539
	  (void) closesocket(new_sock);
	  continue;
	}
      }
    }
#endif /* HAVE_LIBWRAP */

    {
      size_socket dummyLen;
5540 5541 5542 5543
      struct sockaddr_storage dummy;
      dummyLen = sizeof(dummy);
      if (  getsockname(new_sock,(struct sockaddr *)&dummy, 
                  (SOCKET_SIZE_TYPE *)&dummyLen) < 0  )
unknown's avatar
unknown committed
5544 5545
      {
	sql_perror("Error on new connection socket");
5546
	(void) shutdown(new_sock, SHUT_RDWR);
unknown's avatar
unknown committed
5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557
	(void) closesocket(new_sock);
	continue;
      }
    }

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

    if (!(thd= new THD))
    {
5558
      (void) shutdown(new_sock, SHUT_RDWR);
Konstantin Osipov's avatar
Konstantin Osipov committed
5559
      (void) closesocket(new_sock);
unknown's avatar
unknown committed
5560 5561 5562
      continue;
    }
    if (!(vio_tmp=vio_new(new_sock,
5563
			  sock == unix_sock ? VIO_TYPE_SOCKET :
unknown's avatar
unknown committed
5564
			  VIO_TYPE_TCPIP,
5565
			  sock == unix_sock ? VIO_LOCALHOST: 0)) ||
unknown's avatar
unknown committed
5566 5567
	my_net_init(&thd->net,vio_tmp))
    {
5568 5569 5570 5571 5572 5573 5574
      /*
        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
5575 5576
      else
      {
5577
	(void) shutdown(new_sock, SHUT_RDWR);
unknown's avatar
unknown committed
5578 5579 5580 5581 5582 5583
	(void) closesocket(new_sock);
      }
      delete thd;
      continue;
    }
    if (sock == unix_sock)
5584
      thd->security_ctx->host=(char*) my_localhost;
5585

unknown's avatar
unknown committed
5586 5587
    create_new_thread(thd);
  }
5588 5589 5590
  DBUG_VOID_RETURN;
}

unknown's avatar
unknown committed
5591

5592 5593 5594 5595 5596
#ifdef _WIN32
pthread_handler_t handle_connections_sockets_thread(void *arg)
{
  my_thread_init();
  handle_connections_sockets();
5597
  decrement_handler_count();
5598
  return 0;
unknown's avatar
unknown committed
5599 5600
}

5601
pthread_handler_t handle_connections_namedpipes(void *arg)
unknown's avatar
unknown committed
5602 5603
{
  HANDLE hConnectedPipe;
5604
  OVERLAPPED connectOverlapped= {0};
unknown's avatar
unknown committed
5605 5606 5607
  THD *thd;
  my_thread_init();
  DBUG_ENTER("handle_connections_namedpipes");
5608 5609 5610 5611 5612 5613
  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
5614 5615 5616 5617
  DBUG_PRINT("general",("Waiting for named pipe connections."));
  while (!abort_loop)
  {
    /* wait for named pipe connection */
5618 5619 5620 5621 5622 5623 5624 5625 5626 5627
    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
5628 5629
    if (abort_loop)
      break;
unknown's avatar
unknown committed
5630
    if (!fConnected)
unknown's avatar
unknown committed
5631
      fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
unknown's avatar
unknown committed
5632
    if (!fConnected)
unknown's avatar
unknown committed
5633
    {
unknown's avatar
Merge  
unknown committed
5634 5635
      CloseHandle(hPipe);
      if ((hPipe= CreateNamedPipe(pipe_name,
5636 5637
                                  PIPE_ACCESS_DUPLEX |
                                  FILE_FLAG_OVERLAPPED,
unknown's avatar
Merge  
unknown committed
5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648
                                  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
5649 5650 5651 5652 5653 5654 5655
      {
	sql_perror("Can't create new named pipe!");
	break;					// Abort
      }
    }
    hConnectedPipe = hPipe;
    /* create new pipe for new connection */
5656
    if ((hPipe = CreateNamedPipe(pipe_name,
5657 5658
                 PIPE_ACCESS_DUPLEX |
                 FILE_FLAG_OVERLAPPED,
unknown's avatar
unknown committed
5659 5660 5661 5662
				 PIPE_TYPE_BYTE |
				 PIPE_READMODE_BYTE |
				 PIPE_WAIT,
				 PIPE_UNLIMITED_INSTANCES,
5663 5664
				 (int) global_system_variables.net_buffer_length,
				 (int) global_system_variables.net_buffer_length,
unknown's avatar
unknown committed
5665 5666 5667 5668 5669 5670 5671 5672 5673
				 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
5674
    if (!(thd = new THD))
unknown's avatar
unknown committed
5675
    {
unknown's avatar
Merge  
unknown committed
5676 5677
      DisconnectNamedPipe(hConnectedPipe);
      CloseHandle(hConnectedPipe);
unknown's avatar
unknown committed
5678 5679
      continue;
    }
5680
    if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
unknown's avatar
unknown committed
5681 5682
	my_net_init(&thd->net, thd->net.vio))
    {
5683
      close_connection(thd, ER_OUT_OF_RESOURCES, 1);
unknown's avatar
unknown committed
5684 5685 5686
      delete thd;
      continue;
    }
5687 5688
    /* Host is unknown */
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
unknown's avatar
unknown committed
5689 5690
    create_new_thread(thd);
  }
5691
  CloseHandle(connectOverlapped.hEvent);
5692
  decrement_handler_count();
unknown's avatar
unknown committed
5693 5694
  DBUG_RETURN(0);
}
Vladislav Vaintroub's avatar
Vladislav Vaintroub committed
5695
#endif /* _WIN32 */
unknown's avatar
unknown committed
5696

5697

unknown's avatar
unknown committed
5698
#ifdef HAVE_SMEM
5699

unknown's avatar
unknown committed
5700 5701
/**
  Thread of shared memory's service.
5702

unknown's avatar
unknown committed
5703 5704
  @param arg                              Arguments of thread
*/
5705
pthread_handler_t handle_connections_shared_memory(void *arg)
5706
{
5707 5708
  /* file-mapping object, use for create shared memory */
  HANDLE handle_connect_file_map= 0;
5709
  char  *handle_connect_map= 0;                 // pointer on shared memory
5710 5711 5712
  HANDLE event_connect_answer= 0;
  ulong smem_buffer_length= shared_memory_buffer_length + 4;
  ulong connect_number= 1;
5713
  char *tmp= NULL;
5714 5715
  char *suffix_pos;
  char connect_number_char[22], *p;
5716
  const char *errmsg= 0;
5717
  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
5718 5719 5720 5721
  my_thread_init();
  DBUG_ENTER("handle_connections_shared_memorys");
  DBUG_PRINT("general",("Waiting for allocated shared memory."));

5722 5723 5724 5725 5726 5727
  /*
     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;

5728 5729 5730 5731 5732 5733 5734 5735
  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;

5736 5737 5738 5739 5740 5741 5742
  /*
    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)
  */
5743
  suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
5744
  strmov(suffix_pos, "CONNECT_REQUEST");
5745 5746
  if ((smem_event_connect_request= CreateEvent(sa_event,
                                               FALSE, FALSE, tmp)) == 0)
5747
  {
5748
    errmsg= "Could not create request event";
5749 5750
    goto error;
  }
5751
  strmov(suffix_pos, "CONNECT_ANSWER");
5752
  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5753
  {
5754
    errmsg="Could not create answer event";
5755 5756
    goto error;
  }
5757
  strmov(suffix_pos, "CONNECT_DATA");
5758 5759 5760
  if ((handle_connect_file_map=
       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
5761
  {
5762
    errmsg= "Could not create file mapping";
5763 5764
    goto error;
  }
5765 5766 5767
  if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
						  FILE_MAP_WRITE,0,0,
						  sizeof(DWORD))) == 0)
5768
  {
5769
    errmsg= "Could not create shared memory service";
5770 5771 5772 5773 5774
    goto error;
  }

  while (!abort_loop)
  {
5775
    /* Wait a request from client */
5776
    WaitForSingleObject(smem_event_connect_request,INFINITE);
5777

unknown's avatar
unknown committed
5778 5779 5780
    /*
       it can be after shutdown command
    */
unknown's avatar
Merge  
unknown committed
5781
    if (abort_loop)
unknown's avatar
unknown committed
5782
      goto error;
5783

5784 5785 5786 5787 5788 5789
    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
5790
    HANDLE event_conn_closed= 0;
5791
    THD *thd= 0;
5792

5793
    p= int10_to_str(connect_number, connect_number_char, 10);
5794 5795 5796 5797 5798 5799 5800 5801 5802 5803
    /*
      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);
5804
    strmov(suffix_pos, "DATA");
5805 5806 5807
    if ((handle_client_file_map=
         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
5808
    {
5809
      errmsg= "Could not create file mapping";
5810 5811
      goto errorconn;
    }
5812 5813 5814
    if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
						  FILE_MAP_WRITE,0,0,
						  smem_buffer_length)) == 0)
5815
    {
5816
      errmsg= "Could not create memory map";
5817 5818 5819
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_WROTE");
5820
    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5821
    {
5822
      errmsg= "Could not create client write event";
5823 5824 5825
      goto errorconn;
    }
    strmov(suffix_pos, "CLIENT_READ");
5826
    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5827
    {
5828
      errmsg= "Could not create client read event";
5829 5830 5831
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_READ");
5832
    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5833
    {
5834
      errmsg= "Could not create server read event";
5835 5836 5837
      goto errorconn;
    }
    strmov(suffix_pos, "SERVER_WROTE");
5838 5839
    if ((event_server_wrote= CreateEvent(sa_event,
                                         FALSE, FALSE, tmp)) == 0)
5840
    {
5841
      errmsg= "Could not create server write event";
5842 5843
      goto errorconn;
    }
unknown's avatar
unknown committed
5844
    strmov(suffix_pos, "CONNECTION_CLOSED");
5845 5846
    if ((event_conn_closed= CreateEvent(sa_event,
                                        TRUE, FALSE, tmp)) == 0)
unknown's avatar
unknown committed
5847 5848 5849 5850
    {
      errmsg= "Could not create closed connection event";
      goto errorconn;
    }
5851
    if (abort_loop)
5852
      goto errorconn;
5853 5854 5855
    if (!(thd= new THD))
      goto errorconn;
    /* Send number of connection to client */
5856
    int4store(handle_connect_map, connect_number);
5857
    if (!SetEvent(event_connect_answer))
5858
    {
5859
      errmsg= "Could not send answer event";
5860 5861
      goto errorconn;
    }
5862
    /* Set event that client should receive data */
5863 5864
    if (!SetEvent(event_client_read))
    {
5865
      errmsg= "Could not set client to read mode";
5866 5867
      goto errorconn;
    }
5868
    if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
unknown's avatar
unknown committed
5869 5870 5871 5872 5873
                                                   handle_client_map,
                                                   event_client_wrote,
                                                   event_client_read,
                                                   event_server_wrote,
                                                   event_server_read,
unknown's avatar
unknown committed
5874
                                                   event_conn_closed)) ||
unknown's avatar
unknown committed
5875
                        my_net_init(&thd->net, thd->net.vio))
5876
    {
5877
      close_connection(thd, ER_OUT_OF_RESOURCES, 1);
5878 5879
      errmsg= 0;
      goto errorconn;
5880
    }
5881
    thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
5882
    create_new_thread(thd);
5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894
    connect_number++;
    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);
    }
5895
    if (handle_client_file_map)
unknown's avatar
unknown committed
5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908
      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);
5909
    delete thd;
5910
  }
5911 5912

  /* End shared memory handling */
5913
error:
5914 5915 5916
  if (tmp)
    my_free(tmp, MYF(0));

5917 5918 5919 5920 5921 5922
  if (errmsg)
  {
    char buff[180];
    strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
    sql_perror(buff);
  }
5923 5924
  my_security_attr_free(sa_event);
  my_security_attr_free(sa_mapping);
5925 5926 5927
  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);
5928
  if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
5929 5930

  decrement_handler_count();
5931 5932 5933
  DBUG_RETURN(0);
}
#endif /* HAVE_SMEM */
5934
#endif /* EMBEDDED_LIBRARY */
unknown's avatar
unknown committed
5935

5936 5937 5938

/****************************************************************************
  Handle start options
unknown's avatar
unknown committed
5939 5940
******************************************************************************/

5941
DYNAMIC_ARRAY all_options;
5942

5943 5944 5945 5946 5947
/**
  System variables are automatically command-line options (few
  exceptions are documented in sys_var.h), so don't need
  to be listed here.
*/
5948

Marc Alff's avatar
Marc Alff committed
5949
struct my_option my_long_options[]=
5950
{
unknown's avatar
unknown committed
5951
  {"help", '?', "Display this help and exit.", 
5952
   (uchar**) &opt_help, (uchar**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
unknown's avatar
unknown committed
5953 5954
   0, 0},
#ifdef HAVE_REPLICATION
5955
  {"abort-slave-event-count", 0,
unknown's avatar
unknown committed
5956
   "Option used by mysql-test for debugging and testing of replication.",
5957
   (uchar**) &abort_slave_event_count,  (uchar**) &abort_slave_event_count,
unknown's avatar
unknown committed
5958 5959
   0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
5960
  {"allow-suspicious-udfs", 0,
unknown's avatar
unknown committed
5961 5962
   "Allows use of UDFs consisting of only one symbol xxx() "
   "without corresponding xxx_init() or xxx_deinit(). That also means "
5963 5964
   "that one can load any function from any library, for example exit() "
   "from libc.so",
5965
   (uchar**) &opt_allow_suspicious_udfs, (uchar**) &opt_allow_suspicious_udfs,
5966
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
5967 5968
  {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0,
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
5969
  {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
5970
   (uchar**) &my_bind_addr_str, (uchar**) &my_bind_addr_str, 0, GET_STR,
unknown's avatar
unknown committed
5971
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5972 5973 5974
  {"binlog-do-db", OPT_BINLOG_DO_DB,
   "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
5975
  {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
5976
   "Tells the master that updates to the given database should not be logged tothe binary log.",
5977
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5978
  {"binlog-row-event-max-size", 0,
5979 5980 5981
   "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.",
5982 5983
   (uchar**) &opt_binlog_rows_event_max_size, 
   (uchar**) &opt_binlog_rows_event_max_size, 0, 
5984 5985 5986 5987 5988
   GET_ULONG, REQUIRED_ARG, 
   /* def_value */ 1024, /* min_value */  256, /* max_value */ ULONG_MAX, 
   /* sub_size */     0, /* block_size */ 256, 
   /* app_type */ 0
  },
5989
#ifndef DISABLE_GRANT_OPTIONS
5990
  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
5991
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
5992
#endif
5993
  {"character-set-client-handshake", 0,
unknown's avatar
unknown committed
5994
   "Don't ignore client side character set value sent during handshake.",
5995 5996
   (uchar**) &opt_character_set_client_handshake,
   (uchar**) &opt_character_set_client_handshake,
5997
    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
5998
  {"character-set-filesystem", 0,
unknown's avatar
unknown committed
5999
   "Set the filesystem character set.",
6000 6001
   (uchar**) &character_set_filesystem_name,
   (uchar**) &character_set_filesystem_name,
unknown's avatar
unknown committed
6002
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6003
  {"character-set-server", 'C', "Set the default character set.",
6004
   (uchar**) &default_character_set_name, (uchar**) &default_character_set_name,
unknown's avatar
unknown committed
6005
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6006
  {"chroot", 'r', "Chroot mysqld daemon during startup.",
6007
   (uchar**) &mysqld_chroot, (uchar**) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6008
   0, 0, 0, 0, 0, 0},
6009
  {"collation-server", 0, "Set the default collation.",
6010
   (uchar**) &default_collation_name, (uchar**) &default_collation_name,
unknown's avatar
unknown committed
6011
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6012
  {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.",
6013
   (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
6014
   0, 0, 0},
6015
  {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
6016
   NO_ARG, 0, 0, 0, 0, 0, 0},
6017 6018 6019
  /* 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. */
6020 6021
  {"default-storage-engine", 0, "The default storage engine for new tables",
   (uchar**) &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
6022
   0, 0, 0, 0, 0, 0 },
6023
  {"default-time-zone", 0, "Set the default time zone.",
6024
   (uchar**) &default_tz_name, (uchar**) &default_tz_name,
6025
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
unknown's avatar
unknown committed
6026
#ifdef HAVE_OPENSSL
6027
  {"des-key-file", 0,
unknown's avatar
unknown committed
6028
   "Load keys for des_encrypt() and des_encrypt from given file.",
6029
   (uchar**) &des_key_file, (uchar**) &des_key_file, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6030 6031 6032
   0, 0, 0, 0, 0, 0},
#endif /* HAVE_OPENSSL */
#ifdef HAVE_REPLICATION
6033
  {"disconnect-slave-event-count", 0,
unknown's avatar
unknown committed
6034
   "Option used by mysql-test for debugging and testing of replication.",
6035 6036
   (uchar**) &disconnect_slave_event_count,
   (uchar**) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
unknown's avatar
unknown committed
6037 6038
   0, 0, 0},
#endif /* HAVE_REPLICATION */
6039
#ifdef HAVE_STACK_TRACE_ON_SEGV
6040
  {"enable-pstack", 0, "Print a symbolic stack trace on failure.",
6041
   (uchar**) &opt_do_pstack, (uchar**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
6042
   0, 0, 0, 0},
6043
#endif /* HAVE_STACK_TRACE_ON_SEGV */
6044
  /* See how it's handled in get_one_option() */
6045 6046
  {"exit-info", 'T', "Used for debugging;  Use at your own risk!", 0, 0, 0,
   GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
6047
  {"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.",
6048
   (uchar**) &opt_external_locking, (uchar**) &opt_external_locking,
unknown's avatar
unknown committed
6049
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6050 6051
  /* We must always support the next option to make scripts like mysqltest
     easier to do */
6052
  {"gdb", 0,
6053
   "Set up signals usable for debugging",
6054
   (uchar**) &opt_debugging, (uchar**) &opt_debugging,
6055
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6056
#ifdef HAVE_LARGE_PAGE_OPTION
6057
  {"super-large-pages", 0, "Enable support for super large pages.",
6058
   (uchar**) &opt_super_large_pages, (uchar**) &opt_super_large_pages, 0,
6059
   GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
unknown's avatar
Merge  
unknown committed
6060
#endif
6061
  {"language", 'L',
6062 6063 6064 6065
   "Client error messages in given language. May be given as a full path. "
   "Deprecated. Use --lc-messages-dir instead.",
   (uchar**) &lc_messages_dir_ptr, (uchar**) &lc_messages_dir_ptr, 0,
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6066
  {"lc-messages", 0,
6067 6068 6069
   "Set the language used for the error messages.",
   (uchar**) &lc_messages, (uchar**) &lc_messages, 0, GET_STR, REQUIRED_ARG,
   0, 0, 0, 0, 0, 0 },
6070
  {"lc-time-names", 0,
6071
   "Set the language used for the month names and the days of the week.",
6072 6073
   (uchar**) &lc_time_names_name,
   (uchar**) &lc_time_names_name,
6074
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
6075
  {"log", 'l', "Log connections and queries to file (deprecated option, use "
6076 6077
   "--general-log/--general-log-file instead).", (uchar**) &opt_logname,
   (uchar**) &opt_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0},
6078
  {"log-bin", OPT_BIN_LOG,
unknown's avatar
Merge  
unknown committed
6079 6080 6081
   "Log update queries in binary format. Optional (but strongly recommended "
   "to avoid replication problems if server's hostname changes) argument "
   "should be the chosen location for the binary log files.",
6082
   (uchar**) &opt_bin_logname, (uchar**) &opt_bin_logname, 0, GET_STR_ALLOC,
unknown's avatar
unknown committed
6083
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6084
  {"log-bin-index", 0,
6085
   "File that holds the names for last binary log files.",
6086
   (uchar**) &opt_binlog_index_name, (uchar**) &opt_binlog_index_name, 0, GET_STR,
6087
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6088
  {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
6089
   (uchar**) &myisam_log_filename, (uchar**) &myisam_log_filename, 0, GET_STR,
6090
   OPT_ARG, 0, 0, 0, 0, 0, 0},
6091
  {"log-short-format", 0,
unknown's avatar
unknown committed
6092
   "Don't log extra information to update and slow-query logs.",
6093
   (uchar**) &opt_short_log_format, (uchar**) &opt_short_log_format,
unknown's avatar
unknown committed
6094
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6095
  {"log-slow-admin-statements", 0,
6096
   "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.",
6097 6098
   (uchar**) &opt_log_slow_admin_statements,
   (uchar**) &opt_log_slow_admin_statements,
6099
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6100
 {"log-slow-slave-statements", 0,
6101 6102 6103 6104
  "Log slow statements executed by slave thread to the slow log if it is open.",
  (uchar**) &opt_log_slow_slave_statements,
  (uchar**) &opt_log_slow_slave_statements,
  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
Konstantin Osipov's avatar
Konstantin Osipov committed
6105 6106 6107 6108 6109
  {"log-slow-queries", OPT_SLOW_QUERY_LOG,
   "Log slow queries to a table or log file. Defaults logging to table "
   "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
   "Must be enabled to activate other slow log options. "
   "Deprecated option, use --slow-query-log/--slow-query-log-file instead.",
6110
   (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR_ALLOC, OPT_ARG,
unknown's avatar
unknown committed
6111
   0, 0, 0, 0, 0, 0},
6112
  {"log-tc", 0,
unknown's avatar
Merge  
unknown committed
6113 6114
   "Path to transaction coordinator log (used for transactions that affect "
   "more than one storage engine, when binary log is disabled)",
6115
   (uchar**) &opt_tc_log_file, (uchar**) &opt_tc_log_file, 0, GET_STR,
unknown's avatar
Merge  
unknown committed
6116
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6117
#ifdef HAVE_MMAP
6118
  {"log-tc-size", 0, "Size of transaction coordinator log.",
6119
   (uchar**) &opt_tc_log_size, (uchar**) &opt_tc_log_size, 0, GET_ULONG,
6120 6121
   REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0,
   TC_LOG_PAGE_SIZE, 0},
6122
#endif
6123
  {"master-info-file", 0,
unknown's avatar
unknown committed
6124 6125
   "The location and name of the file that remembers the master and where the I/O replication \
thread is in the master's binlogs.",
6126
   (uchar**) &master_info_file, (uchar**) &master_info_file, 0, GET_STR,
unknown's avatar
unknown committed
6127
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6128
  {"master-retry-count", 0,
6129
   "The number of tries the slave will make to connect to the master before giving up.",
6130
   (uchar**) &master_retry_count, (uchar**) &master_retry_count, 0, GET_ULONG,
6131
   REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6132
#ifdef HAVE_REPLICATION
6133 6134 6135 6136
  {"init-rpl-role", 0, "Set the replication role.",
    (uchar**)&rpl_status, (uchar**)&rpl_status, &rpl_role_typelib,
   GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"max-binlog-dump-events", 0,
6137
   "Option used by mysql-test for debugging and testing of replication.",
6138
   (uchar**) &max_binlog_dump_events, (uchar**) &max_binlog_dump_events, 0,
6139
   GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6140
#endif /* HAVE_REPLICATION */
6141
  {"memlock", 0, "Lock mysqld in memory.", (uchar**) &locked_in_memory,
6142
   (uchar**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6143
  {"one-thread", OPT_ONE_THREAD,
unknown's avatar
unknown committed
6144 6145
   "(deprecated): Only use one thread (for debugging under Linux). Use thread-handling=no-threads instead",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6146
  {"old-style-user-limits", 0,
unknown's avatar
Merge  
unknown committed
6147
   "Enable old-style user limits (before 5.0.3 user resources were counted per each user+host vs. per account)",
6148
   (uchar**) &opt_old_style_user_limits, (uchar**) &opt_old_style_user_limits,
unknown's avatar
Merge  
unknown committed
6149
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6150
  {"port-open-timeout", 0,
6151
   "Maximum time in seconds to wait for the port to become free. "
6152 6153
   "(Default: no wait)", (uchar**) &mysqld_port_timeout,
   (uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166
  {"replicate-do-db", OPT_REPLICATE_DO_DB,
   "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.%.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
   "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 to replicate-do-db.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
   "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-table=db_name.%. ",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
   "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-datbase updates, in contrast to replicate-ignore-db.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
6167
   "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.",
6168
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6169
#ifdef HAVE_REPLICATION
6170
  {"replicate-same-server-id", 0,
6171 6172 6173
   "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.",
6174 6175
   (uchar**) &replicate_same_server_id,
   (uchar**) &replicate_same_server_id,
6176
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6177
#endif
unknown's avatar
unknown committed
6178 6179 6180 6181 6182 6183
  {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
   "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.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
   "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.",
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6184 6185
  {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6186
  {"safe-user-create", 0,
6187
   "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
6188
   (uchar**) &opt_safe_user_create, (uchar**) &opt_safe_user_create, 0, GET_BOOL,
6189
   NO_ARG, 0, 0, 0, 0, 0, 0},
6190 6191 6192 6193 6194 6195 6196 6197 6198
#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
  {"safemalloc", 0, "Enable the memory allocation checking.",
   (uchar**) &sf_malloc_quick, (uchar**) &sf_malloc_quick, 0,
   GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
  {"safemalloc-mem-limit", 0, "Simulate memory shortage.",
   (uchar**)&sf_malloc_mem_limit, (uchar**)&sf_malloc_mem_limit, 0, GET_UINT,
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
  {"show-slave-auth-info", 0,
6199
   "Show user and password in SHOW SLAVE HOSTS on this master",
6200
   (uchar**) &opt_show_slave_auth_info, (uchar**) &opt_show_slave_auth_info, 0,
6201
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6202
#ifndef DISABLE_GRANT_OPTIONS
6203
  {"skip-grant-tables", 0,
6204
   "Start without grant tables. This gives all users FULL ACCESS to all tables!",
6205
   (uchar**) &opt_noacl, (uchar**) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6206
   0},
6207
#endif
unknown's avatar
unknown committed
6208 6209
  {"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},
6210
  {"skip-name-resolve", OPT_SKIP_RESOLVE,
6211
   "Don't resolve hostnames. All hostnames are IP's or 'localhost'.",
6212 6213 6214
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"skip-new", OPT_SKIP_NEW, "Don't use new, possible wrong routines.",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6215
  {"skip-slave-start", 0,
6216 6217
   "If set, slave is not autostarted.", (uchar**) &opt_skip_slave_start,
   (uchar**) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6218
  {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
6219
   "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
6220 6221
   0, 0, 0, 0},
  {"skip-thread-priority", OPT_SKIP_PRIOR,
Konstantin Osipov's avatar
Konstantin Osipov committed
6222 6223 6224
   "Don't give threads different priorities. This option is deprecated "
   "because it has no effect; the implied behavior is already the default.",
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
unknown's avatar
SCRUM  
unknown committed
6225
#ifdef HAVE_REPLICATION
6226
  {"sporadic-binlog-dump-fail", 0,
unknown's avatar
unknown committed
6227
   "Option used by mysql-test for debugging and testing of replication.",
6228 6229
   (uchar**) &opt_sporadic_binlog_dump_fail,
   (uchar**) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
unknown's avatar
unknown committed
6230 6231
   0},
#endif /* HAVE_REPLICATION */
6232
#ifdef HAVE_OPENSSL
6233 6234 6235 6236
  {"ssl", 0,
   "Enable SSL for connection (automatically enabled with other flags).",
   (uchar **) &opt_use_ssl, (uchar **) &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
   0, 0, 0},
6237
#endif
unknown's avatar
unknown committed
6238
#ifdef __WIN__
6239
  {"standalone", 0,
unknown's avatar
unknown committed
6240 6241 6242 6243
  "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.",
6244
   (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG,
6245 6246 6247 6248 6249
   /*
     The system call realpath() produces warnings under valgrind and
     purify. These are not suppressed: instead we disable symlinks
     option if compiled with valgrind support.
   */
6250
   IF_PURIFY(0,1), 0, 0, 0, 0, 0},
6251
  {"sysdate-is-now", 0,
unknown's avatar
unknown committed
6252
   "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.",
6253
   (uchar**) &global_system_variables.sysdate_is_now,
unknown's avatar
unknown committed
6254
   0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
6255
  {"tc-heuristic-recover", 0,
unknown's avatar
unknown committed
6256
   "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.",
6257 6258
   (uchar**) &tc_heuristic_recover, (uchar**) &tc_heuristic_recover,
   &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
Ingo Struewing's avatar
Ingo Struewing committed
6259 6260 6261 6262 6263 6264 6265 6266
#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.",
   (uchar**) &opt_debug_sync_timeout, 0,
   0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
#endif /* defined(ENABLED_DEBUG_SYNC) */
6267
  {"temp-pool", 0,
6268
#if (ENABLE_TEMP_POOL)
6269
   "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.",
6270 6271 6272
#else
   "This option is ignored on this OS.",
#endif
6273
   (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
unknown's avatar
unknown committed
6274
   0, 0, 0, 0, 0},
6275 6276 6277 6278 6279
  {"transaction-isolation", 0,
   "Default transaction isolation level.",
   (uchar**)&global_system_variables.tx_isolation,
   (uchar**)&global_system_variables.tx_isolation, &tx_isolation_typelib,
   GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6280
  {"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.",
6281
   (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG,
6282
   IF_PURIFY(0,1), 0, 0, 0, 0, 0},
6283
  {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
unknown's avatar
unknown committed
6284
   0, 0, 0, 0, 0, 0},
unknown's avatar
unknown committed
6285
  {"verbose", 'v', "Used with --help option for detailed help",
6286
   (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
unknown's avatar
unknown committed
6287
   0, 0},
6288
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
6289
   NO_ARG, 0, 0, 0, 0, 0, 0},
6290
  {"plugin-load", 0,
6291
   "Optional semicolon-separated list of plugins to load, where each plugin is "
6292 6293
   "identified as name=library, where name is the plugin name and library "
   "is the plugin library in plugin_dir.",
6294
   (uchar**) &opt_plugin_load, (uchar**) &opt_plugin_load, 0,
unknown's avatar
WL#2936  
unknown committed
6295
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6296
  {"table_cache", 0, "Deprecated; use --table-open-cache instead.",
6297
   (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG,
6298
   REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
6299
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
6300
};
unknown's avatar
unknown committed
6301

6302

6303
static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
6304
{
6305
  var->type= SHOW_LONGLONG;
6306 6307 6308 6309
  var->value= (char *)&thd->query_id;
  return 0;
}

6310

6311
static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
6312
{
6313
  var->type= SHOW_MY_BOOL;
6314 6315 6316 6317
  var->value= (char *)&thd->net.compress;
  return 0;
}

6318
static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
6319
{
6320
  var->type= SHOW_LONG;
6321
  var->value= buff;
unknown's avatar
unknown committed
6322
  *((long *)buff)= (long) (thd->query_start() - server_start_time);
6323 6324 6325
  return 0;
}

6326
#ifdef ENABLED_PROFILING
6327 6328 6329 6330 6331 6332 6333
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;
}
6334
#endif
6335

6336
#ifdef HAVE_REPLICATION
6337
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
6338
{
6339
  var->type= SHOW_CHAR;
6340 6341 6342 6343
  var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
  return 0;
}

6344
static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
6345
{
6346
  var->type= SHOW_MY_BOOL;
Marc Alff's avatar
Marc Alff committed
6347
  mysql_mutex_lock(&LOCK_active_mi);
6348
  var->value= buff;
6349 6350
  *((my_bool *)buff)= (my_bool) (active_mi && 
                                 active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
6351
                                 active_mi->rli.slave_running);
Marc Alff's avatar
Marc Alff committed
6352
  mysql_mutex_unlock(&LOCK_active_mi);
6353 6354 6355
  return 0;
}

6356
static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
6357 6358 6359 6360 6361
{
  /*
    TODO: with multimaster, have one such counter per line in
    SHOW SLAVE STATUS, and have the sum over all lines here.
  */
Marc Alff's avatar
Marc Alff committed
6362
  mysql_mutex_lock(&LOCK_active_mi);
6363 6364
  if (active_mi)
  {
6365
    var->type= SHOW_LONG;
6366
    var->value= buff;
Marc Alff's avatar
Marc Alff committed
6367
    mysql_mutex_lock(&active_mi->rli.data_lock);
6368
    *((long *)buff)= (long)active_mi->rli.retried_trans;
Marc Alff's avatar
Marc Alff committed
6369
    mysql_mutex_unlock(&active_mi->rli.data_lock);
6370 6371
  }
  else
6372
    var->type= SHOW_UNDEF;
Marc Alff's avatar
Marc Alff committed
6373
  mysql_mutex_unlock(&LOCK_active_mi);
6374 6375
  return 0;
}
Andrei Elkin's avatar
Andrei Elkin committed
6376 6377 6378

static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
{
Marc Alff's avatar
Marc Alff committed
6379
  mysql_mutex_lock(&LOCK_active_mi);
Andrei Elkin's avatar
Andrei Elkin committed
6380 6381 6382 6383
  if (active_mi)
  {
    var->type= SHOW_LONGLONG;
    var->value= buff;
Marc Alff's avatar
Marc Alff committed
6384
    mysql_mutex_lock(&active_mi->rli.data_lock);
Andrei Elkin's avatar
Andrei Elkin committed
6385
    *((longlong *)buff)= active_mi->received_heartbeats;
Marc Alff's avatar
Marc Alff committed
6386
    mysql_mutex_unlock(&active_mi->rli.data_lock);
Andrei Elkin's avatar
Andrei Elkin committed
6387 6388 6389
  }
  else
    var->type= SHOW_UNDEF;
Marc Alff's avatar
Marc Alff committed
6390
  mysql_mutex_unlock(&LOCK_active_mi);
Andrei Elkin's avatar
Andrei Elkin committed
6391 6392 6393 6394 6395
  return 0;
}

static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
{
Marc Alff's avatar
Marc Alff committed
6396
  mysql_mutex_lock(&LOCK_active_mi);
Andrei Elkin's avatar
Andrei Elkin committed
6397 6398 6399 6400 6401 6402 6403 6404
  if (active_mi)
  {
    var->type= SHOW_CHAR;
    var->value= buff;
    my_sprintf(buff, (buff, "%.3f",active_mi->heartbeat_period));
  }
  else
    var->type= SHOW_UNDEF;
Marc Alff's avatar
Marc Alff committed
6405
  mysql_mutex_unlock(&LOCK_active_mi);
Andrei Elkin's avatar
Andrei Elkin committed
6406 6407 6408 6409
  return 0;
}


6410 6411
#endif /* HAVE_REPLICATION */

6412
static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
6413
{
6414
  var->type= SHOW_LONG;
6415 6416 6417 6418 6419
  var->value= buff;
  *((long *)buff)= (long)cached_open_tables();
  return 0;
}

unknown's avatar
unknown committed
6420 6421 6422 6423
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
6424
  mysql_mutex_lock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
6425
  *((long *)buff)= (long)prepared_stmt_count;
Marc Alff's avatar
Marc Alff committed
6426
  mysql_mutex_unlock(&LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
6427 6428 6429
  return 0;
}

6430
static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
6431
{
6432
  var->type= SHOW_LONG;
6433 6434 6435 6436 6437 6438 6439
  var->value= buff;
  *((long *)buff)= (long)cached_table_definitions();
  return 0;
}

#ifdef HAVE_OPENSSL
/* Functions relying on CTX */
6440
static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
6441
{
6442
  var->type= SHOW_LONG;
6443 6444 6445 6446 6447 6448
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
  return 0;
}

6449
static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
6450
{
6451
  var->type= SHOW_LONG;
6452 6453 6454 6455 6456 6457
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

6458
static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
6459
{
6460
  var->type= SHOW_LONG;
6461 6462 6463 6464 6465 6466
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
  return 0;
}

6467
static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
6468
{
6469
  var->type= SHOW_LONG;
6470 6471 6472 6473 6474 6475
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

6476
static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
6477
{
6478
  var->type= SHOW_LONG;
6479 6480 6481 6482 6483 6484
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
  return 0;
}

6485
static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
6486
{
6487
  var->type= SHOW_LONG;
6488 6489 6490 6491 6492 6493
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

6494
static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
6495
{
6496
  var->type= SHOW_LONG;
6497 6498 6499 6500 6501 6502
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
  return 0;
}

6503
static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
6504
{
6505
  var->type= SHOW_LONG;
6506 6507 6508 6509 6510 6511
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
  return 0;
}

6512
static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
6513
{
6514
  var->type= SHOW_LONG;
6515 6516 6517 6518 6519 6520
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
  return 0;
}

6521
static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
6522
{
6523
  var->type= SHOW_LONG;
6524 6525 6526 6527 6528 6529
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
  return 0;
}

6530
static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
6531
{
6532
  var->type= SHOW_LONG;
6533 6534 6535 6536 6537 6538
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
  return 0;
}

6539
static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
6540
{
6541
  var->type= SHOW_LONG;
6542 6543 6544 6545 6546 6547
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
  return 0;
}

6548
static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
6549
{
6550
  var->type= SHOW_LONG;
6551 6552 6553 6554 6555 6556
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
  return 0;
}

6557
static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
6558
{
6559
  var->type= SHOW_LONG;
6560 6561 6562 6563 6564 6565
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
  return 0;
}

6566
static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
6567
{
6568
  var->type= SHOW_LONG;
6569 6570 6571 6572 6573 6574
  var->value= buff;
  *((long *)buff)= (!ssl_acceptor_fd ? 0 :
                     SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
  return 0;
}

6575
static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
6576
{
6577
  var->type= SHOW_CHAR;
6578
  if (!ssl_acceptor_fd)
unknown's avatar
unknown committed
6579
    var->value= const_cast<char*>("NONE");
6580 6581 6582 6583
  else
    switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
    {
    case SSL_SESS_CACHE_OFF:
unknown's avatar
unknown committed
6584
      var->value= const_cast<char*>("OFF"); break;
6585
    case SSL_SESS_CACHE_CLIENT:
unknown's avatar
unknown committed
6586
      var->value= const_cast<char*>("CLIENT"); break;
6587
    case SSL_SESS_CACHE_SERVER:
unknown's avatar
unknown committed
6588
      var->value= const_cast<char*>("SERVER"); break;
6589
    case SSL_SESS_CACHE_BOTH:
unknown's avatar
unknown committed
6590
      var->value= const_cast<char*>("BOTH"); break;
6591
    case SSL_SESS_CACHE_NO_AUTO_CLEAR:
unknown's avatar
unknown committed
6592
      var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
6593
    case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
unknown's avatar
unknown committed
6594
      var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
6595
    default:
unknown's avatar
unknown committed
6596
      var->value= const_cast<char*>("Unknown"); break;
6597 6598 6599 6600
    }
  return 0;
}

6601 6602 6603 6604 6605 6606 6607
/*
   Functions relying on SSL 
   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.
 */
6608
static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
6609
{
6610
  var->type= SHOW_CHAR;
6611 6612 6613
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
  else
6614
    var->value= (char *)"";
6615 6616 6617
  return 0;
}

6618
static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
6619
{
6620
  var->type= SHOW_LONG;
6621
  var->value= buff;
6622 6623 6624 6625
  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
6626
  return 0;
6627 6628
}

6629
static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
6630
{
6631
  var->type= SHOW_LONG;
6632
  var->value= buff;
6633 6634 6635 6636
  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;
6637 6638 6639
  return 0;
}

6640
static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
6641
{
6642
  var->type= SHOW_LONG;
6643
  var->value= buff;
6644 6645 6646 6647
  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;
6648 6649 6650
  return 0;
}

6651
static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
6652
{
6653
  var->type= SHOW_LONG;
6654
  var->value= buff;
6655 6656 6657 6658
  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;
6659 6660 6661
  return 0;
}

6662
static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
6663
{
6664
  var->type= SHOW_CHAR;
6665 6666 6667
  if( thd->vio_ok() && thd->net.vio->ssl_arg )
    var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
  else
6668
    var->value= (char *)"";
6669 6670 6671
  return 0;
}

6672
static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
6673
{
6674
  var->type= SHOW_CHAR;
6675
  var->value= buff;
6676
  if (thd->vio_ok() && thd->net.vio->ssl_arg)
6677 6678 6679
  {
    int i;
    const char *p;
6680 6681 6682
    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++)
6683
    {
6684
      buff= strnmov(buff, p, end-buff-1);
6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695
      *buff++= ':';
    }
    if (i)
      buff--;
  }
  *buff=0;
  return 0;
}

#endif /* HAVE_OPENSSL */

6696

unknown's avatar
unknown committed
6697 6698 6699 6700
/*
  Variables shown by SHOW STATUS in alphabetical order
*/

6701
SHOW_VAR status_vars[]= {
6702 6703
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
6704 6705
  {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
  {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
6706 6707
  {"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
6708
  {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
6709
  {"Compression",              (char*) &show_net_compression, SHOW_FUNC},
6710
  {"Connections",              (char*) &thread_id,              SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
6711
  {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
6712
  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
unknown's avatar
Merge  
unknown committed
6713
  {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
6714
  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
6715
  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
6716
  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
6717
  {"Flush_commands",           (char*) &refresh_version,        SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732
  {"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},
  {"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},
  {"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},
  {"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},
  {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
  {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
6733
  {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
6734 6735
  {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
  {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
6736 6737 6738 6739
  {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
  {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
  {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
  {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
6740
  {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
6741
  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
6742 6743 6744
  {"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},
6745 6746
  {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_FUNC},
  {"Open_tables",              (char*) &show_open_tables,       SHOW_FUNC},
6747
  {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
unknown's avatar
Merge  
unknown committed
6748
  {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
6749
  {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
unknown's avatar
unknown committed
6750
  {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_FUNC},
unknown's avatar
unknown committed
6751
#ifdef HAVE_QUERY_CACHE
6752 6753
  {"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
6754
  {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
6755
  {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
6756
  {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
unknown's avatar
unknown committed
6757
  {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
6758 6759
  {"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
6760
#endif /*HAVE_QUERY_CACHE*/
6761
  {"Queries",                  (char*) &show_queries,            SHOW_FUNC},
6762
  {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
6763 6764 6765
#ifdef HAVE_REPLICATION
  {"Rpl_status",               (char*) &show_rpl_status,          SHOW_FUNC},
#endif
unknown's avatar
Merge  
unknown committed
6766 6767 6768 6769 6770
  {"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},
6771
  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
6772 6773
#ifdef HAVE_REPLICATION
  {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC},
Andrei Elkin's avatar
Andrei Elkin committed
6774 6775
  {"Slave_heartbeat_period",   (char*) &show_heartbeat_period, SHOW_FUNC},
  {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC},
6776 6777
  {"Slave_running",            (char*) &show_slave_running,     SHOW_FUNC},
#endif
6778
  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
unknown's avatar
Merge  
unknown committed
6779 6780 6781 6782 6783
  {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
  {"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
6784
#ifdef HAVE_OPENSSL
6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807
  {"Ssl_accept_renegotiates",  (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC},
  {"Ssl_accepts",              (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC},
  {"Ssl_callback_cache_hits",  (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC},
  {"Ssl_cipher",               (char*) &show_ssl_get_cipher, SHOW_FUNC},
  {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list, SHOW_FUNC},
  {"Ssl_client_connects",      (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC},
  {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC},
  {"Ssl_ctx_verify_depth",     (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC},
  {"Ssl_ctx_verify_mode",      (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC},
  {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout, SHOW_FUNC},
  {"Ssl_finished_accepts",     (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC},
  {"Ssl_finished_connects",    (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC},
  {"Ssl_session_cache_hits",   (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC},
  {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC},
  {"Ssl_session_cache_mode",   (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC},
  {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC},
  {"Ssl_session_cache_size",   (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC},
  {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC},
  {"Ssl_sessions_reused",      (char*) &show_ssl_session_reused, SHOW_FUNC},
  {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC},
  {"Ssl_verify_depth",         (char*) &show_ssl_get_verify_depth, SHOW_FUNC},
  {"Ssl_verify_mode",          (char*) &show_ssl_get_verify_mode, SHOW_FUNC},
  {"Ssl_version",              (char*) &show_ssl_get_version, SHOW_FUNC},
unknown's avatar
unknown committed
6808
#endif /* HAVE_OPENSSL */
unknown's avatar
unknown committed
6809 6810
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
6811
#ifdef HAVE_MMAP
unknown's avatar
Merge  
unknown committed
6812 6813 6814
  {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
  {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG},
  {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
6815
#endif
6816
  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_NOFLUSH},
Konstantin Osipov's avatar
Konstantin Osipov committed
6817
  {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
6818 6819
  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
  {"Threads_running",          (char*) &thread_running,         SHOW_INT},
6820
  {"Uptime",                   (char*) &show_starttime,         SHOW_FUNC},
6821
#ifdef ENABLED_PROFILING
6822
  {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_FUNC},
6823
#endif
6824
  {NullS, NullS, SHOW_LONG}
unknown's avatar
unknown committed
6825 6826
};

Marc Alff's avatar
Marc Alff committed
6827
bool add_terminator(DYNAMIC_ARRAY *options)
6828 6829
{
  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
6830
  return insert_dynamic(options, (uchar *)&empty_element);
6831 6832
}

6833
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
6834 6835
static void print_version(void)
{
6836
  set_server_version();
6837

6838 6839
  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
6840 6841
}

6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873
/** 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;
  init_alloc_root(&mem_root, 4096, 4096);

  pop_dynamic(&all_options);
Marc Alff's avatar
Marc Alff committed
6874
  sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
6875 6876
  add_plugin_options(&all_options, &mem_root);
  sort_dynamic(&all_options, (qsort_cmp) option_cmp);
Marc Alff's avatar
Marc Alff committed
6877
  add_terminator(&all_options);
6878 6879 6880 6881 6882 6883 6884 6885

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

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

unknown's avatar
unknown committed
6886 6887
static void usage(void)
{
6888
  DBUG_ENTER("usage");
6889
  if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
unknown's avatar
unknown committed
6890 6891 6892 6893 6894
					           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
6895
  print_version();
unknown's avatar
unknown committed
6896
  puts("\
6897
Copyright (C) 2000-2008 MySQL AB, by Monty and others\n\
6898
Copyright (C) 2008,2009 Sun Microsystems, Inc.\n\
unknown's avatar
unknown committed
6899
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
6900 6901
and you are welcome to modify and redistribute it under the GPL license\n\n\
Starts the MySQL database server\n");
unknown's avatar
unknown committed
6902 6903

  printf("Usage: %s [OPTIONS]\n", my_progname);
6904
  if (!opt_verbose)
6905
    puts("\nFor more help options (several pages), use mysqld --verbose --help");
6906 6907
  else
  {
unknown's avatar
unknown committed
6908 6909
#ifdef __WIN__
  puts("NT and Win32 specific options:\n\
6910 6911
  --install                     Install the default service (NT)\n\
  --install-manual              Install the default service started manually (NT)\n\
unknown's avatar
unknown committed
6912 6913
  --install service_name        Install an optional service (NT)\n\
  --install-manual service_name Install an optional service started manually (NT)\n\
6914
  --remove                      Remove the default service from the service list (NT)\n\
unknown's avatar
unknown committed
6915 6916 6917
  --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
6918
");
6919
  puts("");
unknown's avatar
unknown committed
6920
#endif
6921
  print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
unknown's avatar
unknown committed
6922 6923
  puts("");
  set_ports();
6924

unknown's avatar
WL#2936  
unknown committed
6925
  /* Print out all the options including plugin supplied options */
6926
  print_help();
6927

6928 6929 6930 6931 6932 6933 6934
  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
6935
  puts("\n\
unknown's avatar
unknown committed
6936
To see what values a running MySQL server is using, type\n\
6937
'mysqladmin variables' instead of 'mysqld --verbose --help'.");
6938
  }
6939
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
6940
}
6941
#endif /*!EMBEDDED_LIBRARY*/
unknown's avatar
unknown committed
6942

unknown's avatar
unknown committed
6943
/**
6944
  Initialize MySQL global variables to default values.
unknown's avatar
unknown committed
6945

unknown's avatar
unknown committed
6946
  @note
unknown's avatar
unknown committed
6947 6948 6949 6950
    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
6951

6952
    We don't need to set variables refered to in my_long_options
unknown's avatar
unknown committed
6953 6954
    as these are initialized by my_getopt.
*/
unknown's avatar
unknown committed
6955

6956
static int mysql_init_variables(void)
unknown's avatar
unknown committed
6957 6958 6959 6960
{
  /* Things reset to zero */
  opt_skip_slave_start= opt_reckless_slave = 0;
  mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
6961
  myisam_test_invalid_symlink= test_if_data_home_dir;
unknown's avatar
unknown committed
6962 6963
  opt_log= opt_slow_log= 0;
  opt_update_log= 0;
6964
  opt_bin_log= 0;
unknown's avatar
unknown committed
6965
  opt_disable_networking= opt_skip_show_db=0;
6966
  opt_ignore_builtin_innodb= 0;
unknown's avatar
Merge  
unknown committed
6967 6968
  opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
6969 6970
  opt_secure_auth= 0;
  opt_bootstrap= opt_myisam_log= 0;
unknown's avatar
unknown committed
6971 6972 6973 6974 6975 6976 6977 6978 6979
  mqh_used= 0;
  segfaulted= kill_in_progress= 0;
  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;
6980
  opt_using_transactions= 0;
unknown's avatar
unknown committed
6981 6982
  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
6983
  aborted_threads= aborted_connects= 0;
unknown's avatar
unknown committed
6984 6985
  delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
  delayed_insert_errors= thread_created= 0;
unknown's avatar
Merge  
unknown committed
6986
  specialflag= 0;
6987
  binlog_cache_use=  binlog_cache_disk_use= 0;
unknown's avatar
unknown committed
6988 6989
  max_used_connections= slow_launch_threads = 0;
  mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
6990
  prepared_stmt_count= 0;
6991
  mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
6992
  bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
unknown's avatar
Merge  
unknown committed
6993
  bzero((char *) &global_status_var, sizeof(global_status_var));
6994
  opt_large_pages= 0;
6995
  opt_super_large_pages= 0;
Ingo Struewing's avatar
Ingo Struewing committed
6996 6997 6998
#if defined(ENABLED_DEBUG_SYNC)
  opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
6999
  key_map_full.set_all();
unknown's avatar
unknown committed
7000

7001 7002 7003 7004 7005
  /* 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
7006
  character_set_filesystem= &my_charset_bin;
7007

unknown's avatar
unknown committed
7008 7009 7010 7011 7012
  opt_specialflag= SPECIAL_ENGLISH;
  unix_sock= ip_sock= INVALID_SOCKET;
  mysql_home_ptr= mysql_home;
  pidfile_name_ptr= pidfile_name;
  log_error_file_ptr= log_error_file;
7013
  lc_messages_dir_ptr= lc_messages_dir;
unknown's avatar
unknown committed
7014 7015
  protocol_version= PROTOCOL_VERSION;
  what_to_log= ~ (1L << (uint) COM_TIME);
7016
  refresh_version= 1L;	/* Increments on each reload */
7017
  global_query_id= thread_id= 1L;
7018
  my_atomic_rwlock_init(&global_query_id_lock);
7019
  my_atomic_rwlock_init(&thread_running_lock);
unknown's avatar
unknown committed
7020 7021 7022
  strmov(server_version, MYSQL_SERVER_VERSION);
  threads.empty();
  thread_cache.empty();
7023
  key_caches.empty();
unknown's avatar
unknown committed
7024
  if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
7025
                                                default_key_cache_base.length)))
7026 7027 7028 7029
  {
    sql_print_error("Cannot allocate the keycache");
    return 1;
  }
7030 7031
  /* set key_cache_hash.default_value = dflt_key_cache */
  multi_keycache_init();
unknown's avatar
unknown committed
7032 7033

  /* Set directory paths */
7034 7035 7036
  mysql_real_data_home_len=
    strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
            sizeof(mysql_real_data_home)-1) - mysql_real_data_home;
unknown's avatar
unknown committed
7037 7038
  /* Replication parameters */
  master_info_file= (char*) "master.info",
unknown's avatar
unknown committed
7039
    relay_log_info_file= (char*) "relay-log.info";
unknown's avatar
unknown committed
7040 7041 7042 7043 7044
  report_user= report_password = report_host= 0;	/* TO BE DELETED */
  opt_relay_logname= opt_relaylog_index_name= 0;

  /* Variables in libraries */
  charsets_dir= 0;
7045
  default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
7046
  default_collation_name= compiled_default_collation_name;
unknown's avatar
unknown committed
7047
  character_set_filesystem_name= (char*) "binary";
7048
  lc_messages= (char*) "en_US";
7049
  lc_time_names_name= (char*) "en_US";
7050
  
unknown's avatar
unknown committed
7051 7052 7053 7054 7055 7056
  /* 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");
#endif
  opt_error_log= IF_WIN(1,0);
7057 7058
#ifdef ENABLED_PROFILING
    have_profiling = SHOW_OPTION_YES;
7059
#else
7060
    have_profiling = SHOW_OPTION_NO;
7061
#endif
7062

unknown's avatar
unknown committed
7063
#ifdef HAVE_OPENSSL
7064
  have_ssl=SHOW_OPTION_YES;
unknown's avatar
unknown committed
7065
#else
7066
  have_ssl=SHOW_OPTION_NO;
unknown's avatar
unknown committed
7067
#endif
unknown's avatar
unknown committed
7068
#ifdef HAVE_BROKEN_REALPATH
unknown's avatar
unknown committed
7069 7070 7071 7072
  have_symlink=SHOW_OPTION_NO;
#else
  have_symlink=SHOW_OPTION_YES;
#endif
7073 7074 7075 7076 7077
#ifdef HAVE_DLOPEN
  have_dlopen=SHOW_OPTION_YES;
#else
  have_dlopen=SHOW_OPTION_NO;
#endif
unknown's avatar
unknown committed
7078 7079 7080 7081 7082
#ifdef HAVE_QUERY_CACHE
  have_query_cache=SHOW_OPTION_YES;
#else
  have_query_cache=SHOW_OPTION_NO;
#endif
7083 7084 7085 7086 7087 7088 7089 7090 7091 7092
#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
7093 7094 7095 7096 7097 7098
#ifdef HAVE_CRYPT
  have_crypt=SHOW_OPTION_YES;
#else
  have_crypt=SHOW_OPTION_NO;
#endif
#ifdef HAVE_COMPRESS
7099
  have_compress= SHOW_OPTION_YES;
unknown's avatar
unknown committed
7100
#else
7101
  have_compress= SHOW_OPTION_NO;
unknown's avatar
unknown committed
7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113
#endif
#ifdef HAVE_LIBWRAP
  libwrapName= NullS;
#endif
#ifdef HAVE_OPENSSL
  des_key_file = 0;
  ssl_acceptor_fd= 0;
#endif
#ifdef HAVE_SMEM
  shared_memory_base_name= default_shared_memory_base_name;
#endif

unknown's avatar
unknown committed
7114 7115
#if defined(__WIN__) || defined(__NETWARE__)
  /* Allow Win32 and NetWare users to move MySQL anywhere */
unknown's avatar
unknown committed
7116 7117
  {
    char prg_dev[LIBLEN];
7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129
#if defined __WIN__
	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
#endif
unknown's avatar
unknown committed
7130 7131 7132 7133 7134 7135
    my_path(prg_dev,my_progname,"mysql/bin");
    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
    cleanup_dirname(mysql_home,prg_dev);
  }
#else
  const char *tmpenv;
unknown's avatar
unknown committed
7136
  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
unknown's avatar
unknown committed
7137
    tmpenv = DEFAULT_MYSQL_HOME;
unknown's avatar
unknown committed
7138
  (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
unknown's avatar
unknown committed
7139
#endif
7140
  return 0;
unknown's avatar
unknown committed
7141 7142
}

7143 7144 7145 7146
my_bool
mysqld_get_one_option(int optid,
                      const struct my_option *opt __attribute__((unused)),
                      char *argument)
unknown's avatar
unknown committed
7147
{
7148 7149
  switch(optid) {
  case '#':
unknown's avatar
unknown committed
7150
#ifndef DBUG_OFF
unknown's avatar
unknown committed
7151
    DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
7152 7153 7154 7155
#endif
    opt_endinfo=1;				/* unireg: memory allocation */
    break;
  case 'a':
7156
    global_system_variables.sql_mode= MODE_ANSI;
unknown's avatar
unknown committed
7157
    global_system_variables.tx_isolation= ISO_SERIALIZABLE;
7158 7159 7160 7161
    break;
  case 'b':
    strmake(mysql_home,argument,sizeof(mysql_home)-1);
    break;
7162
  case 'C':
7163 7164
    if (default_collation_name == compiled_default_collation_name)
      default_collation_name= 0;
7165
    break;
7166
  case 'l':
7167
    WARN_DEPRECATED(NULL, 7, 0, "--log", "'--general-log'/'--general-log-file'");
7168 7169 7170 7171
    opt_log=1;
    break;
  case 'h':
    strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
unknown's avatar
unknown committed
7172
    /* Correct pointer set by my_getopt (for embedded library) */
7173
    mysql_real_data_home_ptr= mysql_real_data_home;
7174
    break;
7175
  case 'u':
7176
    if (!mysqld_user || !strcmp(mysqld_user, argument))
unknown's avatar
unknown committed
7177
      mysqld_user= argument;
7178
    else
7179
      sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
7180
    break;
7181
  case 'L':
7182
    strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1);
7183
    lc_messages_dir_ptr= lc_messages_dir;
7184
    break;
7185 7186
  case OPT_BINLOG_FORMAT:
    binlog_format_used= true;
7187
    break;
7188
#include <sslopt-case.h>
7189
#ifndef EMBEDDED_LIBRARY
7190 7191 7192
  case 'V':
    print_version();
    exit(0);
7193
#endif /*EMBEDDED_LIBRARY*/
7194 7195 7196 7197 7198 7199 7200 7201
  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;
7202 7203 7204 7205 7206 7207 7208 7209
  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:
7210
    opt_bin_log= test(argument != disabled_my_option);
7211
    break;
unknown's avatar
SCRUM  
unknown committed
7212
#ifdef HAVE_REPLICATION
7213
  case (int)OPT_REPLICATE_IGNORE_DB:
7214
  {
7215
    rpl_filter->add_ignore_db(argument);
7216 7217 7218 7219
    break;
  }
  case (int)OPT_REPLICATE_DO_DB:
  {
7220
    rpl_filter->add_do_db(argument);
7221 7222 7223 7224 7225
    break;
  }
  case (int)OPT_REPLICATE_REWRITE_DB:
  {
    char* key = argument,*p, *val;
7226

7227
    if (!(p= strstr(argument, "->")))
7228
    {
7229 7230
      sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
      return 1;
7231
    }
7232
    val= p--;
unknown's avatar
unknown committed
7233
    while (my_isspace(mysqld_charset, *p) && p > argument)
7234 7235
      *p-- = 0;
    if (p == argument)
7236
    {
7237 7238
      sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
      return 1;
7239
    }
7240 7241
    *val= 0;
    val+= 2;
unknown's avatar
unknown committed
7242
    while (*val && my_isspace(mysqld_charset, *val))
7243 7244
      *val++;
    if (!*val)
7245
    {
7246 7247
      sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
      return 1;
7248 7249
    }

7250
    rpl_filter->add_db_rewrite(key, val);
7251 7252 7253
    break;
  }

7254
  case (int)OPT_BINLOG_IGNORE_DB:
7255
  {
7256
    binlog_filter->add_ignore_db(argument);
7257 7258
    break;
  }
7259
  case (int)OPT_BINLOG_DO_DB:
7260
  {
7261
    binlog_filter->add_do_db(argument);
7262 7263
    break;
  }
7264
  case (int)OPT_REPLICATE_DO_TABLE:
7265
  {
7266
    if (rpl_filter->add_do_table(argument))
7267
    {
7268 7269
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
7270
    }
7271 7272
    break;
  }
7273
  case (int)OPT_REPLICATE_WILD_DO_TABLE:
7274
  {
7275
    if (rpl_filter->add_wild_do_table(argument))
7276
    {
7277 7278
      sql_print_error("Could not add do table rule '%s'!\n", argument);
      return 1;
7279
    }
7280 7281
    break;
  }
7282
  case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
7283
  {
7284
    if (rpl_filter->add_wild_ignore_table(argument))
7285
    {
7286 7287
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
7288
    }
7289 7290
    break;
  }
7291
  case (int)OPT_REPLICATE_IGNORE_TABLE:
7292
  {
7293
    if (rpl_filter->add_ignore_table(argument))
7294
    {
7295 7296
      sql_print_error("Could not add ignore table rule '%s'!\n", argument);
      return 1;
7297
    }
7298 7299
    break;
  }
unknown's avatar
SCRUM  
unknown committed
7300
#endif /* HAVE_REPLICATION */
7301
  case (int) OPT_SLOW_QUERY_LOG:
7302
    WARN_DEPRECATED(NULL, 7, 0, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'");
7303
    opt_slow_log= 1;
7304
    break;
7305 7306
  case (int) OPT_SKIP_NEW:
    opt_specialflag|= SPECIAL_NO_NEW_FUNC;
7307
    delay_key_write_options= DELAY_KEY_WRITE_NONE;
7308
    myisam_concurrent_insert=0;
7309
    myisam_recover_options= HA_RECOVER_OFF;
unknown's avatar
Merge  
unknown committed
7310
    sp_automatic_privileges=0;
7311
    my_use_symdir=0;
7312
    ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
unknown's avatar
unknown committed
7313
#ifdef HAVE_QUERY_CACHE
7314 7315 7316 7317 7318
    query_cache_size=0;
#endif
    break;
  case (int) OPT_SAFE:
    opt_specialflag|= SPECIAL_SAFE_MODE;
7319
    delay_key_write_options= DELAY_KEY_WRITE_NONE;
7320 7321
    myisam_recover_options= HA_RECOVER_DEFAULT;
    ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
7322 7323 7324
    break;
  case (int) OPT_SKIP_PRIOR:
    opt_specialflag|= SPECIAL_NO_PRIOR;
7325
    sql_print_warning("The --skip-thread-priority startup option is deprecated "
Konstantin Osipov's avatar
Konstantin Osipov committed
7326 7327
                      "and will be removed in MySQL 7.0. This option has no effect "
                      "as the implied behavior is already the default.");
7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342
    break;
  case (int) OPT_SKIP_HOST_CACHE:
    opt_specialflag|= SPECIAL_NO_HOST_CACHE;
    break;
  case (int) OPT_SKIP_RESOLVE:
    opt_specialflag|=SPECIAL_NO_RESOLVE;
    break;
  case (int) OPT_WANT_CORE:
    test_flags |= TEST_CORE_ON_SIGNAL;
    break;
  case (int) OPT_SKIP_STACK_TRACE:
    test_flags|=TEST_NO_STACKTRACE;
    break;
  case (int) OPT_BIND_ADDRESS:
    {
7343 7344 7345 7346 7347 7348 7349
      struct addrinfo *res_lst, hints;    

      bzero(&hints, sizeof(struct addrinfo));
      hints.ai_socktype= SOCK_STREAM;
      hints.ai_protocol= IPPROTO_TCP;

      if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0) 
unknown's avatar
unknown committed
7350
      {
7351 7352
        sql_print_error("Can't start server: cannot resolve hostname!");
        return 1;
unknown's avatar
unknown committed
7353
      }
7354 7355

      if (res_lst->ai_next)
7356
      {
7357
        sql_print_error("Can't start server: bind-address refers to multiple interfaces!");
7358
        return 1;
7359
      }
7360
      freeaddrinfo(res_lst);
7361 7362
    }
    break;
7363 7364 7365 7366
  case OPT_CONSOLE:
    if (opt_console)
      opt_error_log= 0;			// Force logs to stdout
    break;
7367 7368 7369 7370 7371 7372
  case OPT_BOOTSTRAP:
    opt_noacl=opt_bootstrap=1;
    break;
  case OPT_SERVER_ID:
    server_id_supplied = 1;
    break;
unknown's avatar
unknown committed
7373
  case OPT_ONE_THREAD:
7374
    thread_handling= SCHEDULER_ONE_THREAD_PER_CONNECTION;
7375
    break;
unknown's avatar
unknown committed
7376
  case OPT_LOWER_CASE_TABLE_NAMES:
7377
    lower_case_table_names_used= 1;
unknown's avatar
unknown committed
7378
    break;
Ingo Struewing's avatar
Ingo Struewing committed
7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394
#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) */
7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406
  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;
unknown's avatar
unknown committed
7407
  }
7408 7409
  return 0;
}
7410

7411

unknown's avatar
unknown committed
7412
/** Handle arguments for multiple key caches. */
7413

7414 7415 7416 7417
extern "C" int mysql_getopt_value(uchar **value,
                                  const char *keyname, uint key_length,
                                  const struct my_option *option,
                                  int *error);
7418

7419
static uchar* *
7420
mysql_getopt_value(const char *keyname, uint key_length,
7421
		   const struct my_option *option, int *error)
7422
{
7423 7424
  if (error)
    *error= 0;
7425 7426
  switch (option->id) {
  case OPT_KEY_BUFFER_SIZE:
unknown's avatar
unknown committed
7427
  case OPT_KEY_CACHE_BLOCK_SIZE:
7428 7429
  case OPT_KEY_CACHE_DIVISION_LIMIT:
  case OPT_KEY_CACHE_AGE_THRESHOLD:
7430
  {
unknown's avatar
unknown committed
7431
    KEY_CACHE *key_cache;
7432
    if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
7433 7434 7435 7436 7437
    {
      if (error)
        *error= EXIT_OUT_OF_MEMORY;
      return 0;
    }
7438 7439
    switch (option->id) {
    case OPT_KEY_BUFFER_SIZE:
7440
      return (uchar**) &key_cache->param_buff_size;
7441
    case OPT_KEY_CACHE_BLOCK_SIZE:
7442
      return (uchar**) &key_cache->param_block_size;
7443
    case OPT_KEY_CACHE_DIVISION_LIMIT:
7444
      return (uchar**) &key_cache->param_division_limit;
7445
    case OPT_KEY_CACHE_AGE_THRESHOLD:
7446
      return (uchar**) &key_cache->param_age_threshold;
7447
    }
7448 7449
  }
  }
7450
  return option->value;
7451 7452
}

7453
void option_error_reporter(enum loglevel level, const char *format, ...)
unknown's avatar
unknown committed
7454
{
7455
  va_list args;
unknown's avatar
unknown committed
7456
  va_start(args, format);
7457 7458 7459 7460 7461 7462 7463

  /* 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
7464
  va_end(args);
unknown's avatar
unknown committed
7465
}
7466

unknown's avatar
unknown committed
7467

unknown's avatar
unknown committed
7468
/**
Marc Alff's avatar
Marc Alff committed
7469 7470 7471 7472 7473 7474
  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
7475 7476 7477
  @todo
  - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
*/
Marc Alff's avatar
Marc Alff committed
7478
static int get_options(int *argc_ptr, char ***argv_ptr)
7479 7480 7481
{
  int ho_error;

7482
  my_getopt_register_get_addr(mysql_getopt_value);
7483
  my_getopt_error_reporter= option_error_reporter;
unknown's avatar
WL#2936  
unknown committed
7484

Marc Alff's avatar
Marc Alff committed
7485 7486 7487 7488
  /* prepare all_options array */
  my_init_dynamic_array(&all_options, sizeof(my_option),
                        array_elements(my_long_options),
                        array_elements(my_long_options)/4);
7489 7490 7491
  for (my_option *opt= my_long_options;
       opt < my_long_options + array_elements(my_long_options) - 1;
       opt++)
Marc Alff's avatar
Marc Alff committed
7492 7493 7494
    insert_dynamic(&all_options, (uchar*) opt);
  sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
  add_terminator(&all_options);
7495

unknown's avatar
WL#2936  
unknown committed
7496 7497 7498
  /* Skip unknown options so that they may be processed later by plugins */
  my_getopt_skip_unknown= TRUE;

Marc Alff's avatar
Marc Alff committed
7499
  if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer),
7500
                                mysqld_get_one_option)))
7501
    return ho_error;
7502 7503 7504 7505

  if (!opt_help)
    delete_dynamic(&all_options);

Marc Alff's avatar
Marc Alff committed
7506 7507 7508
  /* Add back the program name handle_options removes */
  (*argc_ptr)++;
  (*argv_ptr)--;
7509

7510 7511 7512 7513 7514 7515 7516
  /*
    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.
  */

7517 7518
  if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
       opt_log_slow_slave_statements) &&
7519
      !opt_slow_log)
7520
    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");
7521

7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570
  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)
  {
#if defined(__NETWARE__)
    sql_print_error("Can't start server: skip-networking option is currently not supported on NetWare");
    return 1;
#endif
    mysqld_port= 0;
  }
  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;

  if (global_system_variables.option_bits & OPTION_AUTOCOMMIT)
    global_system_variables.option_bits&= ~OPTION_NOT_AUTOCOMMIT;
  else
    global_system_variables.option_bits|= OPTION_NOT_AUTOCOMMIT;

  global_system_variables.sql_mode=
    expand_sql_mode(global_system_variables.sql_mode);
unknown's avatar
unknown committed
7571
#if defined(HAVE_BROKEN_REALPATH)
7572 7573 7574 7575 7576 7577 7578 7579 7580 7581
  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
7582 7583 7584 7585 7586 7587
  if (opt_debugging)
  {
    /* Allow break with SIGINT, no core or stack trace */
    test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
    test_flags&= ~TEST_CORE_ON_SIGNAL;
  }
7588
  /* Set global MyISAM variables from delay_key_write_options */
7589
  fix_delay_key_write(0, 0, OPT_GLOBAL);
7590

7591
#ifndef EMBEDDED_LIBRARY
7592 7593
  if (mysqld_chroot)
    set_root(mysqld_chroot);
7594
#else
7595
  thread_handling = SCHEDULER_NO_THREADS;
7596 7597
  max_allowed_packet= global_system_variables.max_allowed_packet;
  net_buffer_length= global_system_variables.net_buffer_length;
7598
#endif
7599 7600
  if (fix_paths())
    return 1;
unknown's avatar
unknown committed
7601

unknown's avatar
unknown committed
7602 7603 7604 7605
  /*
    Set some global variables from the global_system_variables
    In most cases the global variables will not be used
  */
7606
  my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
unknown's avatar
unknown committed
7607
  my_default_record_cache_size=global_system_variables.read_buff_size;
unknown's avatar
unknown committed
7608

7609 7610
  global_system_variables.long_query_time= (ulonglong)
    (global_system_variables.long_query_time_double * 1e6);
7611

7612 7613
  if (opt_short_log_format)
    opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
7614

7615
  if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
7616
                                  &global_date_format) ||
7617
      init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
7618
                                  &global_time_format) ||
7619
      init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
7620
                                  &global_datetime_format))
7621
    return 1;
7622

unknown's avatar
unknown committed
7623 7624 7625
#ifdef EMBEDDED_LIBRARY
  one_thread_scheduler(&thread_scheduler);
#else
7626
  if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
unknown's avatar
unknown committed
7627
    one_thread_per_connection_scheduler(&thread_scheduler);
7628
  else if (thread_handling == SCHEDULER_NO_THREADS)
unknown's avatar
unknown committed
7629 7630 7631 7632
    one_thread_scheduler(&thread_scheduler);
  else
    pool_of_threads_scheduler(&thread_scheduler);  /* purecov: tested */
#endif
7633 7634 7635 7636 7637

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

7638
  return 0;
unknown's avatar
unknown committed
7639 7640 7641
}


7642 7643 7644 7645 7646 7647 7648 7649 7650 7651
/*
  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)
*/

static void set_server_version(void)
{
  char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
7652
                     MYSQL_SERVER_SUFFIX_STR, NullS);
7653 7654 7655 7656
#ifdef EMBEDDED_LIBRARY
  end= strmov(end, "-embedded");
#endif
#ifndef DBUG_OFF
7657
  if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
7658 7659 7660 7661 7662 7663 7664
    end= strmov(end, "-debug");
#endif
  if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
    strmov(end, "-log");                        // This may slow down system
}


unknown's avatar
unknown committed
7665 7666 7667
static char *get_relative_path(const char *path)
{
  if (test_if_hard_path(path) &&
7668
      is_prefix(path,DEFAULT_MYSQL_HOME) &&
unknown's avatar
unknown committed
7669 7670
      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
  {
unknown's avatar
unknown committed
7671
    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
7672
    while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
unknown's avatar
unknown committed
7673 7674 7675 7676 7677 7678
      path++;
  }
  return (char*) path;
}


unknown's avatar
unknown committed
7679
/**
7680 7681
  Fix filename and replace extension where 'dir' is relative to
  mysql_real_data_home.
unknown's avatar
unknown committed
7682 7683
  @return
    1 if len(path) > FN_REFLEN
7684 7685 7686
*/

bool
7687
fn_format_relative_to_data_home(char * to, const char *name,
7688 7689 7690 7691 7692 7693 7694 7695 7696 7697
				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,
7698
		    MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
7699 7700 7701
}


7702
static int fix_paths(void)
unknown's avatar
unknown committed
7703
{
7704
  char buff[FN_REFLEN],*pos;
7705
  convert_dirname(mysql_home,mysql_home,NullS);
7706
  /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
7707
  my_realpath(mysql_home,mysql_home,MYF(0));
7708 7709 7710 7711 7712 7713 7714
  /* Ensure that mysql_home ends in FN_LIBCHAR */
  pos=strend(mysql_home);
  if (pos[-1] != FN_LIBCHAR)
  {
    pos[0]= FN_LIBCHAR;
    pos[1]= 0;
  }
7715
  convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
7716
  convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
unknown's avatar
unknown committed
7717 7718
  (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);
7719
  (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
unknown's avatar
unknown committed
7720
  (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
7721
                                      get_relative_path(PLUGINDIR), mysql_home);
7722
  opt_plugin_dir_ptr= opt_plugin_dir;
unknown's avatar
unknown committed
7723

7724 7725 7726 7727 7728 7729
  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
7730
  char *sharedir=get_relative_path(SHAREDIR);
unknown's avatar
unknown committed
7731
  if (test_if_hard_path(sharedir))
unknown's avatar
unknown committed
7732
    strmake(buff,sharedir,sizeof(buff)-1);		/* purecov: tested */
unknown's avatar
unknown committed
7733
  else
unknown's avatar
unknown committed
7734
    strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
7735
  convert_dirname(buff,buff,NullS);
7736
  (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
unknown's avatar
unknown committed
7737 7738

  /* If --character-sets-dir isn't given, use shared library dir */
7739 7740 7741
  if (charsets_dir)
    strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir)-1);
  else
unknown's avatar
unknown committed
7742 7743
    strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
	     CHARSET_DIR, NullS);
unknown's avatar
unknown committed
7744
  (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
unknown's avatar
unknown committed
7745
  convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
unknown's avatar
unknown committed
7746
  charsets_dir=mysql_charsets_dir;
unknown's avatar
unknown committed
7747

unknown's avatar
unknown committed
7748
  if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
7749
    return 1;
7750 7751
  if (!opt_mysql_tmpdir)
    opt_mysql_tmpdir= mysql_tmpdir;
unknown's avatar
SCRUM  
unknown committed
7752
#ifdef HAVE_REPLICATION
7753
  if (!slave_load_tmpdir)
7754
    slave_load_tmpdir= mysql_tmpdir;
7755
#endif /* HAVE_REPLICATION */
7756 7757 7758 7759 7760 7761 7762
  /*
    Convert the secure-file-priv option to system format, allowing
    a quick strcmp to check if read or write is in an allowed dir
   */
  if (opt_secure_file_priv)
  {
    convert_dirname(buff, opt_secure_file_priv, NullS);
7763
    x_free(opt_secure_file_priv);
7764 7765
    opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE));
  }
7766
  return 0;
unknown's avatar
unknown committed
7767 7768
}

unknown's avatar
unknown committed
7769 7770
/**
  Check if file system used for databases is case insensitive.
7771

unknown's avatar
unknown committed
7772
  @param dir_name			Directory to test
7773

unknown's avatar
unknown committed
7774
  @retval
7775
    -1  Don't know (Test failed)
unknown's avatar
unknown committed
7776
  @retval
7777
    0   File system is case sensitive
unknown's avatar
unknown committed
7778
  @retval
7779 7780 7781 7782 7783 7784 7785 7786 7787
    1   File system is case insensitive
*/

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;
7788
  DBUG_ENTER("test_if_case_insensitive");
7789 7790 7791 7792 7793

  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
7794 7795 7796
  mysql_file_delete(key_file_casetest, buff2, MYF(0));
  if ((file= mysql_file_create(key_file_casetest,
                               buff, 0666, O_RDWR, MYF(0))) < 0)
7797
  {
7798
    sql_print_warning("Can't create test file %s", buff);
7799
    DBUG_RETURN(-1);
7800
  }
Marc Alff's avatar
Marc Alff committed
7801 7802
  mysql_file_close(file, MYF(0));
  if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
7803
    result= 1;					// Can access file
Marc Alff's avatar
Marc Alff committed
7804
  mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
7805 7806
  DBUG_PRINT("exit", ("result: %d", result));
  DBUG_RETURN(result);
7807 7808 7809
}


7810 7811
#ifndef EMBEDDED_LIBRARY

unknown's avatar
unknown committed
7812 7813 7814
/**
  Create file to store pid number.
*/
7815 7816 7817
static void create_pid_file()
{
  File file;
Marc Alff's avatar
Marc Alff committed
7818 7819
  if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
                               O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
7820
  {
unknown's avatar
unknown committed
7821
    char buff[21], *end;
7822
    end= int10_to_str((long) getpid(), buff, 10);
unknown's avatar
unknown committed
7823
    *end++= '\n';
Marc Alff's avatar
Marc Alff committed
7824 7825
    if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
                          MYF(MY_WME | MY_NABP)))
7826
    {
Marc Alff's avatar
Marc Alff committed
7827
      mysql_file_close(file, MYF(0));
7828 7829
      return;
    }
Marc Alff's avatar
Marc Alff committed
7830
    mysql_file_close(file, MYF(0));
7831
  }
7832
  sql_perror("Can't start server: can't create PID file");
unknown's avatar
foo1  
unknown committed
7833
  exit(1);
7834
}
7835
#endif /* EMBEDDED_LIBRARY */
7836

unknown's avatar
unknown committed
7837
/** Clear most status variables. */
7838 7839
void refresh_status(THD *thd)
{
Marc Alff's avatar
Marc Alff committed
7840
  mysql_mutex_lock(&LOCK_status);
7841

unknown's avatar
unknown committed
7842
  /* Add thread's status variabes to global status */
7843
  add_to_status(&global_status_var, &thd->status_var);
unknown's avatar
unknown committed
7844 7845

  /* Reset thread's status variables */
7846
  bzero((uchar*) &thd->status_var, sizeof(thd->status_var));
7847

unknown's avatar
unknown committed
7848
  /* Reset some global variables */
unknown's avatar
WL#2936  
unknown committed
7849
  reset_status_vars();
unknown's avatar
unknown committed
7850

7851 7852
  /* Reset the counters of all key caches (default and named). */
  process_key_caches(reset_key_cache_counters);
7853
  flush_status_time= time((time_t*) 0);
Marc Alff's avatar
Marc Alff committed
7854
  mysql_mutex_unlock(&LOCK_status);
7855 7856 7857 7858 7859 7860 7861

  /*
    Set max_used_connections to the number of currently open
    connections.  Lock LOCK_thread_count out of LOCK_status to avoid
    deadlocks.  Status reset becomes not atomic, but status data is
    not exact anyway.
  */
Marc Alff's avatar
Marc Alff committed
7862
  mysql_mutex_lock(&LOCK_thread_count);
7863
  max_used_connections= thread_count-delayed_insert_threads;
Marc Alff's avatar
Marc Alff committed
7864
  mysql_mutex_unlock(&LOCK_thread_count);
7865 7866 7867
}


7868
/*****************************************************************************
unknown's avatar
WL#2936  
unknown committed
7869 7870
  Instantiate variables for missing storage engines
  This section should go away soon
7871 7872
*****************************************************************************/

unknown's avatar
unknown committed
7873
/*****************************************************************************
7874
  Instantiate templates
unknown's avatar
unknown committed
7875 7876
*****************************************************************************/

7877
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
unknown's avatar
unknown committed
7878 7879 7880 7881
/* Used templates */
template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
7882
template class I_List<i_string_pair>;
7883 7884
template class I_List<Statement>;
template class I_List_iterator<Statement>;
unknown's avatar
unknown committed
7885
#endif
Marc Alff's avatar
Marc Alff committed
7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908

#ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP
PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool;
#endif /* HAVE_MMAP */

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

PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
  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_read_lock, key_LOCK_global_system_variables,
  key_LOCK_lock_db, key_LOCK_manager, key_LOCK_mapped_file,
  key_LOCK_mysql_create_db, key_LOCK_open, key_LOCK_prepared_stmt_count,
  key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status,
  key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
  key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
  key_master_info_data_lock, key_master_info_run_lock,
  key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
  key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
7909
  key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages,
Marc Alff's avatar
Marc Alff committed
7910
  key_LOG_INFO_lock, key_LOCK_thread_count;
Marc Alff's avatar
Marc Alff committed
7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960

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},
#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},
  { &key_BINLOG_LOCK_prep_xids, "MYSQL_BIN_LOG::LOCK_prep_xids", 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_read_lock, "LOCK_global_read_lock", PSI_FLAG_GLOBAL},
  { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
  { &key_LOCK_lock_db, "LOCK_lock_db", PSI_FLAG_GLOBAL},
  { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
  { &key_LOCK_mapped_file, "LOCK_mapped_file", PSI_FLAG_GLOBAL},
  { &key_LOCK_mysql_create_db, "LOCK_mysql_create_db", PSI_FLAG_GLOBAL},
  { &key_LOCK_open, "LOCK_open", 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_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL},
  { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
  { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
  { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
  { &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},
  { &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},
  { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
7961
  { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
Marc Alff's avatar
Marc Alff committed
7962
  { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
Marc Alff's avatar
Marc Alff committed
7963 7964
  { &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
  { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}
Marc Alff's avatar
Marc Alff committed
7965 7966 7967 7968 7969 7970 7971 7972
};

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[]=
{
7973 7974 7975
#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
  { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
#endif
Marc Alff's avatar
Marc Alff committed
7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995
  { &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
PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
#endif /* HAVE_MMAP */

PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond,
  key_COND_cache_status_changed, key_COND_global_read_lock, key_COND_manager,
  key_COND_refresh, 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,
  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,
Marc Alff's avatar
Marc Alff committed
7996 7997
  key_TABLE_SHARE_cond, key_user_level_lock_cond,
  key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
Marc Alff's avatar
Marc Alff committed
7998 7999 8000

static PSI_cond_info all_server_conds[]=
{
Marc Alff's avatar
Marc Alff committed
8001 8002 8003
#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 */
Marc Alff's avatar
Marc Alff committed
8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027
#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},
#endif /* HAVE_MMAP */
  { &key_BINLOG_COND_prep_xids, "MYSQL_BIN_LOG::COND_prep_xids", 0},
  { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
  { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
  { &key_COND_global_read_lock, "COND_global_read_lock", PSI_FLAG_GLOBAL},
  { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
  { &key_COND_refresh, "COND_refresh", PSI_FLAG_GLOBAL},
  { &key_COND_rpl_status, "COND_rpl_status", 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},
  { &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},
  { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
Marc Alff's avatar
Marc Alff committed
8028 8029 8030 8031
  { &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},
  { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL}
Marc Alff's avatar
Marc Alff committed
8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137
};

PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
  key_thread_handle_manager, key_thread_main,
  key_thread_one_connection, key_thread_signal_hand;

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},
  { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL}
};

#ifdef HAVE_MMAP
PSI_file_key key_file_map;
#endif /* HAVE_MMAP */

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_MYSQL_LOG, 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;

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_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_MYSQL_LOG, "MYSQL_LOG", 0},
  { &key_file_partition, "partition", 0},
  { &key_file_pid, "pid", 0},
  { &key_file_relay_log_info, "relay_log_info", 0},
  { &key_file_send_file, "send_file", 0},
  { &key_file_tclog, "tclog", 0},
  { &key_file_trg, "trigger_name", 0},
  { &key_file_trn, "trigger", 0},
  { &key_file_init, "init", 0}
};

/**
  Initialise all the performance schema instrumentation points
  used by the server.
*/
void init_server_psi_keys(void)
{
  const char* category= "sql";
  int count;

  if (PSI_server == NULL)
    return;

  count= array_elements(all_server_mutexes);
  PSI_server->register_mutex(category, all_server_mutexes, count);

  count= array_elements(all_server_rwlocks);
  PSI_server->register_rwlock(category, all_server_rwlocks, count);

  count= array_elements(all_server_conds);
  PSI_server->register_cond(category, all_server_conds, count);

  count= array_elements(all_server_threads);
  PSI_server->register_thread(category, all_server_threads, count);

  count= array_elements(all_server_files);
  PSI_server->register_file(category, all_server_files, count);
}

#endif /* HAVE_PSI_INTERFACE */