~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/drizzled.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; version 2 of the License.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
#include <drizzled/configmake.h>
 
22
#include <drizzled/atomics.h>
 
23
 
 
24
#include <netdb.h>
 
25
#include <sys/types.h>
 
26
#include <netinet/tcp.h>
 
27
#include <netinet/in.h>
 
28
#include <signal.h>
 
29
#include <limits.h>
 
30
 
 
31
#include "drizzled/internal/my_sys.h"
 
32
#include "drizzled/internal/my_bit.h"
 
33
#include <drizzled/my_hash.h>
 
34
#include <drizzled/stacktrace.h>
 
35
#include <drizzled/error.h>
 
36
#include <drizzled/errmsg_print.h>
 
37
#include <drizzled/tztime.h>
 
38
#include <drizzled/sql_base.h>
 
39
#include <drizzled/show.h>
 
40
#include <drizzled/sql_parse.h>
 
41
#include <drizzled/item/cmpfunc.h>
 
42
#include <drizzled/session.h>
 
43
#include <drizzled/item/create.h>
 
44
#include <drizzled/unireg.h>
 
45
#include "drizzled/temporal_format.h" /* For init_temporal_formats() */
 
46
#include "drizzled/plugin/listen.h"
 
47
#include "drizzled/plugin/error_message.h"
 
48
#include "drizzled/plugin/client.h"
 
49
#include "drizzled/plugin/scheduler.h"
 
50
#include "drizzled/plugin/xa_resource_manager.h"
 
51
#include "drizzled/plugin/monitored_in_transaction.h"
 
52
#include "drizzled/probes.h"
 
53
#include "drizzled/session_list.h"
 
54
#include "drizzled/charset.h"
 
55
#include "plugin/myisam/myisam.h"
 
56
 
 
57
#include <google/protobuf/stubs/common.h>
 
58
 
 
59
#if TIME_WITH_SYS_TIME
 
60
# include <sys/time.h>
 
61
# include <time.h>
 
62
#else
 
63
# if HAVE_SYS_TIME_H
 
64
#  include <sys/time.h>
 
65
# else
 
66
#  include <time.h>
 
67
# endif
 
68
#endif
 
69
 
 
70
#ifdef HAVE_SYS_PRCTL_H
 
71
#include <sys/prctl.h>
 
72
#endif
 
73
#include <sys/socket.h>
 
74
 
 
75
#include <locale.h>
 
76
 
 
77
 
 
78
#include <errno.h>
 
79
#include <sys/stat.h>
 
80
#include "drizzled/my_getopt.h"
 
81
#ifdef HAVE_SYSENT_H
 
82
#include <sysent.h>
 
83
#endif
 
84
#include <pwd.h>                                // For getpwent
 
85
#include <grp.h>
 
86
 
 
87
#include <sys/resource.h>
 
88
 
 
89
#ifdef HAVE_SELECT_H
 
90
#  include <select.h>
 
91
#endif
 
92
 
 
93
#ifdef HAVE_SYS_SELECT_H
 
94
#include <sys/select.h>
 
95
#endif
 
96
 
 
97
#include <sys/utsname.h>
 
98
 
 
99
#ifdef HAVE_SYS_MMAN_H
 
100
#include <sys/mman.h>
 
101
#endif
 
102
 
 
103
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
 
104
#include <ieeefp.h>
 
105
#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
 
106
 
 
107
#ifdef HAVE_FPU_CONTROL_H
 
108
#include <fpu_control.h>
 
109
#endif
 
110
 
 
111
#ifdef HAVE_SYS_FPU_H
 
112
/* for IRIX to use set_fpc_csr() */
 
113
#include <sys/fpu.h>
 
114
#endif
 
115
 
 
116
#include "drizzled/internal/my_pthread.h"                       // For thr_setconcurency()
 
117
 
 
118
#include <drizzled/gettext.h>
 
119
 
 
120
 
 
121
#ifdef HAVE_purify
 
122
#define IF_PURIFY(A,B) (A)
 
123
#else
 
124
#define IF_PURIFY(A,B) (B)
 
125
#endif
 
126
 
 
127
#define MAX_MEM_TABLE_SIZE SIZE_MAX
 
128
 
 
129
using namespace std;
 
130
 
 
131
namespace drizzled
 
132
{
 
133
 
 
134
#define mysqld_charset &my_charset_utf8_general_ci
 
135
inline void setup_fpu()
 
136
{
 
137
#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
 
138
  /*
 
139
     We can't handle floating point exceptions with threads, so disable
 
140
     this on freebsd.
 
141
     Don't fall for overflow, underflow,divide-by-zero or loss of precision
 
142
  */
 
143
#if defined(__i386__)
 
144
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
 
145
              FP_X_IMP));
 
146
#else
 
147
  fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
 
148
              FP_X_IMP));
 
149
#endif /* __i386__ */
 
150
#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
 
151
 
 
152
  /*
 
153
    x86 (32-bit) requires FPU precision to be explicitly set to 64 bit for
 
154
    portable results of floating point operations
 
155
  */
 
156
#if defined(__i386__) && defined(HAVE_FPU_CONTROL_H) && defined(_FPU_DOUBLE)
 
157
  fpu_control_t cw;
 
158
  _FPU_GETCW(cw);
 
159
  cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
 
160
  _FPU_SETCW(cw);
 
161
#endif /* __i386__ && HAVE_FPU_CONTROL_H && _FPU_DOUBLE */
 
162
}
 
163
 
 
164
#ifdef SOLARIS
 
165
extern "C" int gethostname(char *name, int namelen);
 
166
#endif
 
167
 
 
168
/* Constants */
 
169
static const char *tc_heuristic_recover_names[]=
 
170
{
 
171
  "COMMIT", "ROLLBACK", NULL
 
172
};
 
173
static TYPELIB tc_heuristic_recover_typelib=
 
174
{
 
175
  array_elements(tc_heuristic_recover_names)-1,"",
 
176
  tc_heuristic_recover_names, NULL
 
177
};
 
178
 
 
179
const char *first_keyword= "first";
 
180
const char * const DRIZZLE_CONFIG_NAME= "drizzled";
 
181
#define GET_HA_ROWS GET_ULL
 
182
 
 
183
const char *tx_isolation_names[] =
 
184
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
 
185
  NULL};
 
186
 
 
187
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
 
188
                               tx_isolation_names, NULL};
 
189
 
 
190
/*
 
191
  Used with --help for detailed option
 
192
*/
 
193
static bool opt_help= false;
 
194
static bool opt_help_extended= false;
 
195
 
 
196
arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
 
197
{{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
 
198
 {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
 
199
 {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
 
200
 {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
 
201
 {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
 
202
 
 
203
/* static variables */
 
204
 
 
205
static bool volatile select_thread_in_use;
 
206
static bool volatile ready_to_exit;
 
207
static bool opt_debugging= 0;
 
208
static uint32_t wake_thread;
 
209
static uint32_t killed_threads;
 
210
static char *drizzled_user, *drizzled_chroot;
 
211
static char *language_ptr;
 
212
static const char *default_character_set_name;
 
213
static const char *character_set_filesystem_name;
 
214
static char *lc_time_names_name;
 
215
static char *default_collation_name;
 
216
static char *default_storage_engine_str;
 
217
static const char *compiled_default_collation_name= "utf8_general_ci";
 
218
 
 
219
/* Global variables */
 
220
 
 
221
bool volatile abort_loop;
 
222
bool volatile shutdown_in_progress;
 
223
uint32_t max_used_connections;
 
224
const string opt_scheduler_default("multi_thread");
 
225
char *opt_scheduler= NULL;
 
226
 
 
227
size_t my_thread_stack_size= 65536;
 
228
 
 
229
/*
 
230
  Legacy global plugin::StorageEngine. These will be removed (please do not add more).
 
231
*/
 
232
plugin::StorageEngine *heap_engine;
 
233
plugin::StorageEngine *myisam_engine;
 
234
 
 
235
char* opt_secure_file_priv= 0;
 
236
 
 
237
static bool calling_initgroups= false; /**< Used in SIGSEGV handler. */
 
238
 
 
239
uint32_t drizzled_bind_timeout;
 
240
std::bitset<12> test_flags;
 
241
uint32_t dropping_tables, ha_open_options;
 
242
uint32_t tc_heuristic_recover= 0;
 
243
uint64_t session_startup_options;
 
244
uint32_t back_log;
 
245
uint32_t server_id;
 
246
uint64_t table_cache_size;
 
247
size_t table_def_size;
 
248
uint64_t aborted_threads;
 
249
uint64_t aborted_connects;
 
250
uint64_t max_connect_errors;
 
251
uint32_t global_thread_id= 1UL;
 
252
pid_t current_pid;
 
253
 
 
254
extern const double log_10[309];
 
255
 
 
256
const double log_10[] = {
 
257
  1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
 
258
  1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
 
259
  1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
 
260
  1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
 
261
  1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
 
262
  1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
 
263
  1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
 
264
  1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
 
265
  1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
 
266
  1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
 
267
  1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
 
268
  1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
 
269
  1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
 
270
  1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
 
271
  1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
 
272
  1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
 
273
  1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
 
274
  1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
 
275
  1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
 
276
  1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
 
277
  1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
 
278
  1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
 
279
  1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
 
280
  1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
 
281
  1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
 
282
  1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
 
283
  1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
 
284
  1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
 
285
  1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
 
286
  1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
 
287
  1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
 
288
};
 
289
 
 
290
time_t server_start_time;
 
291
time_t flush_status_time;
 
292
 
 
293
char drizzle_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
 
294
char *default_tz_name;
 
295
char glob_hostname[FN_REFLEN];
 
296
char drizzle_real_data_home[FN_REFLEN],
 
297
     language[FN_REFLEN], 
 
298
     *opt_tc_log_file;
 
299
char drizzle_unpacked_real_data_home[FN_REFLEN];
 
300
const key_map key_map_empty(0);
 
301
key_map key_map_full(0);                        // Will be initialized later
 
302
 
 
303
uint32_t drizzle_data_home_len;
 
304
char drizzle_data_home_buff[2], *drizzle_data_home=drizzle_real_data_home;
 
305
char *drizzle_tmpdir= NULL;
 
306
char *opt_drizzle_tmpdir= NULL;
 
307
 
 
308
/** name of reference on left espression in rewritten IN subquery */
 
309
const char *in_left_expr_name= "<left expr>";
 
310
/** name of additional condition */
 
311
const char *in_additional_cond= "<IN COND>";
 
312
const char *in_having_cond= "<IN HAVING>";
 
313
 
 
314
my_decimal decimal_zero;
 
315
/* classes for comparation parsing/processing */
 
316
 
 
317
FILE *stderror_file=0;
 
318
 
 
319
struct system_variables global_system_variables;
 
320
struct system_variables max_system_variables;
 
321
struct system_status_var global_status_var;
 
322
 
 
323
const CHARSET_INFO *system_charset_info, *files_charset_info ;
 
324
const CHARSET_INFO *table_alias_charset;
 
325
const CHARSET_INFO *character_set_filesystem;
 
326
 
 
327
MY_LOCALE *my_default_lc_time_names;
 
328
 
 
329
SHOW_COMP_OPTION have_symlink;
 
330
 
 
331
/* Thread specific variables */
 
332
 
 
333
pthread_key_t THR_Mem_root;
 
334
pthread_key_t THR_Session;
 
335
pthread_mutex_t LOCK_create_db;
 
336
pthread_mutex_t LOCK_open;
 
337
pthread_mutex_t LOCK_thread_count;
 
338
pthread_mutex_t LOCK_status;
 
339
pthread_mutex_t LOCK_global_read_lock;
 
340
pthread_mutex_t LOCK_global_system_variables;
 
341
 
 
342
pthread_rwlock_t        LOCK_system_variables_hash;
 
343
pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock;
 
344
pthread_t signal_thread;
 
345
pthread_cond_t  COND_server_end;
 
346
 
 
347
/* Static variables */
 
348
 
 
349
static bool segfaulted;
 
350
#ifdef HAVE_STACK_TRACE_ON_SEGV
 
351
static bool opt_do_pstack;
 
352
#endif /* HAVE_STACK_TRACE_ON_SEGV */
 
353
int cleanup_done;
 
354
static char *drizzle_home_ptr, *pidfile_name_ptr;
 
355
static int defaults_argc;
 
356
static char **defaults_argv;
 
357
 
 
358
struct passwd *user_info;
 
359
static pthread_t select_thread;
 
360
static uint32_t thr_kill_signal;
 
361
 
 
362
/**
 
363
  Number of currently active user connections. The variable is protected by
 
364
  LOCK_thread_count.
 
365
*/
 
366
atomic<uint32_t> connection_count;
 
367
 
 
368
/** 
 
369
  Refresh value. We use to test this to find out if a refresh even has happened recently.
 
370
*/
 
371
uint64_t refresh_version;  /* Increments on each reload */
 
372
 
 
373
/* Function declarations */
 
374
bool drizzle_rm_tmp_tables();
 
375
 
 
376
extern "C" pthread_handler_t signal_hand(void *arg);
 
377
static void drizzle_init_variables(void);
 
378
static void get_options(int *argc,char **argv);
 
379
bool drizzled_get_one_option(int, const struct my_option *, char *);
 
380
static int init_thread_environment();
 
381
static const char *get_relative_path(const char *path);
 
382
static void fix_paths(string &progname);
 
383
extern "C" pthread_handler_t handle_slave(void *arg);
 
384
static void clean_up(bool print_message);
 
385
 
 
386
static void usage(void);
 
387
static void clean_up_mutexes(void);
 
388
void close_connections(void);
 
389
 
 
390
/****************************************************************************
 
391
** Code to end drizzled
 
392
****************************************************************************/
 
393
 
 
394
void close_connections(void)
 
395
{
 
396
  /* Abort listening to new connections */
 
397
  plugin::Listen::shutdown();
 
398
 
 
399
  /* kill connection thread */
 
400
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
401
 
 
402
  while (select_thread_in_use)
 
403
  {
 
404
    struct timespec abstime;
 
405
    int error;
 
406
 
 
407
    set_timespec(abstime, 2);
 
408
    for (uint32_t tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
 
409
    {
 
410
      error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count, &abstime);
 
411
      if (error != EINTR)
 
412
        break;
 
413
    }
 
414
  }
 
415
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
416
 
 
417
 
 
418
  /*
 
419
    First signal all threads that it's time to die
 
420
    This will give the threads some time to gracefully abort their
 
421
    statements and inform their clients that the server is about to die.
 
422
  */
 
423
 
 
424
  Session *tmp;
 
425
 
 
426
  (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
427
 
 
428
  for( SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
429
  {
 
430
    tmp= *it;
 
431
    tmp->killed= Session::KILL_CONNECTION;
 
432
    tmp->scheduler->killSession(tmp);
 
433
    DRIZZLE_CONNECTION_DONE(tmp->thread_id);
 
434
    if (tmp->mysys_var)
 
435
    {
 
436
      tmp->mysys_var->abort=1;
 
437
      pthread_mutex_lock(&tmp->mysys_var->mutex);
 
438
      if (tmp->mysys_var->current_cond)
 
439
      {
 
440
        pthread_mutex_lock(tmp->mysys_var->current_mutex);
 
441
        pthread_cond_broadcast(tmp->mysys_var->current_cond);
 
442
        pthread_mutex_unlock(tmp->mysys_var->current_mutex);
 
443
      }
 
444
      pthread_mutex_unlock(&tmp->mysys_var->mutex);
 
445
    }
 
446
  }
 
447
  (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
 
448
 
 
449
  if (connection_count)
 
450
    sleep(2);                                   // Give threads time to die
 
451
 
 
452
  /*
 
453
    Force remaining threads to die by closing the connection to the client
 
454
    This will ensure that threads that are waiting for a command from the
 
455
    client on a blocking read call are aborted.
 
456
  */
 
457
  for (;;)
 
458
  {
 
459
    (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
460
    if (getSessionList().empty())
 
461
    {
 
462
      (void) pthread_mutex_unlock(&LOCK_thread_count);
 
463
      break;
 
464
    }
 
465
    tmp= getSessionList().front();
 
466
    /* Close before unlock, avoiding crash. See LP bug#436685 */
 
467
    tmp->client->close();
 
468
    (void) pthread_mutex_unlock(&LOCK_thread_count);
 
469
  }
 
470
}
 
471
 
 
472
extern "C" void print_signal_warning(int sig);
 
473
 
 
474
extern "C" void print_signal_warning(int sig)
 
475
{
 
476
  if (global_system_variables.log_warnings)
 
477
    errmsg_printf(ERRMSG_LVL_WARN, _("Got signal %d from thread %"PRIu64),
 
478
                  sig, global_thread_id);
 
479
#ifndef HAVE_BSD_SIGNALS
 
480
  my_sigset(sig,print_signal_warning);          /* int. thread system calls */
 
481
#endif
 
482
  if (sig == SIGALRM)
 
483
    alarm(2);                                   /* reschedule alarm */
 
484
}
 
485
 
 
486
/**
 
487
  cleanup all memory and end program nicely.
 
488
 
 
489
    If SIGNALS_DONT_BREAK_READ is defined, this function is called
 
490
    by the main thread. To get Drizzle to shut down nicely in this case
 
491
    (Mac OS X) we have to call exit() instead if pthread_exit().
 
492
 
 
493
  @note
 
494
    This function never returns.
 
495
*/
 
496
void unireg_end(void)
 
497
{
 
498
  clean_up(1);
 
499
  internal::my_thread_end();
 
500
#if defined(SIGNALS_DONT_BREAK_READ)
 
501
  exit(0);
 
502
#else
 
503
  pthread_exit(0);                              // Exit is in main thread
 
504
#endif
 
505
}
 
506
 
 
507
 
 
508
void unireg_abort(int exit_code)
 
509
{
 
510
 
 
511
  if (exit_code)
 
512
    errmsg_printf(ERRMSG_LVL_ERROR, _("Aborting\n"));
 
513
  else if (opt_help || opt_help_extended)
 
514
    usage();
 
515
  clean_up(!opt_help && (exit_code));
 
516
  clean_up_mutexes();
 
517
  internal::my_end();
 
518
  exit(exit_code);
 
519
}
 
520
 
 
521
 
 
522
static void clean_up(bool print_message)
 
523
{
 
524
  if (cleanup_done++)
 
525
    return;
 
526
 
 
527
  table_cache_free();
 
528
  TableShare::cacheStop();
 
529
  set_var_free();
 
530
  free_charsets();
 
531
  ha_end();
 
532
  plugin::Registry &plugins= plugin::Registry::singleton();
 
533
  plugin_shutdown(plugins);
 
534
  xid_cache_free();
 
535
  free_status_vars();
 
536
  if (defaults_argv)
 
537
    internal::free_defaults(defaults_argv);
 
538
  free(drizzle_tmpdir);
 
539
  if (opt_secure_file_priv)
 
540
    free(opt_secure_file_priv);
 
541
 
 
542
  deinit_temporal_formats();
 
543
 
 
544
#if GOOGLE_PROTOBUF_VERSION >= 2001000
 
545
  google::protobuf::ShutdownProtobufLibrary();
 
546
#endif
 
547
 
 
548
  (void) unlink(pidfile_name);  // This may not always exist
 
549
 
 
550
  if (print_message && server_start_time)
 
551
    errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_SHUTDOWN_COMPLETE)),internal::my_progname);
 
552
  /* Returns NULL on globerrs, we don't want to try to free that */
 
553
  //void *freeme=
 
554
  (void *)my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
 
555
  // TODO!!!! EPIC FAIL!!!! This sefaults if uncommented.
 
556
/*  if (freeme != NULL)
 
557
    free(freeme);  */
 
558
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
559
  ready_to_exit=1;
 
560
  /* do the broadcast inside the lock to ensure that my_end() is not called */
 
561
  (void) pthread_cond_broadcast(&COND_server_end);
 
562
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
563
 
 
564
  /*
 
565
    The following lines may never be executed as the main thread may have
 
566
    killed us
 
567
  */
 
568
} /* clean_up */
 
569
 
 
570
 
 
571
static void clean_up_mutexes()
 
572
{
 
573
  (void) pthread_mutex_destroy(&LOCK_create_db);
 
574
  (void) pthread_mutex_destroy(&LOCK_open);
 
575
  (void) pthread_mutex_destroy(&LOCK_thread_count);
 
576
  (void) pthread_mutex_destroy(&LOCK_status);
 
577
  (void) pthread_mutex_destroy(&LOCK_global_system_variables);
 
578
  (void) pthread_rwlock_destroy(&LOCK_system_variables_hash);
 
579
  (void) pthread_mutex_destroy(&LOCK_global_read_lock);
 
580
  (void) pthread_cond_destroy(&COND_thread_count);
 
581
  (void) pthread_cond_destroy(&COND_server_end);
 
582
  (void) pthread_cond_destroy(&COND_refresh);
 
583
  (void) pthread_cond_destroy(&COND_global_read_lock);
 
584
}
 
585
 
 
586
 
 
587
/* Change to run as another user if started with --user */
 
588
 
 
589
static struct passwd *check_user(const char *user)
 
590
{
 
591
  struct passwd *tmp_user_info;
 
592
  uid_t user_id= geteuid();
 
593
 
 
594
  // Don't bother if we aren't superuser
 
595
  if (user_id)
 
596
  {
 
597
    if (user)
 
598
    {
 
599
      /* Don't give a warning, if real user is same as given with --user */
 
600
      tmp_user_info= getpwnam(user);
 
601
      if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
 
602
          global_system_variables.log_warnings)
 
603
            errmsg_printf(ERRMSG_LVL_WARN, _("One can only use the --user switch "
 
604
                            "if running as root\n"));
 
605
    }
 
606
    return NULL;
 
607
  }
 
608
  if (!user)
 
609
  {
 
610
      errmsg_printf(ERRMSG_LVL_ERROR, _("Fatal error: Please read \"Security\" section of "
 
611
                      "the manual to find out how to run drizzled as root!\n"));
 
612
    unireg_abort(1);
 
613
  }
 
614
  if (!strcmp(user,"root"))
 
615
    return NULL;                        // Avoid problem with dynamic libraries
 
616
 
 
617
  if (!(tmp_user_info= getpwnam(user)))
 
618
  {
 
619
    // Allow a numeric uid to be used
 
620
    const char *pos;
 
621
    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
 
622
    if (*pos)                                   // Not numeric id
 
623
      goto err;
 
624
    if (!(tmp_user_info= getpwuid(atoi(user))))
 
625
      goto err;
 
626
  }
 
627
  return tmp_user_info;
 
628
 
 
629
err:
 
630
  errmsg_printf(ERRMSG_LVL_ERROR, _("Fatal error: Can't change to run as user '%s' ;  "
 
631
                    "Please check that the user exists!\n"),user);
 
632
  unireg_abort(1);
 
633
 
 
634
#ifdef PR_SET_DUMPABLE
 
635
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
 
636
  {
 
637
    /* inform kernel that process is dumpable */
 
638
    (void) prctl(PR_SET_DUMPABLE, 1);
 
639
  }
 
640
#endif
 
641
 
 
642
/* Sun Studio 5.10 doesn't like this line.  5.9 requires it */
 
643
#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
 
644
  return NULL;
 
645
#endif
 
646
 
 
647
}
 
648
 
 
649
static void set_user(const char *user, struct passwd *user_info_arg)
 
650
{
 
651
  assert(user_info_arg != 0);
 
652
  /*
 
653
    We can get a SIGSEGV when calling initgroups() on some systems when NSS
 
654
    is configured to use LDAP and the server is statically linked.  We set
 
655
    calling_initgroups as a flag to the SIGSEGV handler that is then used to
 
656
    output a specific message to help the user resolve this problem.
 
657
  */
 
658
  calling_initgroups= true;
 
659
  initgroups((char*) user, user_info_arg->pw_gid);
 
660
  calling_initgroups= false;
 
661
  if (setgid(user_info_arg->pw_gid) == -1)
 
662
  {
 
663
    sql_perror("setgid");
 
664
    unireg_abort(1);
 
665
  }
 
666
  if (setuid(user_info_arg->pw_uid) == -1)
 
667
  {
 
668
    sql_perror("setuid");
 
669
    unireg_abort(1);
 
670
  }
 
671
}
 
672
 
 
673
 
 
674
/** Change root user if started with @c --chroot . */
 
675
static void set_root(const char *path)
 
676
{
 
677
  if ((chroot(path) == -1) || !chdir("/"))
 
678
  {
 
679
    sql_perror("chroot");
 
680
    unireg_abort(1);
 
681
  }
 
682
}
 
683
 
 
684
extern "C" void end_thread_signal(int );
 
685
 
 
686
/** Called when a thread is aborted. */
 
687
extern "C" void end_thread_signal(int )
 
688
{
 
689
  Session *session=current_session;
 
690
  if (session)
 
691
  {
 
692
    statistic_increment(killed_threads, &LOCK_status);
 
693
    session->scheduler->killSessionNow(session);
 
694
    DRIZZLE_CONNECTION_DONE(session->thread_id);
 
695
  }
 
696
  return;
 
697
}
 
698
 
 
699
 
 
700
/*
 
701
  Unlink session from global list of available connections and free session
 
702
 
 
703
  SYNOPSIS
 
704
    Session::unlink()
 
705
    session              Thread handler
 
706
 
 
707
  NOTES
 
708
    LOCK_thread_count is locked and left locked
 
709
*/
 
710
 
 
711
void Session::unlink(Session *session)
 
712
{
 
713
  connection_count.decrement();
 
714
 
 
715
  session->cleanup();
 
716
 
 
717
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
718
  pthread_mutex_lock(&session->LOCK_delete);
 
719
 
 
720
  getSessionList().erase(remove(getSessionList().begin(),
 
721
                         getSessionList().end(),
 
722
                         session));
 
723
 
 
724
  delete session;
 
725
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
726
 
 
727
  return;
 
728
}
 
729
 
 
730
 
 
731
#ifdef THREAD_SPECIFIC_SIGPIPE
 
732
/**
 
733
 
 
734
  @todo
 
735
    One should have to fix that thr_alarm know about this thread too.
 
736
*/
 
737
extern "C" void abort_thread(int )
 
738
{
 
739
  Session *session=current_session;
 
740
  if (session)
 
741
    session->killed= Session::KILL_CONNECTION;
 
742
  return;;
 
743
}
 
744
#endif
 
745
 
 
746
#if defined(BACKTRACE_DEMANGLE)
 
747
#include <cxxabi.h>
 
748
extern "C" char *my_demangle(const char *mangled_name, int *status)
 
749
{
 
750
  return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
 
751
}
 
752
#endif
 
753
 
 
754
extern "C" void handle_segfault(int sig);
 
755
 
 
756
extern "C" void handle_segfault(int sig)
 
757
{
 
758
  time_t curr_time;
 
759
  struct tm tm;
 
760
 
 
761
  /*
 
762
    Strictly speaking, one needs a mutex here
 
763
    but since we have got SIGSEGV already, things are a mess
 
764
    so not having the mutex is not as bad as possibly using a buggy
 
765
    mutex - so we keep things simple
 
766
  */
 
767
  if (segfaulted)
 
768
  {
 
769
    fprintf(stderr, _("Fatal signal %d while backtracing\n"), sig);
 
770
    exit(1);
 
771
  }
 
772
 
 
773
  segfaulted = 1;
 
774
 
 
775
  curr_time= time(NULL);
 
776
  if(curr_time == (time_t)-1)
 
777
  {
 
778
    fprintf(stderr, "Fetal: time() call failed\n");
 
779
    exit(1);
 
780
  }
 
781
 
 
782
  localtime_r(&curr_time, &tm);
 
783
  
 
784
  fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d - drizzled got signal %d;\n"
 
785
          "This could be because you hit a bug. It is also possible that "
 
786
          "this binary\n or one of the libraries it was linked against is "
 
787
          "corrupt, improperly built,\n or misconfigured. This error can "
 
788
          "also be caused by malfunctioning hardware.\n",
 
789
          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
 
790
          tm.tm_hour, tm.tm_min, tm.tm_sec,
 
791
          sig);
 
792
  fprintf(stderr, _("We will try our best to scrape up some info that "
 
793
                    "will hopefully help diagnose\n"
 
794
                    "the problem, but since we have already crashed, "
 
795
                    "something is definitely wrong\nand this may fail.\n\n"));
 
796
  fprintf(stderr, "key_buffer_size=%u\n",
 
797
          (uint32_t) dflt_key_cache->key_cache_mem_size);
 
798
  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
 
799
  fprintf(stderr, "max_used_connections=%u\n", max_used_connections);
 
800
  fprintf(stderr, "connection_count=%u\n", uint32_t(connection_count));
 
801
  fprintf(stderr, _("It is possible that drizzled could use up to \n"
 
802
                    "key_buffer_size + (read_buffer_size + "
 
803
                    "sort_buffer_size)*thread_count\n"
 
804
                    "bytes of memory\n"
 
805
                    "Hope that's ok; if not, decrease some variables in the "
 
806
                    "equation.\n\n"));
 
807
 
 
808
#ifdef HAVE_STACKTRACE
 
809
  Session *session= current_session;
 
810
 
 
811
  if (! (test_flags.test(TEST_NO_STACKTRACE)))
 
812
  {
 
813
    fprintf(stderr,"session: 0x%lx\n",(long) session);
 
814
    fprintf(stderr,_("Attempting backtrace. You can use the following "
 
815
                     "information to find out\n"
 
816
                     "where drizzled died. If you see no messages after this, "
 
817
                     "something went\n"
 
818
                     "terribly wrong...\n"));
 
819
    print_stacktrace(session ? (unsigned char*) session->thread_stack : (unsigned char*) 0,
 
820
                     my_thread_stack_size);
 
821
  }
 
822
  if (session)
 
823
  {
 
824
    const char *kreason= "UNKNOWN";
 
825
    switch (session->killed) {
 
826
    case Session::NOT_KILLED:
 
827
      kreason= "NOT_KILLED";
 
828
      break;
 
829
    case Session::KILL_BAD_DATA:
 
830
      kreason= "KILL_BAD_DATA";
 
831
      break;
 
832
    case Session::KILL_CONNECTION:
 
833
      kreason= "KILL_CONNECTION";
 
834
      break;
 
835
    case Session::KILL_QUERY:
 
836
      kreason= "KILL_QUERY";
 
837
      break;
 
838
    case Session::KILLED_NO_VALUE:
 
839
      kreason= "KILLED_NO_VALUE";
 
840
      break;
 
841
    }
 
842
    fprintf(stderr, _("Trying to get some variables.\n"
 
843
                      "Some pointers may be invalid and cause the "
 
844
                      "dump to abort...\n"));
 
845
    safe_print_str("session->query", session->query.c_str(), 1024);
 
846
    fprintf(stderr, "session->thread_id=%"PRIu32"\n", (uint32_t) session->thread_id);
 
847
    fprintf(stderr, "session->killed=%s\n", kreason);
 
848
  }
 
849
  fflush(stderr);
 
850
#endif /* HAVE_STACKTRACE */
 
851
 
 
852
  if (calling_initgroups)
 
853
    fprintf(stderr, _("\nThis crash occurred while the server was calling "
 
854
                      "initgroups(). This is\n"
 
855
                      "often due to the use of a drizzled that is statically "
 
856
                      "linked against glibc\n"
 
857
                      "and configured to use LDAP in /etc/nsswitch.conf. "
 
858
                      "You will need to either\n"
 
859
                      "upgrade to a version of glibc that does not have this "
 
860
                      "problem (2.3.4 or\n"
 
861
                      "later when used with nscd), disable LDAP in your "
 
862
                      "nsswitch.conf, or use a\n"
 
863
                      "drizzled that is not statically linked.\n"));
 
864
 
 
865
  if (internal::thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
 
866
    fprintf(stderr,
 
867
            _("\nYou are running a statically-linked LinuxThreads binary "
 
868
              "on an NPTL system.\n"
 
869
              "This can result in crashes on some distributions due "
 
870
              "to LT/NPTL conflicts.\n"
 
871
              "You should either build a dynamically-linked binary, or force "
 
872
              "LinuxThreads\n"
 
873
              "to be used with the LD_ASSUME_KERNEL environment variable. "
 
874
              "Please consult\n"
 
875
              "the documentation for your distribution on how to do that.\n"));
 
876
 
 
877
#ifdef HAVE_WRITE_CORE
 
878
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
 
879
  {
 
880
    fprintf(stderr, _("Writing a core file\n"));
 
881
    fflush(stderr);
 
882
    write_core(sig);
 
883
  }
 
884
#endif
 
885
 
 
886
  exit(1);
 
887
}
 
888
 
 
889
#ifndef SA_RESETHAND
 
890
#define SA_RESETHAND 0
 
891
#endif
 
892
#ifndef SA_NODEFER
 
893
#define SA_NODEFER 0
 
894
#endif
 
895
 
 
896
 
 
897
/**
 
898
  All global error messages are sent here where the first one is stored
 
899
  for the client.
 
900
*/
 
901
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
 
902
{
 
903
  Session *session;
 
904
  /*
 
905
    Put here following assertion when situation with EE_* error codes
 
906
    will be fixed
 
907
  */
 
908
  if ((session= current_session))
 
909
  {
 
910
    if (MyFlags & ME_FATALERROR)
 
911
      session->is_fatal_error= 1;
 
912
 
 
913
    /*
 
914
      TODO: There are two exceptions mechanism (Session and sp_rcontext),
 
915
      this could be improved by having a common stack of handlers.
 
916
    */
 
917
    if (session->handle_error(error, str,
 
918
                          DRIZZLE_ERROR::WARN_LEVEL_ERROR))
 
919
      return;;
 
920
 
 
921
    /*
 
922
      session->lex->current_select == 0 if lex structure is not inited
 
923
      (not query command (COM_QUERY))
 
924
    */
 
925
    if (! (session->lex->current_select &&
 
926
        session->lex->current_select->no_error && !session->is_fatal_error))
 
927
    {
 
928
      if (! session->main_da.is_error())            // Return only first message
 
929
      {
 
930
        if (error == 0)
 
931
          error= ER_UNKNOWN_ERROR;
 
932
        if (str == NULL)
 
933
          str= ER(error);
 
934
        session->main_da.set_error_status(error, str);
 
935
      }
 
936
    }
 
937
 
 
938
    if (!session->no_warnings_for_error && !session->is_fatal_error)
 
939
    {
 
940
      /*
 
941
        Suppress infinite recursion if there a memory allocation error
 
942
        inside push_warning.
 
943
      */
 
944
      session->no_warnings_for_error= true;
 
945
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
 
946
      session->no_warnings_for_error= false;
 
947
    }
 
948
  }
 
949
  if (!session || MyFlags & ME_NOREFRESH)
 
950
    errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",internal::my_progname,str);
 
951
}
 
952
 
 
953
 
 
954
static const char *load_default_groups[]= {
 
955
DRIZZLE_CONFIG_NAME, "server", 0, 0};
 
956
 
 
957
static int show_starttime(drizzle_show_var *var, char *buff)
 
958
{
 
959
  var->type= SHOW_LONG;
 
960
  var->value= buff;
 
961
  *((long *)buff)= (long) (time(NULL) - server_start_time);
 
962
  return 0;
 
963
}
 
964
 
 
965
static int show_flushstatustime(drizzle_show_var *var, char *buff)
 
966
{
 
967
  var->type= SHOW_LONG;
 
968
  var->value= buff;
 
969
  *((long *)buff)= (long) (time(NULL) - flush_status_time);
 
970
  return 0;
 
971
}
 
972
 
 
973
static st_show_var_func_container show_starttime_cont= { &show_starttime };
 
974
 
 
975
static st_show_var_func_container show_flushstatustime_cont= { &show_flushstatustime };
 
976
 
 
977
/*
 
978
  Variables shown by SHOW STATUS in alphabetical order
 
979
*/
 
980
static drizzle_show_var com_status_vars[]= {
 
981
  {"admin_commands",       (char*) offsetof(system_status_var, com_other), SHOW_LONG_STATUS},
 
982
  {"alter_db",             (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
 
983
  {"alter_table",          (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
 
984
  {"analyze",              (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
 
985
  {"begin",                (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
 
986
  {"change_db",            (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
 
987
  {"check",                (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CHECK]), SHOW_LONG_STATUS},
 
988
  {"checksum",             (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
 
989
  {"commit",               (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
 
990
  {"create_db",            (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
 
991
  {"create_index",         (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
 
992
  {"create_table",         (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
 
993
  {"delete",               (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_DELETE]), SHOW_LONG_STATUS},
 
994
  {"drop_db",              (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
 
995
  {"drop_index",           (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
 
996
  {"drop_table",           (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
 
997
  {"empty_query",          (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
 
998
  {"flush",                (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
 
999
  {"insert",               (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_INSERT]), SHOW_LONG_STATUS},
 
1000
  {"insert_select",        (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
 
1001
  {"kill",                 (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_KILL]), SHOW_LONG_STATUS},
 
1002
  {"load",                 (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_LOAD]), SHOW_LONG_STATUS},
 
1003
  {"release_savepoint",    (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
 
1004
  {"rename_table",         (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
 
1005
  {"replace",              (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
 
1006
  {"replace_select",       (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
 
1007
  {"rollback",             (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
 
1008
  {"rollback_to_savepoint",(char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
 
1009
  {"savepoint",            (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
 
1010
  {"select",               (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SELECT]), SHOW_LONG_STATUS},
 
1011
  {"set_option",           (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
 
1012
  {"show_create_db",       (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
 
1013
  {"show_create_table",    (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
 
1014
  {"show_errors",          (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
 
1015
  {"show_warnings",        (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
 
1016
  {"truncate",             (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
 
1017
  {"unlock_tables",        (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
 
1018
  {"update",               (char*) offsetof(system_status_var, com_stat[(uint32_t) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
 
1019
  {NULL, NULL, SHOW_LONGLONG}
 
1020
};
 
1021
 
 
1022
static drizzle_show_var status_vars[]= {
 
1023
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONGLONG},
 
1024
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONGLONG},
 
1025
  {"Bytes_received",           (char*) offsetof(system_status_var, bytes_received), SHOW_LONGLONG_STATUS},
 
1026
  {"Bytes_sent",               (char*) offsetof(system_status_var, bytes_sent), SHOW_LONGLONG_STATUS},
 
1027
  {"Connections",              (char*) &global_thread_id, SHOW_INT_NOFLUSH},
 
1028
  {"Created_tmp_disk_tables",  (char*) offsetof(system_status_var, created_tmp_disk_tables), SHOW_LONG_STATUS},
 
1029
  {"Created_tmp_tables",       (char*) offsetof(system_status_var, created_tmp_tables), SHOW_LONG_STATUS},
 
1030
  {"Flush_commands",           (char*) &refresh_version,    SHOW_INT_NOFLUSH},
 
1031
  {"Handler_commit",           (char*) offsetof(system_status_var, ha_commit_count), SHOW_LONG_STATUS},
 
1032
  {"Handler_delete",           (char*) offsetof(system_status_var, ha_delete_count), SHOW_LONG_STATUS},
 
1033
  {"Handler_prepare",          (char*) offsetof(system_status_var, ha_prepare_count),  SHOW_LONG_STATUS},
 
1034
  {"Handler_read_first",       (char*) offsetof(system_status_var, ha_read_first_count), SHOW_LONG_STATUS},
 
1035
  {"Handler_read_key",         (char*) offsetof(system_status_var, ha_read_key_count), SHOW_LONG_STATUS},
 
1036
  {"Handler_read_next",        (char*) offsetof(system_status_var, ha_read_next_count), SHOW_LONG_STATUS},
 
1037
  {"Handler_read_prev",        (char*) offsetof(system_status_var, ha_read_prev_count), SHOW_LONG_STATUS},
 
1038
  {"Handler_read_rnd",         (char*) offsetof(system_status_var, ha_read_rnd_count), SHOW_LONG_STATUS},
 
1039
  {"Handler_read_rnd_next",    (char*) offsetof(system_status_var, ha_read_rnd_next_count), SHOW_LONG_STATUS},
 
1040
  {"Handler_rollback",         (char*) offsetof(system_status_var, ha_rollback_count), SHOW_LONG_STATUS},
 
1041
  {"Handler_savepoint",        (char*) offsetof(system_status_var, ha_savepoint_count), SHOW_LONG_STATUS},
 
1042
  {"Handler_savepoint_rollback",(char*) offsetof(system_status_var, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
 
1043
  {"Handler_update",           (char*) offsetof(system_status_var, ha_update_count), SHOW_LONG_STATUS},
 
1044
  {"Handler_write",            (char*) offsetof(system_status_var, ha_write_count), SHOW_LONG_STATUS},
 
1045
  {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
 
1046
  {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
 
1047
  {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
 
1048
  {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
 
1049
  {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
 
1050
  {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
 
1051
  {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
 
1052
  {"Last_query_cost",          (char*) offsetof(system_status_var, last_query_cost), SHOW_DOUBLE_STATUS},
 
1053
  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_INT},
 
1054
  {"Questions",                (char*) offsetof(system_status_var, questions), SHOW_LONG_STATUS},
 
1055
  {"Select_full_join",         (char*) offsetof(system_status_var, select_full_join_count), SHOW_LONG_STATUS},
 
1056
  {"Select_full_range_join",   (char*) offsetof(system_status_var, select_full_range_join_count), SHOW_LONG_STATUS},
 
1057
  {"Select_range",             (char*) offsetof(system_status_var, select_range_count), SHOW_LONG_STATUS},
 
1058
  {"Select_range_check",       (char*) offsetof(system_status_var, select_range_check_count), SHOW_LONG_STATUS},
 
1059
  {"Select_scan",              (char*) offsetof(system_status_var, select_scan_count), SHOW_LONG_STATUS},
 
1060
  {"Slow_queries",             (char*) offsetof(system_status_var, long_query_count), SHOW_LONG_STATUS},
 
1061
  {"Sort_merge_passes",        (char*) offsetof(system_status_var, filesort_merge_passes), SHOW_LONG_STATUS},
 
1062
  {"Sort_range",               (char*) offsetof(system_status_var, filesort_range_count), SHOW_LONG_STATUS},
 
1063
  {"Sort_rows",                (char*) offsetof(system_status_var, filesort_rows), SHOW_LONG_STATUS},
 
1064
  {"Sort_scan",                (char*) offsetof(system_status_var, filesort_scan_count), SHOW_LONG_STATUS},
 
1065
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_INT},
 
1066
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_INT},
 
1067
  {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
 
1068
  {"Uptime",                   (char*) &show_starttime_cont,         SHOW_FUNC},
 
1069
  {"Uptime_since_flush_status",(char*) &show_flushstatustime_cont,   SHOW_FUNC},
 
1070
  {NULL, NULL, SHOW_LONGLONG}
 
1071
};
 
1072
 
 
1073
static int init_common_variables(const char *conf_file_name, int argc,
 
1074
                                 char **argv, const char **groups)
 
1075
{
 
1076
  time_t curr_time;
 
1077
  umask(((~internal::my_umask) & 0666));
 
1078
  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
 
1079
  tzset();                      // Set tzname
 
1080
 
 
1081
  curr_time= time(NULL);
 
1082
  if (curr_time == (time_t)-1)
 
1083
    return 1;
 
1084
 
 
1085
  max_system_variables.pseudo_thread_id= UINT32_MAX;
 
1086
  server_start_time= flush_status_time= curr_time;
 
1087
 
 
1088
  if (init_thread_environment())
 
1089
    return 1;
 
1090
  drizzle_init_variables();
 
1091
 
 
1092
  {
 
1093
    struct tm tm_tmp;
 
1094
    localtime_r(&server_start_time,&tm_tmp);
 
1095
    strncpy(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
 
1096
            sizeof(system_time_zone)-1);
 
1097
 
 
1098
  }
 
1099
  /*
 
1100
    We set SYSTEM time zone as reasonable default and
 
1101
    also for failure of my_tz_init() and bootstrap mode.
 
1102
    If user explicitly set time zone with --default-time-zone
 
1103
    option we will change this value in my_tz_init().
 
1104
  */
 
1105
  global_system_variables.time_zone= my_tz_SYSTEM;
 
1106
 
 
1107
  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
 
1108
  {
 
1109
    strncpy(glob_hostname, STRING_WITH_LEN("localhost"));
 
1110
    errmsg_printf(ERRMSG_LVL_WARN, _("gethostname failed, using '%s' as hostname"),
 
1111
                  glob_hostname);
 
1112
    strncpy(pidfile_name, STRING_WITH_LEN("drizzle"));
 
1113
  }
 
1114
  else
 
1115
    strncpy(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
 
1116
  strcpy(internal::fn_ext(pidfile_name),".pid");                // Add proper extension
 
1117
 
 
1118
  /*
 
1119
    Add server status variables to the dynamic list of
 
1120
    status variables that is shown by SHOW STATUS.
 
1121
    Later, in plugin_init, new entries could be added to that list.
 
1122
  */
 
1123
  if (add_com_status_vars(com_status_vars))
 
1124
    return 1; // an error was already reported
 
1125
 
 
1126
  if (add_status_vars(status_vars))
 
1127
    return 1; // an error was already reported
 
1128
 
 
1129
  internal::load_defaults(conf_file_name, groups, &argc, &argv);
 
1130
  defaults_argv=argv;
 
1131
  defaults_argc=argc;
 
1132
  get_options(&defaults_argc, defaults_argv);
 
1133
 
 
1134
  current_pid= getpid();                /* Save for later ref */
 
1135
  init_time();                          /* Init time-functions (read zone) */
 
1136
 
 
1137
  if (init_errmessage())        /* Read error messages from file */
 
1138
    return 1;
 
1139
  if (item_create_init())
 
1140
    return 1;
 
1141
  if (set_var_init())
 
1142
    return 1;
 
1143
  /* Creates static regex matching for temporal values */
 
1144
  if (! init_temporal_formats())
 
1145
    return 1;
 
1146
 
 
1147
  if (!(default_charset_info=
 
1148
        get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
 
1149
  {
 
1150
    return 1;                           // Eof of the list
 
1151
  }
 
1152
 
 
1153
  if (default_collation_name)
 
1154
  {
 
1155
    const CHARSET_INFO * const default_collation= get_charset_by_name(default_collation_name);
 
1156
    if (not default_collation)
 
1157
    {
 
1158
      errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_UNKNOWN_COLLATION)), default_collation_name);
 
1159
      return 1;
 
1160
    }
 
1161
    if (not my_charset_same(default_charset_info, default_collation))
 
1162
    {
 
1163
      errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_COLLATION_CHARSET_MISMATCH)),
 
1164
                    default_collation_name,
 
1165
                    default_charset_info->csname);
 
1166
      return 1;
 
1167
    }
 
1168
    default_charset_info= default_collation;
 
1169
  }
 
1170
  /* Set collactions that depends on the default collation */
 
1171
  global_system_variables.collation_server=      default_charset_info;
 
1172
 
 
1173
  if (not (character_set_filesystem=
 
1174
           get_charset_by_csname(character_set_filesystem_name, MY_CS_PRIMARY)))
 
1175
    return 1;
 
1176
  global_system_variables.character_set_filesystem= character_set_filesystem;
 
1177
 
 
1178
  if (!(my_default_lc_time_names=
 
1179
        my_locale_by_name(lc_time_names_name)))
 
1180
  {
 
1181
    errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown locale: '%s'"), lc_time_names_name);
 
1182
    return 1;
 
1183
  }
 
1184
  global_system_variables.lc_time_names= my_default_lc_time_names;
 
1185
 
 
1186
  /* Reset table_alias_charset */
 
1187
  table_alias_charset= files_charset_info;
 
1188
 
 
1189
  return 0;
 
1190
}
 
1191
 
 
1192
 
 
1193
static int init_thread_environment()
 
1194
{
 
1195
   pthread_mutexattr_t attr; 
 
1196
   pthread_mutexattr_init(&attr);
 
1197
 
 
1198
  (void) pthread_mutex_init(&LOCK_create_db, NULL);
 
1199
  (void) pthread_mutex_init(&LOCK_open, NULL);
 
1200
 
 
1201
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 
 
1202
  (void) pthread_mutex_init(&LOCK_thread_count, &attr);
 
1203
  (void) pthread_mutex_init(&LOCK_global_system_variables, &attr);
 
1204
 
 
1205
  (void) pthread_mutex_init(&LOCK_status, MY_MUTEX_INIT_FAST);
 
1206
  (void) pthread_rwlock_init(&LOCK_system_variables_hash, NULL);
 
1207
  (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
 
1208
  (void) pthread_cond_init(&COND_thread_count,NULL);
 
1209
  (void) pthread_cond_init(&COND_server_end,NULL);
 
1210
  (void) pthread_cond_init(&COND_refresh,NULL);
 
1211
  (void) pthread_cond_init(&COND_global_read_lock,NULL);
 
1212
 
 
1213
  pthread_mutexattr_destroy(&attr);
 
1214
 
 
1215
  if (pthread_key_create(&THR_Session,NULL) ||
 
1216
      pthread_key_create(&THR_Mem_root,NULL))
 
1217
  {
 
1218
      errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create thread-keys"));
 
1219
    return 1;
 
1220
  }
 
1221
  return 0;
 
1222
}
 
1223
 
 
1224
 
 
1225
static int init_server_components(plugin::Registry &plugins)
 
1226
{
 
1227
  /*
 
1228
    We need to call each of these following functions to ensure that
 
1229
    all things are initialized so that unireg_abort() doesn't fail
 
1230
  */
 
1231
  if (table_cache_init())
 
1232
    unireg_abort(1);
 
1233
  TableShare::cacheStart();
 
1234
 
 
1235
  setup_fpu();
 
1236
  init_thr_lock();
 
1237
 
 
1238
  /* Setup logs */
 
1239
 
 
1240
  if (xid_cache_init())
 
1241
  {
 
1242
      errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory"));
 
1243
    unireg_abort(1);
 
1244
  }
 
1245
 
 
1246
  /* Allow storage engine to give real error messages */
 
1247
  if (ha_init_errors())
 
1248
    return(1);
 
1249
 
 
1250
  if (plugin_init(plugins, &defaults_argc, defaults_argv,
 
1251
                  ((opt_help) ? true : false)))
 
1252
  {
 
1253
    errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize plugins."));
 
1254
    unireg_abort(1);
 
1255
  }
 
1256
 
 
1257
  if (opt_help || opt_help_extended)
 
1258
    unireg_abort(0);
 
1259
 
 
1260
  /* we do want to exit if there are any other unknown options */
 
1261
  if (defaults_argc > 1)
 
1262
  {
 
1263
    int ho_error;
 
1264
    char **tmp_argv= defaults_argv;
 
1265
    struct my_option no_opts[]=
 
1266
    {
 
1267
      {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
1268
    };
 
1269
    /*
 
1270
      We need to eat any 'loose' arguments first before we conclude
 
1271
      that there are unprocessed options.
 
1272
      But we need to preserve defaults_argv pointer intact for
 
1273
      internal::free_defaults() to work. Thus we use a copy here.
 
1274
    */
 
1275
    my_getopt_skip_unknown= 0;
 
1276
 
 
1277
    if ((ho_error= handle_options(&defaults_argc, &tmp_argv, no_opts,
 
1278
                                  drizzled_get_one_option)))
 
1279
      unireg_abort(ho_error);
 
1280
 
 
1281
    if (defaults_argc)
 
1282
    {
 
1283
      fprintf(stderr,
 
1284
              _("%s: Too many arguments (first extra is '%s').\n"
 
1285
                "Use --verbose --help to get a list of available options\n"),
 
1286
              internal::my_progname, *tmp_argv);
 
1287
      unireg_abort(1);
 
1288
    }
 
1289
  }
 
1290
 
 
1291
  string scheduler_name;
 
1292
  if (opt_scheduler)
 
1293
  {
 
1294
    scheduler_name= opt_scheduler;
 
1295
  }
 
1296
  else
 
1297
  {
 
1298
    scheduler_name= opt_scheduler_default;
 
1299
  }
 
1300
 
 
1301
  if (plugin::Scheduler::setPlugin(scheduler_name))
 
1302
  {
 
1303
      errmsg_printf(ERRMSG_LVL_ERROR,
 
1304
                   _("No scheduler found, cannot continue!\n"));
 
1305
      unireg_abort(1);
 
1306
  }
 
1307
 
 
1308
  /*
 
1309
    This is entirely for legacy. We will create a new "disk based" engine and a
 
1310
    "memory" engine which will be configurable longterm.
 
1311
  */
 
1312
  const std::string myisam_engine_name("MyISAM");
 
1313
  const std::string heap_engine_name("MEMORY");
 
1314
  myisam_engine= plugin::StorageEngine::findByName(myisam_engine_name);
 
1315
  heap_engine= plugin::StorageEngine::findByName(heap_engine_name);
 
1316
 
 
1317
  /*
 
1318
    Check that the default storage engine is actually available.
 
1319
  */
 
1320
  if (default_storage_engine_str)
 
1321
  {
 
1322
    const std::string name(default_storage_engine_str);
 
1323
    plugin::StorageEngine *engine;
 
1324
 
 
1325
    engine= plugin::StorageEngine::findByName(name);
 
1326
    if (engine == NULL)
 
1327
    {
 
1328
      errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown/unsupported storage engine: %s"),
 
1329
                    default_storage_engine_str);
 
1330
      unireg_abort(1);
 
1331
    }
 
1332
    global_system_variables.storage_engine= engine;
 
1333
  }
 
1334
 
 
1335
  if (plugin::XaResourceManager::recoverAllXids(0))
 
1336
  {
 
1337
    unireg_abort(1);
 
1338
  }
 
1339
 
 
1340
  init_update_queries();
 
1341
 
 
1342
  return(0);
 
1343
}
 
1344
 
 
1345
 
 
1346
/****************************************************************************
 
1347
  Handle start options
 
1348
******************************************************************************/
 
1349
 
 
1350
enum options_drizzled
 
1351
{
 
1352
  OPT_SOCKET=256,
 
1353
  OPT_BIND_ADDRESS,            
 
1354
  OPT_PID_FILE,
 
1355
  OPT_STORAGE_ENGINE,          
 
1356
  OPT_INIT_FILE,
 
1357
  OPT_WANT_CORE,
 
1358
  OPT_MEMLOCK,
 
1359
  OPT_SERVER_ID,
 
1360
  OPT_TC_HEURISTIC_RECOVER,
 
1361
  OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
 
1362
  OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
 
1363
  OPT_DO_PSTACK,
 
1364
  OPT_LOCAL_INFILE,
 
1365
  OPT_BACK_LOG,
 
1366
  OPT_JOIN_BUFF_SIZE,
 
1367
  OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
 
1368
  OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
 
1369
  OPT_MAX_ALLOWED_PACKET,
 
1370
  OPT_MAX_CONNECT_ERRORS,
 
1371
  OPT_MAX_HEP_TABLE_SIZE,
 
1372
  OPT_MAX_JOIN_SIZE,
 
1373
  OPT_MAX_SORT_LENGTH,
 
1374
  OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
 
1375
  OPT_MAX_LENGTH_FOR_SORT_DATA,
 
1376
  OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
 
1377
  OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
 
1378
  OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
 
1379
  OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
 
1380
  OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS,
 
1381
  OPT_NET_BUFFER_LENGTH,
 
1382
  OPT_PRELOAD_BUFFER_SIZE,
 
1383
  OPT_RECORD_BUFFER,
 
1384
  OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT,
 
1385
  OPT_DEBUGGING,
 
1386
  OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
 
1387
  OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
 
1388
  OPT_WAIT_TIMEOUT,
 
1389
  OPT_RANGE_ALLOC_BLOCK_SIZE,
 
1390
  OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
 
1391
  OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
 
1392
  OPT_OLD_ALTER_TABLE,
 
1393
  OPT_GROUP_CONCAT_MAX_LEN,
 
1394
  OPT_DEFAULT_COLLATION,
 
1395
  OPT_CHARACTER_SET_FILESYSTEM,
 
1396
  OPT_LC_TIME_NAMES,
 
1397
  OPT_INIT_CONNECT,
 
1398
  OPT_DEFAULT_TIME_ZONE,
 
1399
  OPT_OPTIMIZER_SEARCH_DEPTH,
 
1400
  OPT_SCHEDULER,
 
1401
  OPT_PROTOCOL,
 
1402
  OPT_OPTIMIZER_PRUNE_LEVEL,
 
1403
  OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
 
1404
  OPT_ENABLE_LARGE_PAGES,
 
1405
  OPT_TIMED_MUTEXES,
 
1406
  OPT_TABLE_LOCK_WAIT_TIMEOUT,
 
1407
  OPT_PLUGIN_ADD,
 
1408
  OPT_PLUGIN_REMOVE,
 
1409
  OPT_PLUGIN_LOAD,
 
1410
  OPT_PLUGIN_DIR,
 
1411
  OPT_PORT_OPEN_TIMEOUT,
 
1412
  OPT_SECURE_FILE_PRIV,
 
1413
  OPT_MIN_EXAMINED_ROW_LIMIT
 
1414
};
 
1415
 
 
1416
 
 
1417
struct my_option my_long_options[] =
 
1418
{
 
1419
  {"help", '?', N_("Display this help and exit."),
 
1420
   (char**) &opt_help, (char**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
 
1421
   0, 0},
 
1422
  {"help-extended", '?',
 
1423
   N_("Display this help and exit after initializing plugins."),
 
1424
   (char**) &opt_help_extended, (char**) &opt_help_extended,
 
1425
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
1426
  {"auto-increment-increment", OPT_AUTO_INCREMENT,
 
1427
   N_("Auto-increment columns are incremented by this"),
 
1428
   (char**) &global_system_variables.auto_increment_increment,
 
1429
   (char**) &max_system_variables.auto_increment_increment, 0, GET_ULL,
 
1430
   OPT_ARG, 1, 1, UINT64_MAX, 0, 1, 0 },
 
1431
  {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
 
1432
   N_("Offset added to Auto-increment columns. Used when "
 
1433
      "auto-increment-increment != 1"),
 
1434
   (char**) &global_system_variables.auto_increment_offset,
 
1435
   (char**) &max_system_variables.auto_increment_offset, 0, GET_ULL, OPT_ARG,
 
1436
   1, 1, UINT64_MAX, 0, 1, 0 },
 
1437
  {"basedir", 'b',
 
1438
   N_("Path to installation directory. All paths are usually resolved "
 
1439
      "relative to this."),
 
1440
   (char**) &drizzle_home_ptr, (char**) &drizzle_home_ptr, 0, GET_STR, REQUIRED_ARG,
 
1441
   0, 0, 0, 0, 0, 0},
 
1442
  {"chroot", 'r',
 
1443
   N_("Chroot drizzled daemon during startup."),
 
1444
   (char**) &drizzled_chroot, (char**) &drizzled_chroot, 0, GET_STR, REQUIRED_ARG,
 
1445
   0, 0, 0, 0, 0, 0},
 
1446
  {"collation-server", OPT_DEFAULT_COLLATION,
 
1447
   N_("Set the default collation."),
 
1448
   (char**) &default_collation_name, (char**) &default_collation_name,
 
1449
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
1450
  {"completion-type", OPT_COMPLETION_TYPE,
 
1451
   N_("Default completion type."),
 
1452
   (char**) &global_system_variables.completion_type,
 
1453
   (char**) &max_system_variables.completion_type, 0, GET_UINT,
 
1454
   REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
 
1455
  {"core-file", OPT_WANT_CORE,
 
1456
   N_("Write core on errors."),
 
1457
   0, 0, 0, GET_NO_ARG,
 
1458
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
1459
  {"datadir", 'h',
 
1460
   N_("Path to the database root."),
 
1461
   (char**) &drizzle_data_home,
 
1462
   (char**) &drizzle_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1463
  {"default-storage-engine", OPT_STORAGE_ENGINE,
 
1464
   N_("Set the default storage engine (table type) for tables."),
 
1465
   (char**)&default_storage_engine_str, (char**)&default_storage_engine_str,
 
1466
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1467
  {"default-time-zone", OPT_DEFAULT_TIME_ZONE,
 
1468
   N_("Set the default time zone."),
 
1469
   (char**) &default_tz_name, (char**) &default_tz_name,
 
1470
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
1471
#ifdef HAVE_STACK_TRACE_ON_SEGV
 
1472
  {"enable-pstack", OPT_DO_PSTACK,
 
1473
   N_("Print a symbolic stack trace on failure."),
 
1474
   (char**) &opt_do_pstack, (char**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
 
1475
   0, 0, 0, 0},
 
1476
#endif /* HAVE_STACK_TRACE_ON_SEGV */
 
1477
  /* See how it's handled in get_one_option() */
 
1478
  {"exit-info", 'T',
 
1479
   N_("Used for debugging;  Use at your own risk!"),
 
1480
   0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
1481
  /* We must always support the next option to make scripts like mysqltest
 
1482
     easier to do */
 
1483
  {"gdb", OPT_DEBUGGING,
 
1484
   N_("Set up signals usable for debugging"),
 
1485
   (char**) &opt_debugging, (char**) &opt_debugging,
 
1486
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 
1487
  {"language", 'L',
 
1488
   N_("(IGNORED)"),
 
1489
   (char**) &language_ptr, (char**) &language_ptr, 0, GET_STR, REQUIRED_ARG,
 
1490
   0, 0, 0, 0, 0, 0},
 
1491
  {"lc-time-names", OPT_LC_TIME_NAMES,
 
1492
   N_("Set the language used for the month names and the days of the week."),
 
1493
   (char**) &lc_time_names_name,
 
1494
   (char**) &lc_time_names_name,
 
1495
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
1496
  {"log-warnings", 'W',
 
1497
   N_("Log some not critical warnings to the log file."),
 
1498
   (char**) &global_system_variables.log_warnings,
 
1499
   (char**) &max_system_variables.log_warnings, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
 
1500
   0, 0, 0},
 
1501
  {"pid-file", OPT_PID_FILE,
 
1502
   N_("Pid file used by safe_mysqld."),
 
1503
   (char**) &pidfile_name_ptr, (char**) &pidfile_name_ptr, 0, GET_STR,
 
1504
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1505
  {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
 
1506
   N_("Maximum time in seconds to wait for the port to become free. "
 
1507
      "(Default: no wait)"),
 
1508
   (char**) &drizzled_bind_timeout,
 
1509
   (char**) &drizzled_bind_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1510
  {"secure-file-priv", OPT_SECURE_FILE_PRIV,
 
1511
   N_("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
 
1512
      "within specified directory"),
 
1513
   (char**) &opt_secure_file_priv, (char**) &opt_secure_file_priv, 0,
 
1514
   GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1515
  {"server-id", OPT_SERVER_ID,
 
1516
   N_("Uniquely identifies the server instance in the community of "
 
1517
      "replication partners."),
 
1518
   (char**) &server_id, (char**) &server_id, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 0,
 
1519
   0, 0, 0},
 
1520
  {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
 
1521
   N_("Don't print a stack trace on failure."),
 
1522
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
 
1523
   0, 0, 0, 0},
 
1524
  {"symbolic-links", 's',
 
1525
   N_("Enable symbolic link support."),
 
1526
   (char**) &internal::my_use_symdir, (char**) &internal::my_use_symdir, 0, GET_BOOL, NO_ARG,
 
1527
   /*
 
1528
     The system call realpath() produces warnings under valgrind and
 
1529
     purify. These are not suppressed: instead we disable symlinks
 
1530
     option if compiled with valgrind support.
 
1531
   */
 
1532
   IF_PURIFY(0,1), 0, 0, 0, 0, 0},
 
1533
  {"timed_mutexes", OPT_TIMED_MUTEXES,
 
1534
   N_("Specify whether to time mutexes (only InnoDB mutexes are currently "
 
1535
      "supported)"),
 
1536
   (char**) &internal::timed_mutexes, (char**) &internal::timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
 
1537
    0, 0, 0, 0, 0},
 
1538
  {"tmpdir", 't',
 
1539
   N_("Path for temporary files."),
 
1540
   (char**) &opt_drizzle_tmpdir,
 
1541
   (char**) &opt_drizzle_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1542
  {"transaction-isolation", OPT_TX_ISOLATION,
 
1543
   N_("Default transaction isolation level."),
 
1544
   0, 0, 0, GET_STR, REQUIRED_ARG, 0,
 
1545
   0, 0, 0, 0, 0},
 
1546
  {"user", 'u',
 
1547
   N_("Run drizzled daemon as user."),
 
1548
   0, 0, 0, GET_STR, REQUIRED_ARG,
 
1549
   0, 0, 0, 0, 0, 0},
 
1550
  {"version", 'V',
 
1551
   N_("Output version information and exit."),
 
1552
   0, 0, 0, GET_NO_ARG,
 
1553
   NO_ARG, 0, 0, 0, 0, 0, 0},
 
1554
  {"back_log", OPT_BACK_LOG,
 
1555
   N_("The number of outstanding connection requests Drizzle can have. This "
 
1556
      "comes into play when the main Drizzle thread gets very many connection "
 
1557
      "requests in a very short time."),
 
1558
    (char**) &back_log, (char**) &back_log, 0, GET_UINT,
 
1559
    REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
 
1560
  { "bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
 
1561
    N_("Size of tree cache used in bulk insert optimization. Note that this is "
 
1562
       "a limit per thread!"),
 
1563
    (char**) &global_system_variables.bulk_insert_buff_size,
 
1564
    (char**) &max_system_variables.bulk_insert_buff_size,
 
1565
    0, GET_ULL, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0},
 
1566
  { "div_precision_increment", OPT_DIV_PRECINCREMENT,
 
1567
   N_("Precision of the result of '/' operator will be increased on that "
 
1568
      "value."),
 
1569
   (char**) &global_system_variables.div_precincrement,
 
1570
   (char**) &max_system_variables.div_precincrement, 0, GET_UINT,
 
1571
   REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
 
1572
  { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN,
 
1573
    N_("The maximum length of the result of function  group_concat."),
 
1574
    (char**) &global_system_variables.group_concat_max_len,
 
1575
    (char**) &max_system_variables.group_concat_max_len, 0, GET_UINT64,
 
1576
    REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0},
 
1577
  { "join_buffer_size", OPT_JOIN_BUFF_SIZE,
 
1578
    N_("The size of the buffer that is used for full joins."),
 
1579
   (char**) &global_system_variables.join_buff_size,
 
1580
   (char**) &max_system_variables.join_buff_size, 0, GET_UINT64,
 
1581
   REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX,
 
1582
   MALLOC_OVERHEAD, IO_SIZE, 0},
 
1583
  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
 
1584
   N_("Max packetlength to send/receive from to server."),
 
1585
   (char**) &global_system_variables.max_allowed_packet,
 
1586
   (char**) &max_system_variables.max_allowed_packet, 0, GET_UINT32,
 
1587
   REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
 
1588
  {"max_connect_errors", OPT_MAX_CONNECT_ERRORS,
 
1589
   N_("If there is more than this number of interrupted connections from a "
 
1590
      "host this host will be blocked from further connections."),
 
1591
   (char**) &max_connect_errors, (char**) &max_connect_errors, 0, GET_UINT64,
 
1592
   REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0},
 
1593
  {"max_error_count", OPT_MAX_ERROR_COUNT,
 
1594
   N_("Max number of errors/warnings to store for a statement."),
 
1595
   (char**) &global_system_variables.max_error_count,
 
1596
   (char**) &max_system_variables.max_error_count,
 
1597
   0, GET_UINT64, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
 
1598
  {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
 
1599
   N_("Don't allow creation of heap tables bigger than this."),
 
1600
   (char**) &global_system_variables.max_heap_table_size,
 
1601
   (char**) &max_system_variables.max_heap_table_size, 0, GET_ULL,
 
1602
   REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE,
 
1603
   MALLOC_OVERHEAD, 1024, 0},
 
1604
  {"max_join_size", OPT_MAX_JOIN_SIZE,
 
1605
   N_("Joins that are probably going to read more than max_join_size records "
 
1606
      "return an error."),
 
1607
   (char**) &global_system_variables.max_join_size,
 
1608
   (char**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
 
1609
   INT32_MAX, 1, INT32_MAX, 0, 1, 0},
 
1610
  {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
 
1611
   N_("Max number of bytes in sorted records."),
 
1612
   (char**) &global_system_variables.max_length_for_sort_data,
 
1613
   (char**) &max_system_variables.max_length_for_sort_data, 0, GET_ULL,
 
1614
   REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
 
1615
  { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
 
1616
    N_("Limit assumed max number of seeks when looking up rows based on a key"),
 
1617
    (char**) &global_system_variables.max_seeks_for_key,
 
1618
    (char**) &max_system_variables.max_seeks_for_key, 0, GET_UINT64,
 
1619
    REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 },
 
1620
  {"max_sort_length", OPT_MAX_SORT_LENGTH,
 
1621
   N_("The number of bytes to use when sorting BLOB or TEXT values "
 
1622
      "(only the first max_sort_length bytes of each value are used; the "
 
1623
      "rest are ignored)."),
 
1624
   (char**) &global_system_variables.max_sort_length,
 
1625
   (char**) &max_system_variables.max_sort_length, 0, GET_SIZE,
 
1626
   REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
 
1627
  {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
 
1628
   N_("After this many write locks, allow some read locks to run in between."),
 
1629
   (char**) &max_write_lock_count, (char**) &max_write_lock_count, 0, GET_ULL,
 
1630
   REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
 
1631
  {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
 
1632
   N_("Don't log queries which examine less than min_examined_row_limit "
 
1633
      "rows to file."),
 
1634
   (char**) &global_system_variables.min_examined_row_limit,
 
1635
   (char**) &max_system_variables.min_examined_row_limit, 0, GET_ULL,
 
1636
   REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0},
 
1637
  {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
 
1638
    N_("Controls the heuristic(s) applied during query optimization to prune "
 
1639
       "less-promising partial plans from the optimizer search space. Meaning: "
 
1640
       "false - do not apply any heuristic, thus perform exhaustive search; "
 
1641
       "true - prune plans based on number of retrieved rows."),
 
1642
    (char**) &global_system_variables.optimizer_prune_level,
 
1643
    (char**) &max_system_variables.optimizer_prune_level,
 
1644
    0, GET_BOOL, OPT_ARG, 1, 0, 1, 0, 1, 0},
 
1645
  {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
 
1646
   N_("Maximum depth of search performed by the query optimizer. Values "
 
1647
      "larger than the number of relations in a query result in better query "
 
1648
      "plans, but take longer to compile a query. Smaller values than the "
 
1649
      "number of tables in a relation result in faster optimization, but may "
 
1650
      "produce very bad query plans. If set to 0, the system will "
 
1651
      "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
 
1652
      "optimizer will switch to the original find_best (used for "
 
1653
      "testing/comparison)."),
 
1654
   (char**) &global_system_variables.optimizer_search_depth,
 
1655
   (char**) &max_system_variables.optimizer_search_depth,
 
1656
   0, GET_UINT, OPT_ARG, 0, 0, MAX_TABLES+2, 0, 1, 0},
 
1657
  {"plugin_dir", OPT_PLUGIN_DIR,
 
1658
   N_("Directory for plugins."),
 
1659
   (char**) &opt_plugin_dir_ptr, (char**) &opt_plugin_dir_ptr, 0,
 
1660
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1661
  {"plugin_add", OPT_PLUGIN_ADD,
 
1662
   N_("Optional comma separated list of plugins to load at startup in addition "
 
1663
      "to the default list of plugins. "
 
1664
      "[for example: --plugin_add=crc32,logger_gearman]"),
 
1665
   (char**) &opt_plugin_add, (char**) &opt_plugin_add, 0,
 
1666
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1667
  {"plugin_remove", OPT_PLUGIN_ADD,
 
1668
   N_("Optional comma separated list of plugins to not load at startup. Effectively "
 
1669
      "removes a plugin from the list of plugins to be loaded. "
 
1670
      "[for example: --plugin_remove=crc32,logger_gearman]"),
 
1671
   (char**) &opt_plugin_remove, (char**) &opt_plugin_remove, 0,
 
1672
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1673
  {"plugin_load", OPT_PLUGIN_LOAD,
 
1674
   N_("Optional comma separated list of plugins to load at starup instead of "
 
1675
      "the default plugin load list. "
 
1676
      "[for example: --plugin_load=crc32,logger_gearman]"),
 
1677
   (char**) &opt_plugin_load, (char**) &opt_plugin_load, 0,
 
1678
   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1679
  {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
 
1680
   N_("The size of the buffer that is allocated when preloading indexes"),
 
1681
   (char**) &global_system_variables.preload_buff_size,
 
1682
   (char**) &max_system_variables.preload_buff_size, 0, GET_ULL,
 
1683
   REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
 
1684
  {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
 
1685
   N_("Allocation block size for query parsing and execution"),
 
1686
   (char**) &global_system_variables.query_alloc_block_size,
 
1687
   (char**) &max_system_variables.query_alloc_block_size, 0, GET_UINT,
 
1688
   REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
 
1689
  {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
 
1690
   N_("Persistent buffer for query parsing and execution"),
 
1691
   (char**) &global_system_variables.query_prealloc_size,
 
1692
   (char**) &max_system_variables.query_prealloc_size, 0, GET_UINT,
 
1693
   REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
 
1694
   ULONG_MAX, 0, 1024, 0},
 
1695
  {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
 
1696
   N_("Allocation block size for storing ranges during optimization"),
 
1697
   (char**) &global_system_variables.range_alloc_block_size,
 
1698
   (char**) &max_system_variables.range_alloc_block_size, 0, GET_SIZE,
 
1699
   REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, SIZE_MAX,
 
1700
   0, 1024, 0},
 
1701
  {"read_buffer_size", OPT_RECORD_BUFFER,
 
1702
    N_("Each thread that does a sequential scan allocates a buffer of this "
 
1703
       "size for each table it scans. If you do many sequential scans, you may "
 
1704
       "want to increase this value."),
 
1705
    (char**) &global_system_variables.read_buff_size,
 
1706
    (char**) &max_system_variables.read_buff_size,0, GET_UINT, REQUIRED_ARG,
 
1707
    128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT32_MAX, MALLOC_OVERHEAD, IO_SIZE,
 
1708
    0},
 
1709
  {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
 
1710
   N_("When reading rows in sorted order after a sort, the rows are read "
 
1711
      "through this buffer to avoid a disk seeks. If not set, then it's set "
 
1712
      "to the value of record_buffer."),
 
1713
   (char**) &global_system_variables.read_rnd_buff_size,
 
1714
   (char**) &max_system_variables.read_rnd_buff_size, 0,
 
1715
   GET_UINT, REQUIRED_ARG, 256*1024L, 64 /*IO_SIZE*2+MALLOC_OVERHEAD*/ ,
 
1716
   UINT32_MAX, MALLOC_OVERHEAD, 1 /* Small lower limit to be able to test MRR */, 0},
 
1717
  {"scheduler", OPT_SCHEDULER,
 
1718
   N_("Select scheduler to be used (by default multi-thread)."),
 
1719
   (char**)&opt_scheduler, (char**)&opt_scheduler,
 
1720
   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
1721
  /* x8 compared to MySQL's x2. We have UTF8 to consider. */
 
1722
  {"sort_buffer_size", OPT_SORT_BUFFER,
 
1723
   N_("Each thread that needs to do a sort allocates a buffer of this size."),
 
1724
   (char**) &global_system_variables.sortbuff_size,
 
1725
   (char**) &max_system_variables.sortbuff_size, 0, GET_SIZE, REQUIRED_ARG,
 
1726
   MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*8, SIZE_MAX,
 
1727
   MALLOC_OVERHEAD, 1, 0},
 
1728
  {"table_definition_cache", OPT_TABLE_DEF_CACHE,
 
1729
   N_("The number of cached table definitions."),
 
1730
   (char**) &table_def_size, (char**) &table_def_size,
 
1731
   0, GET_SIZE, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0},
 
1732
  {"table_open_cache", OPT_TABLE_OPEN_CACHE,
 
1733
   N_("The number of cached open tables."),
 
1734
   (char**) &table_cache_size, (char**) &table_cache_size, 0, GET_UINT64,
 
1735
   REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, TABLE_OPEN_CACHE_MIN, 512*1024L, 0, 1, 0},
 
1736
  {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT,
 
1737
   N_("Timeout in seconds to wait for a table level lock before returning an "
 
1738
      "error. Used only if the connection has active cursors."),
 
1739
   (char**) &table_lock_wait_timeout, (char**) &table_lock_wait_timeout,
 
1740
   0, GET_ULL, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
 
1741
  {"thread_stack", OPT_THREAD_STACK,
 
1742
   N_("The stack size for each thread."),
 
1743
   (char**) &my_thread_stack_size,
 
1744
   (char**) &my_thread_stack_size, 0, GET_SIZE,
 
1745
   REQUIRED_ARG,DEFAULT_THREAD_STACK,
 
1746
   UINT32_C(1024*512), SIZE_MAX, 0, 1024, 0},
 
1747
  {"tmp_table_size", OPT_TMP_TABLE_SIZE,
 
1748
   N_("If an internal in-memory temporary table exceeds this size, Drizzle will"
 
1749
      " automatically convert it to an on-disk MyISAM table."),
 
1750
   (char**) &global_system_variables.tmp_table_size,
 
1751
   (char**) &max_system_variables.tmp_table_size, 0, GET_ULL,
 
1752
   REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
 
1753
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
1754
};
 
1755
 
 
1756
static void print_version(void)
 
1757
{
 
1758
  /*
 
1759
    Note: the instance manager keys off the string 'Ver' so it can find the
 
1760
    version from the output of 'drizzled --version', so don't change it!
 
1761
  */
 
1762
  printf("%s  Ver %s for %s-%s on %s (%s)\n",internal::my_progname,
 
1763
         PANDORA_RELEASE_VERSION, HOST_VENDOR, HOST_OS, HOST_CPU,
 
1764
         COMPILATION_COMMENT);
 
1765
}
 
1766
 
 
1767
static void usage(void)
 
1768
{
 
1769
  if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
 
1770
    exit(1);
 
1771
  if (!default_collation_name)
 
1772
    default_collation_name= (char*) default_charset_info->name;
 
1773
  print_version();
 
1774
  puts(_("Copyright (C) 2008 Sun Microsystems\n"
 
1775
         "This software comes with ABSOLUTELY NO WARRANTY. "
 
1776
         "This is free software,\n"
 
1777
         "and you are welcome to modify and redistribute it under the GPL "
 
1778
         "license\n\n"
 
1779
         "Starts the Drizzle database server\n"));
 
1780
 
 
1781
  printf(_("Usage: %s [OPTIONS]\n"), internal::my_progname);
 
1782
  {
 
1783
     internal::print_defaults(DRIZZLE_CONFIG_NAME,load_default_groups);
 
1784
     puts("");
 
1785
 
 
1786
     /* Print out all the options including plugin supplied options */
 
1787
     my_print_help_inc_plugins(my_long_options);
 
1788
  }
 
1789
}
 
1790
 
 
1791
 
 
1792
/**
 
1793
  Initialize all Drizzle global variables to default values.
 
1794
 
 
1795
  We don't need to set numeric variables refered to in my_long_options
 
1796
  as these are initialized by my_getopt.
 
1797
 
 
1798
  @note
 
1799
    The reason to set a lot of global variables to zero is to allow one to
 
1800
    restart the embedded server with a clean environment
 
1801
    It's also needed on some exotic platforms where global variables are
 
1802
    not set to 0 when a program starts.
 
1803
 
 
1804
    We don't need to set numeric variables refered to in my_long_options
 
1805
    as these are initialized by my_getopt.
 
1806
*/
 
1807
 
 
1808
static void drizzle_init_variables(void)
 
1809
{
 
1810
  /* Things reset to zero */
 
1811
  drizzle_home[0]= pidfile_name[0]= 0;
 
1812
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
 
1813
  opt_secure_file_priv= 0;
 
1814
  segfaulted= 0;
 
1815
  cleanup_done= 0;
 
1816
  defaults_argc= 0;
 
1817
  defaults_argv= 0;
 
1818
  dropping_tables= ha_open_options=0;
 
1819
  test_flags.reset();
 
1820
  wake_thread=0;
 
1821
  abort_loop= select_thread_in_use= false;
 
1822
  ready_to_exit= shutdown_in_progress= 0;
 
1823
  aborted_threads= aborted_connects= 0;
 
1824
  max_used_connections= 0;
 
1825
  drizzled_user= drizzled_chroot= 0;
 
1826
  memset(&global_status_var, 0, sizeof(global_status_var));
 
1827
  key_map_full.set();
 
1828
 
 
1829
  /* Character sets */
 
1830
  system_charset_info= &my_charset_utf8_general_ci;
 
1831
  files_charset_info= &my_charset_utf8_general_ci;
 
1832
  table_alias_charset= &my_charset_bin;
 
1833
  character_set_filesystem= &my_charset_bin;
 
1834
 
 
1835
  /* Things with default values that are not zero */
 
1836
  drizzle_home_ptr= drizzle_home;
 
1837
  pidfile_name_ptr= pidfile_name;
 
1838
  language_ptr= language;
 
1839
  drizzle_data_home= drizzle_real_data_home;
 
1840
  session_startup_options= (OPTION_AUTO_IS_NULL | OPTION_SQL_NOTES);
 
1841
  refresh_version= 1L;  /* Increments on each reload */
 
1842
  global_thread_id= 1UL;
 
1843
  getSessionList().clear();
 
1844
 
 
1845
  /* Set directory paths */
 
1846
  strncpy(language, LANGUAGE, sizeof(language)-1);
 
1847
  strncpy(drizzle_real_data_home, get_relative_path(LOCALSTATEDIR),
 
1848
          sizeof(drizzle_real_data_home)-1);
 
1849
  drizzle_data_home_buff[0]=FN_CURLIB;  // all paths are relative from here
 
1850
  drizzle_data_home_buff[1]=0;
 
1851
  drizzle_data_home_len= 2;
 
1852
 
 
1853
  /* Variables in libraries */
 
1854
  default_character_set_name= "utf8";
 
1855
  default_collation_name= (char *)compiled_default_collation_name;
 
1856
  character_set_filesystem_name= "binary";
 
1857
  lc_time_names_name= (char*) "en_US";
 
1858
  /* Set default values for some option variables */
 
1859
  default_storage_engine_str= (char*) "innodb";
 
1860
  global_system_variables.storage_engine= NULL;
 
1861
  global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
 
1862
  global_system_variables.select_limit= (uint64_t) HA_POS_ERROR;
 
1863
  max_system_variables.select_limit=    (uint64_t) HA_POS_ERROR;
 
1864
  global_system_variables.max_join_size= (uint64_t) HA_POS_ERROR;
 
1865
  max_system_variables.max_join_size=   (uint64_t) HA_POS_ERROR;
 
1866
 
 
1867
  /* Variables that depends on compile options */
 
1868
#ifdef HAVE_BROKEN_REALPATH
 
1869
  have_symlink=SHOW_OPTION_NO;
 
1870
#else
 
1871
  have_symlink=SHOW_OPTION_YES;
 
1872
#endif
 
1873
 
 
1874
  const char *tmpenv;
 
1875
  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
 
1876
    tmpenv = PREFIX;
 
1877
  (void) strncpy(drizzle_home, tmpenv, sizeof(drizzle_home)-1);
 
1878
  
 
1879
  connection_count= 0;
 
1880
}
 
1881
 
 
1882
 
 
1883
bool drizzled_get_one_option(int optid, const struct my_option *opt,
 
1884
                             char *argument)
 
1885
{
 
1886
  switch(optid) {
 
1887
  case 'a':
 
1888
    global_system_variables.tx_isolation= ISO_SERIALIZABLE;
 
1889
    break;
 
1890
  case 'b':
 
1891
    strncpy(drizzle_home,argument,sizeof(drizzle_home)-1);
 
1892
    break;
 
1893
  case 'C':
 
1894
    if (default_collation_name == compiled_default_collation_name)
 
1895
      default_collation_name= 0;
 
1896
    break;
 
1897
  case 'h':
 
1898
    strncpy(drizzle_real_data_home,argument, sizeof(drizzle_real_data_home)-1);
 
1899
    /* Correct pointer set by my_getopt (for embedded library) */
 
1900
    drizzle_data_home= drizzle_real_data_home;
 
1901
    drizzle_data_home_len= strlen(drizzle_data_home);
 
1902
    break;
 
1903
  case 'u':
 
1904
    if (!drizzled_user || !strcmp(drizzled_user, argument))
 
1905
      drizzled_user= argument;
 
1906
    else
 
1907
      errmsg_printf(ERRMSG_LVL_WARN, _("Ignoring user change to '%s' because the user was "
 
1908
                          "set to '%s' earlier on the command line\n"),
 
1909
                        argument, drizzled_user);
 
1910
    break;
 
1911
  case 'L':
 
1912
    strncpy(language, argument, sizeof(language)-1);
 
1913
    break;
 
1914
  case 'V':
 
1915
    print_version();
 
1916
    exit(0);
 
1917
  case 'W':
 
1918
    if (!argument)
 
1919
      global_system_variables.log_warnings++;
 
1920
    else if (argument == disabled_my_option)
 
1921
      global_system_variables.log_warnings= 0L;
 
1922
    else
 
1923
      global_system_variables.log_warnings= atoi(argument);
 
1924
    break;
 
1925
  case 'T':
 
1926
    if (argument)
 
1927
    {
 
1928
      test_flags.set((uint32_t) atoi(argument));
 
1929
    }
 
1930
    break;
 
1931
  case (int) OPT_WANT_CORE:
 
1932
    test_flags.set(TEST_CORE_ON_SIGNAL);
 
1933
    break;
 
1934
  case (int) OPT_SKIP_STACK_TRACE:
 
1935
    test_flags.set(TEST_NO_STACKTRACE);
 
1936
    break;
 
1937
  case (int) OPT_SKIP_SYMLINKS:
 
1938
    internal::my_use_symdir=0;
 
1939
    break;
 
1940
  case (int) OPT_BIND_ADDRESS:
 
1941
    {
 
1942
      struct addrinfo *res_lst, hints;
 
1943
 
 
1944
      memset(&hints, 0, sizeof(struct addrinfo));
 
1945
      hints.ai_socktype= SOCK_STREAM;
 
1946
      hints.ai_protocol= IPPROTO_TCP;
 
1947
 
 
1948
      if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0)
 
1949
      {
 
1950
          errmsg_printf(ERRMSG_LVL_ERROR, _("Can't start server: cannot resolve hostname!"));
 
1951
        exit(1);
 
1952
      }
 
1953
 
 
1954
      if (res_lst->ai_next)
 
1955
      {
 
1956
          errmsg_printf(ERRMSG_LVL_ERROR, _("Can't start server: bind-address refers to "
 
1957
                          "multiple interfaces!"));
 
1958
        exit(1);
 
1959
      }
 
1960
      freeaddrinfo(res_lst);
 
1961
    }
 
1962
    break;
 
1963
  case (int) OPT_PID_FILE:
 
1964
    strncpy(pidfile_name, argument, sizeof(pidfile_name)-1);
 
1965
    break;
 
1966
  case OPT_SERVER_ID:
 
1967
    break;
 
1968
  case OPT_TX_ISOLATION:
 
1969
    {
 
1970
      int type;
 
1971
      type= find_type_or_exit(argument, &tx_isolation_typelib, opt->name);
 
1972
      global_system_variables.tx_isolation= (type-1);
 
1973
      break;
 
1974
    }
 
1975
  case OPT_TC_HEURISTIC_RECOVER:
 
1976
    tc_heuristic_recover= find_type_or_exit(argument,
 
1977
                                            &tc_heuristic_recover_typelib,
 
1978
                                            opt->name);
 
1979
    break;
 
1980
  }
 
1981
 
 
1982
  return 0;
 
1983
}
 
1984
 
 
1985
static void option_error_reporter(enum loglevel level, const char *format, ...)
 
1986
{
 
1987
  va_list args;
 
1988
  va_start(args, format);
 
1989
 
 
1990
  /* Don't print warnings for --loose options during bootstrap */
 
1991
  if (level == ERROR_LEVEL || global_system_variables.log_warnings)
 
1992
  {
 
1993
    plugin::ErrorMessage::vprintf(current_session, ERROR_LEVEL, format, args);
 
1994
  }
 
1995
  va_end(args);
 
1996
}
 
1997
 
 
1998
 
 
1999
/**
 
2000
  @todo
 
2001
  - FIXME add EXIT_TOO_MANY_ARGUMENTS to "drizzled/error.h" and return that code?
 
2002
*/
 
2003
static void get_options(int *argc,char **argv)
 
2004
{
 
2005
  int ho_error;
 
2006
 
 
2007
  my_getopt_error_reporter= option_error_reporter;
 
2008
 
 
2009
  string progname(argv[0]);
 
2010
 
 
2011
  /* Skip unknown options so that they may be processed later by plugins */
 
2012
  my_getopt_skip_unknown= true;
 
2013
 
 
2014
  if ((ho_error= handle_options(argc, &argv, my_long_options,
 
2015
                                drizzled_get_one_option)))
 
2016
    exit(ho_error);
 
2017
  (*argc)++; /* add back one for the progname handle_options removes */
 
2018
             /* no need to do this for argv as we are discarding it. */
 
2019
 
 
2020
#if defined(HAVE_BROKEN_REALPATH)
 
2021
  internal::my_use_symdir=0;
 
2022
  internal::my_disable_symlinks=1;
 
2023
  have_symlink=SHOW_OPTION_NO;
 
2024
#else
 
2025
  if (!internal::my_use_symdir)
 
2026
  {
 
2027
    internal::my_disable_symlinks=1;
 
2028
    have_symlink=SHOW_OPTION_DISABLED;
 
2029
  }
 
2030
#endif
 
2031
  if (opt_debugging)
 
2032
  {
 
2033
    /* Allow break with SIGINT, no core or stack trace */
 
2034
    test_flags.set(TEST_SIGINT);
 
2035
    test_flags.set(TEST_NO_STACKTRACE);
 
2036
    test_flags.reset(TEST_CORE_ON_SIGNAL);
 
2037
  }
 
2038
 
 
2039
  if (drizzled_chroot)
 
2040
    set_root(drizzled_chroot);
 
2041
  fix_paths(progname);
 
2042
 
 
2043
  /*
 
2044
    Set some global variables from the global_system_variables
 
2045
    In most cases the global variables will not be used
 
2046
  */
 
2047
  internal::my_default_record_cache_size=global_system_variables.read_buff_size;
 
2048
}
 
2049
 
 
2050
 
 
2051
static const char *get_relative_path(const char *path)
 
2052
{
 
2053
  if (internal::test_if_hard_path(path) &&
 
2054
      (strncmp(path, PREFIX, strlen(PREFIX)) == 0) &&
 
2055
      strcmp(PREFIX,FN_ROOTDIR))
 
2056
  {
 
2057
    if (strlen(PREFIX) < strlen(path))
 
2058
      path+=(size_t) strlen(PREFIX);
 
2059
    while (*path == FN_LIBCHAR)
 
2060
      path++;
 
2061
  }
 
2062
  return path;
 
2063
}
 
2064
 
 
2065
 
 
2066
static void fix_paths(string &progname)
 
2067
{
 
2068
  char buff[FN_REFLEN],*pos,rp_buff[PATH_MAX];
 
2069
  internal::convert_dirname(drizzle_home,drizzle_home,NULL);
 
2070
  /* Resolve symlinks to allow 'drizzle_home' to be a relative symlink */
 
2071
#if defined(HAVE_BROKEN_REALPATH)
 
2072
   internal::my_load_path(drizzle_home, drizzle_home, NULL);
 
2073
#else
 
2074
  if (!realpath(drizzle_home,rp_buff))
 
2075
    internal::my_load_path(rp_buff, drizzle_home, NULL);
 
2076
  rp_buff[FN_REFLEN-1]= '\0';
 
2077
  strcpy(drizzle_home,rp_buff);
 
2078
  /* Ensure that drizzle_home ends in FN_LIBCHAR */
 
2079
  pos= strchr(drizzle_home, '\0');
 
2080
#endif
 
2081
  if (pos[-1] != FN_LIBCHAR)
 
2082
  {
 
2083
    pos[0]= FN_LIBCHAR;
 
2084
    pos[1]= 0;
 
2085
  }
 
2086
  internal::convert_dirname(drizzle_real_data_home,drizzle_real_data_home,NULL);
 
2087
  (void) internal::fn_format(buff, drizzle_real_data_home, "", "",
 
2088
                   (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
 
2089
  (void) internal::unpack_dirname(drizzle_unpacked_real_data_home, buff);
 
2090
  internal::convert_dirname(language,language,NULL);
 
2091
  (void) internal::my_load_path(drizzle_home, drizzle_home,""); // Resolve current dir
 
2092
  (void) internal::my_load_path(drizzle_real_data_home, drizzle_real_data_home,drizzle_home);
 
2093
  (void) internal::my_load_path(pidfile_name, pidfile_name,drizzle_real_data_home);
 
2094
 
 
2095
  if (opt_plugin_dir_ptr == NULL)
 
2096
  {
 
2097
    /* No plugin dir has been specified. Figure out where the plugins are */
 
2098
    if (progname[0] != FN_LIBCHAR)
 
2099
    {
 
2100
      /* We have a relative path and need to find the absolute */
 
2101
      char working_dir[FN_REFLEN];
 
2102
      char *working_dir_ptr= working_dir;
 
2103
      working_dir_ptr= getcwd(working_dir_ptr, FN_REFLEN);
 
2104
      string new_path(working_dir);
 
2105
      if (*(new_path.end()-1) != '/')
 
2106
        new_path.push_back('/');
 
2107
      if (progname[0] == '.' && progname[1] == '/')
 
2108
        new_path.append(progname.substr(2));
 
2109
      else
 
2110
        new_path.append(progname);
 
2111
      progname.swap(new_path);
 
2112
    }
 
2113
 
 
2114
    /* Now, trim off the exe name */
 
2115
    string progdir(progname.substr(0, progname.rfind(FN_LIBCHAR)+1));
 
2116
    if (progdir.rfind(".libs/") != string::npos)
 
2117
    {
 
2118
      progdir.assign(progdir.substr(0, progdir.rfind(".libs/")));
 
2119
    }
 
2120
    string testfile(progdir);
 
2121
    testfile.append("drizzled.o");
 
2122
    struct stat testfile_stat;
 
2123
    if (stat(testfile.c_str(), &testfile_stat))
 
2124
    {
 
2125
      /* drizzled.o doesn't exist - we are not in a source dir.
 
2126
       * Go on as usual
 
2127
       */
 
2128
      (void) internal::my_load_path(opt_plugin_dir, get_relative_path(PKGPLUGINDIR),
 
2129
                                          drizzle_home);
 
2130
    }
 
2131
    else
 
2132
    {
 
2133
      /* We are in a source dir! Plugin dir is ../plugin/.libs */
 
2134
      size_t last_libchar_pos= progdir.rfind(FN_LIBCHAR,progdir.size()-2)+1;
 
2135
      string source_plugindir(progdir.substr(0,last_libchar_pos));
 
2136
      source_plugindir.append("plugin/.libs");
 
2137
      (void) internal::my_load_path(opt_plugin_dir, source_plugindir.c_str(), "");
 
2138
    }
 
2139
  }
 
2140
  else
 
2141
  {
 
2142
    (void) internal::my_load_path(opt_plugin_dir, opt_plugin_dir_ptr, drizzle_home);
 
2143
  }
 
2144
  opt_plugin_dir_ptr= opt_plugin_dir;
 
2145
 
 
2146
  const char *sharedir= get_relative_path(PKGDATADIR);
 
2147
  if (internal::test_if_hard_path(sharedir))
 
2148
    strncpy(buff,sharedir,sizeof(buff)-1);
 
2149
  else
 
2150
  {
 
2151
    strcpy(buff, drizzle_home);
 
2152
    strncat(buff, sharedir, sizeof(buff)-strlen(drizzle_home)-1);
 
2153
  }
 
2154
  internal::convert_dirname(buff,buff,NULL);
 
2155
  (void) internal::my_load_path(language,language,buff);
 
2156
 
 
2157
  {
 
2158
    char *tmp_string;
 
2159
    struct stat buf;
 
2160
 
 
2161
    tmp_string= getenv("TMPDIR");
 
2162
 
 
2163
    if (opt_drizzle_tmpdir)
 
2164
      drizzle_tmpdir= strdup(opt_drizzle_tmpdir);
 
2165
    else if (tmp_string == NULL)
 
2166
      drizzle_tmpdir= strdup(P_tmpdir);
 
2167
    else
 
2168
      drizzle_tmpdir= strdup(tmp_string);
 
2169
 
 
2170
    assert(drizzle_tmpdir);
 
2171
 
 
2172
    if (stat(drizzle_tmpdir, &buf) || (S_ISDIR(buf.st_mode) == false))
 
2173
    {
 
2174
      exit(1);
 
2175
    }
 
2176
  }
 
2177
 
 
2178
  /*
 
2179
    Convert the secure-file-priv option to system format, allowing
 
2180
    a quick strcmp to check if read or write is in an allowed dir
 
2181
   */
 
2182
  if (opt_secure_file_priv)
 
2183
  {
 
2184
    internal::convert_dirname(buff, opt_secure_file_priv, NULL);
 
2185
    free(opt_secure_file_priv);
 
2186
    opt_secure_file_priv= strdup(buff);
 
2187
    if (opt_secure_file_priv == NULL)
 
2188
      exit(1);
 
2189
  }
 
2190
}
 
2191
 
 
2192
} /* namespace drizzled */
 
2193
 
 
2194
using namespace drizzled;
 
2195
 
 
2196
 
 
2197
static void init_signals(void)
 
2198
{
 
2199
  sigset_t set;
 
2200
  struct sigaction sa;
 
2201
 
 
2202
  if (!(test_flags.test(TEST_NO_STACKTRACE) || 
 
2203
        test_flags.test(TEST_CORE_ON_SIGNAL)))
 
2204
  {
 
2205
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
 
2206
    sigemptyset(&sa.sa_mask);
 
2207
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
 
2208
 
 
2209
    init_stacktrace();
 
2210
    sa.sa_handler=handle_segfault;
 
2211
    sigaction(SIGSEGV, &sa, NULL);
 
2212
    sigaction(SIGABRT, &sa, NULL);
 
2213
#ifdef SIGBUS
 
2214
    sigaction(SIGBUS, &sa, NULL);
 
2215
#endif
 
2216
    sigaction(SIGILL, &sa, NULL);
 
2217
    sigaction(SIGFPE, &sa, NULL);
 
2218
  }
 
2219
 
 
2220
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
 
2221
  {
 
2222
    /* Change limits so that we will get a core file */
 
2223
    struct rlimit rl;
 
2224
    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
 
2225
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
 
2226
        errmsg_printf(ERRMSG_LVL_WARN,
 
2227
                      _("setrlimit could not change the size of core files "
 
2228
                        "to 'infinity';  We may not be able to generate a "
 
2229
                        "core file on signals"));
 
2230
  }
 
2231
  (void) sigemptyset(&set);
 
2232
  my_sigset(SIGPIPE,SIG_IGN);
 
2233
  sigaddset(&set,SIGPIPE);
 
2234
#ifndef IGNORE_SIGHUP_SIGQUIT
 
2235
  sigaddset(&set,SIGQUIT);
 
2236
  sigaddset(&set,SIGHUP);
 
2237
#endif
 
2238
  sigaddset(&set,SIGTERM);
 
2239
 
 
2240
  /* Fix signals if blocked by parents (can happen on Mac OS X) */
 
2241
  sigemptyset(&sa.sa_mask);
 
2242
  sa.sa_flags = 0;
 
2243
  sa.sa_handler = print_signal_warning;
 
2244
  sigaction(SIGTERM, &sa, (struct sigaction*) 0);
 
2245
  sa.sa_flags = 0;
 
2246
  sa.sa_handler = print_signal_warning;
 
2247
  sigaction(SIGHUP, &sa, (struct sigaction*) 0);
 
2248
#ifdef SIGTSTP
 
2249
  sigaddset(&set,SIGTSTP);
 
2250
#endif
 
2251
  if (test_flags.test(TEST_SIGINT))
 
2252
  {
 
2253
    my_sigset(thr_kill_signal, end_thread_signal);
 
2254
    // May be SIGINT
 
2255
    sigdelset(&set, thr_kill_signal);
 
2256
  }
 
2257
  else
 
2258
    sigaddset(&set,SIGINT);
 
2259
  sigprocmask(SIG_SETMASK,&set,NULL);
 
2260
  pthread_sigmask(SIG_SETMASK,&set,NULL);
 
2261
  return;;
 
2262
}
 
2263
 
 
2264
int main(int argc, char **argv)
 
2265
{
 
2266
#if defined(ENABLE_NLS)
 
2267
# if defined(HAVE_LOCALE_H)
 
2268
  setlocale(LC_ALL, "");
 
2269
# endif
 
2270
  bindtextdomain("drizzle", LOCALEDIR);
 
2271
  textdomain("drizzle");
 
2272
#endif
 
2273
 
 
2274
  plugin::Registry &plugins= plugin::Registry::singleton();
 
2275
  plugin::Client *client;
 
2276
  Session *session;
 
2277
 
 
2278
  MY_INIT(argv[0]);             // init my_sys library & pthreads
 
2279
  /* nothing should come before this line ^^^ */
 
2280
 
 
2281
  /* Set signal used to kill Drizzle */
 
2282
#if defined(SIGUSR2)
 
2283
  thr_kill_signal= internal::thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
 
2284
#else
 
2285
  thr_kill_signal= SIGINT;
 
2286
#endif
 
2287
 
 
2288
  if (init_common_variables(DRIZZLE_CONFIG_NAME,
 
2289
                            argc, argv, load_default_groups))
 
2290
    unireg_abort(1);                            // Will do exit
 
2291
 
 
2292
  init_signals();
 
2293
 
 
2294
 
 
2295
  select_thread=pthread_self();
 
2296
  select_thread_in_use=1;
 
2297
 
 
2298
  if (chdir(drizzle_real_data_home) && !opt_help)
 
2299
  {
 
2300
    errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), drizzle_real_data_home);
 
2301
    unireg_abort(1);
 
2302
  }
 
2303
  drizzle_data_home= drizzle_data_home_buff;
 
2304
  drizzle_data_home[0]=FN_CURLIB;               // all paths are relative from here
 
2305
  drizzle_data_home[1]=0;
 
2306
  drizzle_data_home_len= 2;
 
2307
 
 
2308
  if ((user_info= check_user(drizzled_user)))
 
2309
  {
 
2310
    set_user(drizzled_user, user_info);
 
2311
  }
 
2312
 
 
2313
  if (server_id == 0)
 
2314
  {
 
2315
    server_id= 1;
 
2316
  }
 
2317
 
 
2318
  if (init_server_components(plugins))
 
2319
    unireg_abort(1);
 
2320
 
 
2321
  if (plugin::Listen::setup())
 
2322
    unireg_abort(1);
 
2323
 
 
2324
  /*
 
2325
    init signals & alarm
 
2326
    After this we can't quit by a simple unireg_abort
 
2327
  */
 
2328
  error_handler_hook= my_message_sql;
 
2329
 
 
2330
  assert(plugin::num_trx_monitored_objects > 0);
 
2331
  if (drizzle_rm_tmp_tables() ||
 
2332
      my_tz_init((Session *)0, default_tz_name))
 
2333
  {
 
2334
    abort_loop= true;
 
2335
    select_thread_in_use=0;
 
2336
    (void) pthread_kill(signal_thread, SIGTERM);
 
2337
 
 
2338
    (void) unlink(pidfile_name);        // Not needed anymore
 
2339
 
 
2340
    exit(1);
 
2341
  }
 
2342
 
 
2343
  init_status_vars();
 
2344
 
 
2345
  errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
 
2346
                PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
 
2347
 
 
2348
 
 
2349
  /* Listen for new connections and start new session for each connection
 
2350
     accepted. The listen.getClient() method will return NULL when the server
 
2351
     should be shutdown. */
 
2352
  while ((client= plugin::Listen::getClient()) != NULL)
 
2353
  {
 
2354
    if (!(session= new Session(client)))
 
2355
    {
 
2356
      delete client;
 
2357
      continue;
 
2358
    }
 
2359
 
 
2360
    /* If we error on creation we drop the connection and delete the session. */
 
2361
    if (session->schedule())
 
2362
      Session::unlink(session);
 
2363
  }
 
2364
 
 
2365
  /* (void) pthread_attr_destroy(&connection_attrib); */
 
2366
 
 
2367
 
 
2368
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
2369
  select_thread_in_use=0;                       // For close_connections
 
2370
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
2371
  (void) pthread_cond_broadcast(&COND_thread_count);
 
2372
 
 
2373
  /* Wait until cleanup is done */
 
2374
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
2375
  while (!ready_to_exit)
 
2376
    pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
 
2377
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
2378
 
 
2379
  clean_up(1);
 
2380
  plugin::Registry::shutdown();
 
2381
  clean_up_mutexes();
 
2382
  internal::my_end();
 
2383
  return 0;
 
2384
}
 
2385