drizzled.cc

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include "config.h"
00021 #include <drizzled/configmake.h>
00022 #include <drizzled/atomics.h>
00023 
00024 #include <netdb.h>
00025 #include <sys/types.h>
00026 #include <netinet/tcp.h>
00027 #include <netinet/in.h>
00028 #include <signal.h>
00029 #include <limits.h>
00030 
00031 #include "drizzled/internal/my_sys.h"
00032 #include "drizzled/internal/my_bit.h"
00033 #include <drizzled/my_hash.h>
00034 #include <drizzled/stacktrace.h>
00035 #include "drizzled/my_error.h"
00036 #include <drizzled/error.h>
00037 #include <drizzled/errmsg_print.h>
00038 #include <drizzled/tztime.h>
00039 #include <drizzled/sql_base.h>
00040 #include <drizzled/show.h>
00041 #include <drizzled/sql_parse.h>
00042 #include <drizzled/item/cmpfunc.h>
00043 #include <drizzled/session.h>
00044 #include <drizzled/item/create.h>
00045 #include <drizzled/unireg.h>
00046 #include "drizzled/temporal_format.h" /* For init_temporal_formats() */
00047 #include "drizzled/plugin/listen.h"
00048 #include "drizzled/plugin/error_message.h"
00049 #include "drizzled/plugin/client.h"
00050 #include "drizzled/plugin/scheduler.h"
00051 #include "drizzled/probes.h"
00052 #include "drizzled/session_list.h"
00053 #include "drizzled/charset.h"
00054 #include "plugin/myisam/myisam.h"
00055 
00056 #include <google/protobuf/stubs/common.h>
00057 
00058 #if TIME_WITH_SYS_TIME
00059 # include <sys/time.h>
00060 # include <time.h>
00061 #else
00062 # if HAVE_SYS_TIME_H
00063 #  include <sys/time.h>
00064 # else
00065 #  include <time.h>
00066 # endif
00067 #endif
00068 
00069 #ifdef HAVE_SYS_PRCTL_H
00070 #include <sys/prctl.h>
00071 #endif
00072 #include <sys/socket.h>
00073 
00074 #include <locale.h>
00075 
00076 #define mysqld_charset &my_charset_utf8_general_ci
00077 
00078 #ifdef HAVE_purify
00079 #define IF_PURIFY(A,B) (A)
00080 #else
00081 #define IF_PURIFY(A,B) (B)
00082 #endif
00083 
00084 #define MAX_MEM_TABLE_SIZE SIZE_MAX
00085 
00086 #include <errno.h>
00087 #include <sys/stat.h>
00088 #include "drizzled/my_getopt.h"
00089 #ifdef HAVE_SYSENT_H
00090 #include <sysent.h>
00091 #endif
00092 #include <pwd.h>        // For getpwent
00093 #include <grp.h>
00094 
00095 #include <sys/resource.h>
00096 
00097 #ifdef HAVE_SELECT_H
00098 #  include <select.h>
00099 #endif
00100 
00101 #ifdef HAVE_SYS_SELECT_H
00102 #include <sys/select.h>
00103 #endif
00104 
00105 #include <sys/utsname.h>
00106 
00107 #ifdef HAVE_SYS_MMAN_H
00108 #include <sys/mman.h>
00109 #endif
00110 
00111 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
00112 #include <ieeefp.h>
00113 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
00114 
00115 #ifdef HAVE_FPU_CONTROL_H
00116 #include <fpu_control.h>
00117 #endif
00118 
00119 #ifdef HAVE_SYS_FPU_H
00120 /* for IRIX to use set_fpc_csr() */
00121 #include <sys/fpu.h>
00122 #endif
00123 
00124 inline void setup_fpu()
00125 {
00126 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
00127   /*
00128      We can't handle floating point exceptions with threads, so disable
00129      this on freebsd.
00130      Don't fall for overflow, underflow,divide-by-zero or loss of precision
00131   */
00132 #if defined(__i386__)
00133   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
00134         FP_X_IMP));
00135 #else
00136   fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
00137               FP_X_IMP));
00138 #endif /* __i386__ */
00139 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
00140 
00141   /*
00142     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit for
00143     portable results of floating point operations
00144   */
00145 #if defined(__i386__) && defined(HAVE_FPU_CONTROL_H) && defined(_FPU_DOUBLE)
00146   fpu_control_t cw;
00147   _FPU_GETCW(cw);
00148   cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
00149   _FPU_SETCW(cw);
00150 #endif /* __i386__ && HAVE_FPU_CONTROL_H && _FPU_DOUBLE */
00151 }
00152 
00153 #include "drizzled/internal/my_pthread.h"     // For thr_setconcurency()
00154 
00155 #include <drizzled/gettext.h>
00156 
00157 #ifdef SOLARIS
00158 extern "C" int gethostname(char *name, int namelen);
00159 #endif
00160 
00161 using namespace std;
00162 using namespace drizzled;
00163 
00164 /* Constants */
00165 
00166 
00167 const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
00168 static const char *optimizer_switch_names[]=
00169 {
00170   "no_materialization", "no_semijoin",
00171   NULL
00172 };
00173 
00174 /* Corresponding defines are named OPTIMIZER_SWITCH_XXX */
00175 static const unsigned int optimizer_switch_names_len[]=
00176 {
00177   /*no_materialization*/          19,
00178   /*no_semijoin*/                 11
00179 };
00180 
00181 TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
00182                                     optimizer_switch_names,
00183                                     (unsigned int *)optimizer_switch_names_len };
00184 
00185 static const char *tc_heuristic_recover_names[]=
00186 {
00187   "COMMIT", "ROLLBACK", NULL
00188 };
00189 static TYPELIB tc_heuristic_recover_typelib=
00190 {
00191   array_elements(tc_heuristic_recover_names)-1,"",
00192   tc_heuristic_recover_names, NULL
00193 };
00194 
00195 const char *first_keyword= "first";
00196 const char * const DRIZZLE_CONFIG_NAME= "drizzled";
00197 #define GET_HA_ROWS GET_ULL
00198 
00199 const char *tx_isolation_names[] =
00200 { "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
00201   NULL};
00202 
00203 TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
00204                                tx_isolation_names, NULL};
00205 
00206 /*
00207   Used with --help for detailed option
00208 */
00209 static bool opt_help= false;
00210 static bool opt_help_extended= false;
00211 
00212 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
00213 {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
00214  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
00215  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
00216  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
00217  {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
00218 
00219 /* static variables */
00220 
00221 static bool volatile select_thread_in_use;
00222 static bool volatile ready_to_exit;
00223 static bool opt_debugging= 0;
00224 static uint32_t wake_thread;
00225 static uint32_t killed_threads;
00226 static char *drizzled_user, *drizzled_chroot;
00227 static char *language_ptr;
00228 static const char *default_character_set_name;
00229 static const char *character_set_filesystem_name;
00230 static char *lc_time_names_name;
00231 static char *default_collation_name;
00232 static char *default_storage_engine_str;
00233 static const char *compiled_default_collation_name= "utf8_general_ci";
00234 
00235 /* Global variables */
00236 
00237 bool locked_in_memory;
00238 bool volatile abort_loop;
00239 bool volatile shutdown_in_progress;
00240 uint32_t max_used_connections;
00241 const string opt_scheduler_default("multi_thread");
00242 char *opt_scheduler= NULL;
00243 
00244 size_t my_thread_stack_size= 65536;
00245 
00246 /*
00247   Legacy global plugin::StorageEngine. These will be removed (please do not add more).
00248 */
00249 plugin::StorageEngine *heap_engine;
00250 plugin::StorageEngine *myisam_engine;
00251 
00252 char* opt_secure_file_priv= 0;
00253 
00254 static bool calling_initgroups= false; 
00256 uint32_t drizzled_bind_timeout;
00257 std::bitset<12> test_flags;
00258 uint32_t dropping_tables, ha_open_options;
00259 uint32_t tc_heuristic_recover= 0;
00260 uint64_t session_startup_options;
00261 uint32_t back_log;
00262 uint32_t server_id;
00263 uint64_t table_cache_size;
00264 size_t table_def_size;
00265 uint64_t aborted_threads;
00266 uint64_t aborted_connects;
00267 uint64_t max_connect_errors;
00268 uint32_t global_thread_id= 1UL;
00269 pid_t current_pid;
00270 
00271 extern const double log_10[309];
00272 
00273 const double log_10[] = {
00274   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
00275   1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
00276   1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
00277   1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
00278   1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
00279   1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
00280   1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
00281   1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
00282   1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
00283   1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
00284   1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
00285   1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
00286   1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
00287   1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
00288   1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
00289   1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
00290   1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
00291   1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
00292   1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
00293   1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
00294   1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
00295   1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
00296   1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
00297   1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
00298   1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
00299   1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
00300   1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
00301   1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
00302   1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
00303   1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
00304   1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
00305 };
00306 
00307 time_t server_start_time;
00308 time_t flush_status_time;
00309 
00310 char drizzle_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
00311 char *default_tz_name;
00312 char glob_hostname[FN_REFLEN];
00313 char drizzle_real_data_home[FN_REFLEN],
00314      language[FN_REFLEN], 
00315      *opt_tc_log_file;
00316 char drizzle_unpacked_real_data_home[FN_REFLEN];
00317 const key_map key_map_empty(0);
00318 key_map key_map_full(0);                        // Will be initialized later
00319 
00320 uint32_t drizzle_data_home_len;
00321 char drizzle_data_home_buff[2], *drizzle_data_home=drizzle_real_data_home;
00322 char *drizzle_tmpdir= NULL;
00323 char *opt_drizzle_tmpdir= NULL;
00324 
00326 const char *in_left_expr_name= "<left expr>";
00328 const char *in_additional_cond= "<IN COND>";
00329 const char *in_having_cond= "<IN HAVING>";
00330 
00331 my_decimal decimal_zero;
00332 /* classes for comparation parsing/processing */
00333 
00334 FILE *stderror_file=0;
00335 
00336 struct system_variables global_system_variables;
00337 struct system_variables max_system_variables;
00338 struct system_status_var global_status_var;
00339 
00340 const CHARSET_INFO *system_charset_info, *files_charset_info ;
00341 const CHARSET_INFO *table_alias_charset;
00342 const CHARSET_INFO *character_set_filesystem;
00343 
00344 MY_LOCALE *my_default_lc_time_names;
00345 
00346 SHOW_COMP_OPTION have_symlink;
00347 
00348 /* Thread specific variables */
00349 
00350 pthread_key_t THR_Mem_root;
00351 pthread_key_t THR_Session;
00352 pthread_mutex_t LOCK_create_db;
00353 pthread_mutex_t LOCK_open;
00354 pthread_mutex_t LOCK_thread_count;
00355 pthread_mutex_t LOCK_status;
00356 pthread_mutex_t LOCK_global_read_lock;
00357 pthread_mutex_t LOCK_global_system_variables;
00358 
00359 pthread_rwlock_t  LOCK_system_variables_hash;
00360 pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock;
00361 pthread_t signal_thread;
00362 pthread_cond_t  COND_server_end;
00363 
00364 /* Static variables */
00365 
00366 static bool segfaulted;
00367 #ifdef HAVE_STACK_TRACE_ON_SEGV
00368 static bool opt_do_pstack;
00369 #endif /* HAVE_STACK_TRACE_ON_SEGV */
00370 int cleanup_done;
00371 static char *drizzle_home_ptr, *pidfile_name_ptr;
00372 static int defaults_argc;
00373 static char **defaults_argv;
00374 
00375 struct passwd *user_info;
00376 static pthread_t select_thread;
00377 static uint32_t thr_kill_signal;
00378 
00383 drizzled::atomic<uint32_t> connection_count;
00384 
00388 uint64_t refresh_version;  /* Increments on each reload */
00389 
00390 /* Function declarations */
00391 bool drizzle_rm_tmp_tables();
00392 
00393 extern "C" pthread_handler_t signal_hand(void *arg);
00394 static void drizzle_init_variables(void);
00395 static void get_options(int *argc,char **argv);
00396 extern "C" bool drizzled_get_one_option(int, const struct my_option *, char *);
00397 static int init_thread_environment();
00398 static const char *get_relative_path(const char *path);
00399 static void fix_paths(string &progname);
00400 extern "C" pthread_handler_t handle_slave(void *arg);
00401 static void clean_up(bool print_message);
00402 
00403 static void usage(void);
00404 static void clean_up_mutexes(void);
00405 void close_connections(void);
00406  
00407 /****************************************************************************
00408 ** Code to end drizzled
00409 ****************************************************************************/
00410 
00411 void close_connections(void)
00412 {
00413   /* Abort listening to new connections */
00414   plugin::Listen::shutdown();
00415 
00416   /* kill connection thread */
00417   (void) pthread_mutex_lock(&LOCK_thread_count);
00418 
00419   while (select_thread_in_use)
00420   {
00421     struct timespec abstime;
00422     int error;
00423 
00424     set_timespec(abstime, 2);
00425     for (uint32_t tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
00426     {
00427       error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count, &abstime);
00428       if (error != EINTR)
00429         break;
00430     }
00431   }
00432   (void) pthread_mutex_unlock(&LOCK_thread_count);
00433 
00434 
00435   /*
00436     First signal all threads that it's time to die
00437     This will give the threads some time to gracefully abort their
00438     statements and inform their clients that the server is about to die.
00439   */
00440 
00441   Session *tmp;
00442 
00443   (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
00444 
00445   for( vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
00446   {
00447     tmp= *it;
00448     tmp->killed= Session::KILL_CONNECTION;
00449     tmp->scheduler->killSession(tmp);
00450     DRIZZLE_CONNECTION_DONE(tmp->thread_id);
00451     if (tmp->mysys_var)
00452     {
00453       tmp->mysys_var->abort=1;
00454       pthread_mutex_lock(&tmp->mysys_var->mutex);
00455       if (tmp->mysys_var->current_cond)
00456       {
00457         pthread_mutex_lock(tmp->mysys_var->current_mutex);
00458         pthread_cond_broadcast(tmp->mysys_var->current_cond);
00459         pthread_mutex_unlock(tmp->mysys_var->current_mutex);
00460       }
00461       pthread_mutex_unlock(&tmp->mysys_var->mutex);
00462     }
00463   }
00464   (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
00465 
00466   if (connection_count)
00467     sleep(2);                                   // Give threads time to die
00468 
00469   /*
00470     Force remaining threads to die by closing the connection to the client
00471     This will ensure that threads that are waiting for a command from the
00472     client on a blocking read call are aborted.
00473   */
00474   for (;;)
00475   {
00476     (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
00477     if (getSessionList().empty())
00478     {
00479       (void) pthread_mutex_unlock(&LOCK_thread_count);
00480       break;
00481     }
00482     tmp= getSessionList().front();
00483     /* Close before unlock, avoiding crash. See LP bug#436685 */
00484     tmp->client->close();
00485     (void) pthread_mutex_unlock(&LOCK_thread_count);
00486   }
00487 }
00488 
00489 extern "C" void print_signal_warning(int sig);
00490 
00491 extern "C" void print_signal_warning(int sig)
00492 {
00493   if (global_system_variables.log_warnings)
00494     errmsg_printf(ERRMSG_LVL_WARN, _("Got signal %d from thread %"PRIu64),
00495                   sig, global_thread_id);
00496 #ifndef HAVE_BSD_SIGNALS
00497   my_sigset(sig,print_signal_warning);    /* int. thread system calls */
00498 #endif
00499   if (sig == SIGALRM)
00500     alarm(2);         /* reschedule alarm */
00501 }
00502 
00513 void unireg_end(void)
00514 {
00515   clean_up(1);
00516   my_thread_end();
00517 #if defined(SIGNALS_DONT_BREAK_READ)
00518   exit(0);
00519 #else
00520   pthread_exit(0);        // Exit is in main thread
00521 #endif
00522 }
00523 
00524 
00525 void unireg_abort(int exit_code)
00526 {
00527 
00528   if (exit_code)
00529     errmsg_printf(ERRMSG_LVL_ERROR, _("Aborting\n"));
00530   else if (opt_help || opt_help_extended)
00531     usage();
00532   clean_up(!opt_help && (exit_code));
00533   clean_up_mutexes();
00534   my_end();
00535   exit(exit_code);
00536 }
00537 
00538 
00539 static void clean_up(bool print_message)
00540 {
00541   if (cleanup_done++)
00542     return;
00543 
00544   table_cache_free();
00545   TableShare::cacheStop();
00546   set_var_free();
00547   free_charsets();
00548   ha_end();
00549   plugin::Registry &plugins= plugin::Registry::singleton();
00550   plugin_shutdown(plugins);
00551   xid_cache_free();
00552   free_status_vars();
00553   if (defaults_argv)
00554     free_defaults(defaults_argv);
00555   free(drizzle_tmpdir);
00556   if (opt_secure_file_priv)
00557     free(opt_secure_file_priv);
00558 
00559   deinit_temporal_formats();
00560 
00561 #if GOOGLE_PROTOBUF_VERSION >= 2001000
00562   google::protobuf::ShutdownProtobufLibrary();
00563 #endif
00564 
00565   (void) unlink(pidfile_name);  // This may not always exist
00566 
00567   if (print_message && server_start_time)
00568     errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_SHUTDOWN_COMPLETE)),my_progname);
00569   /* Returns NULL on globerrs, we don't want to try to free that */
00570   //void *freeme=
00571   (void *)my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST);
00572   // TODO!!!! EPIC FAIL!!!! This sefaults if uncommented.
00573 /*  if (freeme != NULL)
00574     free(freeme);  */
00575   (void) pthread_mutex_lock(&LOCK_thread_count);
00576   ready_to_exit=1;
00577   /* do the broadcast inside the lock to ensure that my_end() is not called */
00578   (void) pthread_cond_broadcast(&COND_server_end);
00579   (void) pthread_mutex_unlock(&LOCK_thread_count);
00580 
00581   /*
00582     The following lines may never be executed as the main thread may have
00583     killed us
00584   */
00585 } /* clean_up */
00586 
00587 
00588 static void clean_up_mutexes()
00589 {
00590   (void) pthread_mutex_destroy(&LOCK_create_db);
00591   (void) pthread_mutex_destroy(&LOCK_open);
00592   (void) pthread_mutex_destroy(&LOCK_thread_count);
00593   (void) pthread_mutex_destroy(&LOCK_status);
00594   (void) pthread_mutex_destroy(&LOCK_global_system_variables);
00595   (void) pthread_rwlock_destroy(&LOCK_system_variables_hash);
00596   (void) pthread_mutex_destroy(&LOCK_global_read_lock);
00597   (void) pthread_cond_destroy(&COND_thread_count);
00598   (void) pthread_cond_destroy(&COND_server_end);
00599   (void) pthread_cond_destroy(&COND_refresh);
00600   (void) pthread_cond_destroy(&COND_global_read_lock);
00601 }
00602 
00603 
00604 /* Change to run as another user if started with --user */
00605 
00606 static struct passwd *check_user(const char *user)
00607 {
00608   struct passwd *tmp_user_info;
00609   uid_t user_id= geteuid();
00610 
00611   // Don't bother if we aren't superuser
00612   if (user_id)
00613   {
00614     if (user)
00615     {
00616       /* Don't give a warning, if real user is same as given with --user */
00617       tmp_user_info= getpwnam(user);
00618       if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
00619           global_system_variables.log_warnings)
00620             errmsg_printf(ERRMSG_LVL_WARN, _("One can only use the --user switch "
00621                             "if running as root\n"));
00622     }
00623     return NULL;
00624   }
00625   if (!user)
00626   {
00627       errmsg_printf(ERRMSG_LVL_ERROR, _("Fatal error: Please read \"Security\" section of "
00628                       "the manual to find out how to run drizzled as root!\n"));
00629     unireg_abort(1);
00630   }
00631   if (!strcmp(user,"root"))
00632     return NULL;                        // Avoid problem with dynamic libraries
00633 
00634   if (!(tmp_user_info= getpwnam(user)))
00635   {
00636     // Allow a numeric uid to be used
00637     const char *pos;
00638     for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
00639     if (*pos)                                   // Not numeric id
00640       goto err;
00641     if (!(tmp_user_info= getpwuid(atoi(user))))
00642       goto err;
00643   }
00644   return tmp_user_info;
00645 
00646 err:
00647   errmsg_printf(ERRMSG_LVL_ERROR, _("Fatal error: Can't change to run as user '%s' ;  "
00648                     "Please check that the user exists!\n"),user);
00649   unireg_abort(1);
00650 
00651 #ifdef PR_SET_DUMPABLE
00652   if (test_flags.test(TEST_CORE_ON_SIGNAL))
00653   {
00654     /* inform kernel that process is dumpable */
00655     (void) prctl(PR_SET_DUMPABLE, 1);
00656   }
00657 #endif
00658 
00659 /* Sun Studio 5.10 doesn't like this line.  5.9 requires it */
00660 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
00661   return NULL;
00662 #endif
00663 
00664 }
00665 
00666 static void set_user(const char *user, struct passwd *user_info_arg)
00667 {
00668   assert(user_info_arg != 0);
00669   /*
00670     We can get a SIGSEGV when calling initgroups() on some systems when NSS
00671     is configured to use LDAP and the server is statically linked.  We set
00672     calling_initgroups as a flag to the SIGSEGV handler that is then used to
00673     output a specific message to help the user resolve this problem.
00674   */
00675   calling_initgroups= true;
00676   initgroups((char*) user, user_info_arg->pw_gid);
00677   calling_initgroups= false;
00678   if (setgid(user_info_arg->pw_gid) == -1)
00679   {
00680     sql_perror("setgid");
00681     unireg_abort(1);
00682   }
00683   if (setuid(user_info_arg->pw_uid) == -1)
00684   {
00685     sql_perror("setuid");
00686     unireg_abort(1);
00687   }
00688 }
00689 
00690 
00691 static void set_effective_user(struct passwd *user_info_arg)
00692 {
00693   assert(user_info_arg != 0);
00694   if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
00695   {
00696     sql_perror("setregid");
00697     unireg_abort(1);
00698   }
00699   if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
00700   {
00701     sql_perror("setreuid");
00702     unireg_abort(1);
00703   }
00704 }
00705 
00706 
00708 static void set_root(const char *path)
00709 {
00710   if ((chroot(path) == -1) || !chdir("/"))
00711   {
00712     sql_perror("chroot");
00713     unireg_abort(1);
00714   }
00715 }
00716 
00717 extern "C" void end_thread_signal(int );
00718 
00720 extern "C" void end_thread_signal(int )
00721 {
00722   Session *session=current_session;
00723   if (session)
00724   {
00725     statistic_increment(killed_threads, &LOCK_status);
00726     session->scheduler->killSessionNow(session);
00727     DRIZZLE_CONNECTION_DONE(session->thread_id);
00728   }
00729   return;
00730 }
00731 
00732 
00733 /*
00734   Unlink session from global list of available connections and free session
00735 
00736   SYNOPSIS
00737     Session::unlink()
00738     session    Thread handler
00739 
00740   NOTES
00741     LOCK_thread_count is locked and left locked
00742 */
00743 
00744 void Session::unlink(Session *session)
00745 {
00746   connection_count.decrement();
00747 
00748   session->cleanup();
00749 
00750   (void) pthread_mutex_lock(&LOCK_thread_count);
00751   pthread_mutex_lock(&session->LOCK_delete);
00752 
00753   getSessionList().erase(remove(getSessionList().begin(),
00754                          getSessionList().end(),
00755                          session));
00756 
00757   delete session;
00758   (void) pthread_mutex_unlock(&LOCK_thread_count);
00759 
00760   return;
00761 }
00762 
00763 
00764 #ifdef THREAD_SPECIFIC_SIGPIPE
00765 
00770 extern "C" void abort_thread(int )
00771 {
00772   Session *session=current_session;
00773   if (session)
00774     session->killed= Session::KILL_CONNECTION;
00775   return;;
00776 }
00777 #endif
00778 
00779 #if defined(BACKTRACE_DEMANGLE)
00780 #include <cxxabi.h>
00781 extern "C" char *my_demangle(const char *mangled_name, int *status)
00782 {
00783   return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
00784 }
00785 #endif
00786 
00787 extern "C" void handle_segfault(int sig);
00788 
00789 extern "C" void handle_segfault(int sig)
00790 {
00791   time_t curr_time;
00792   struct tm tm;
00793 
00794   /*
00795     Strictly speaking, one needs a mutex here
00796     but since we have got SIGSEGV already, things are a mess
00797     so not having the mutex is not as bad as possibly using a buggy
00798     mutex - so we keep things simple
00799   */
00800   if (segfaulted)
00801   {
00802     fprintf(stderr, _("Fatal signal %d while backtracing\n"), sig);
00803     exit(1);
00804   }
00805 
00806   segfaulted = 1;
00807 
00808   curr_time= time(NULL);
00809   if(curr_time == (time_t)-1)
00810   {
00811     fprintf(stderr, "Fetal: time() call failed\n");
00812     exit(1);
00813   }
00814 
00815   localtime_r(&curr_time, &tm);
00816   
00817   fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d - drizzled got signal %d;\n"
00818           "This could be because you hit a bug. It is also possible that "
00819           "this binary\n or one of the libraries it was linked against is "
00820           "corrupt, improperly built,\n or misconfigured. This error can "
00821           "also be caused by malfunctioning hardware.\n",
00822           tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
00823           tm.tm_hour, tm.tm_min, tm.tm_sec,
00824           sig);
00825   fprintf(stderr, _("We will try our best to scrape up some info that "
00826                     "will hopefully help diagnose\n"
00827                     "the problem, but since we have already crashed, "
00828                     "something is definitely wrong\nand this may fail.\n\n"));
00829   fprintf(stderr, "key_buffer_size=%u\n",
00830           (uint32_t) dflt_key_cache->key_cache_mem_size);
00831   fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
00832   fprintf(stderr, "max_used_connections=%u\n", max_used_connections);
00833   fprintf(stderr, "connection_count=%u\n", uint32_t(connection_count));
00834   fprintf(stderr, _("It is possible that drizzled could use up to \n"
00835                     "key_buffer_size + (read_buffer_size + "
00836                     "sort_buffer_size)*thread_count\n"
00837                     "bytes of memory\n"
00838                     "Hope that's ok; if not, decrease some variables in the "
00839                     "equation.\n\n"));
00840 
00841 #ifdef HAVE_STACKTRACE
00842   Session *session= current_session;
00843 
00844   if (! (test_flags.test(TEST_NO_STACKTRACE)))
00845   {
00846     fprintf(stderr,"session: 0x%lx\n",(long) session);
00847     fprintf(stderr,_("Attempting backtrace. You can use the following "
00848                      "information to find out\n"
00849                      "where drizzled died. If you see no messages after this, "
00850                      "something went\n"
00851                      "terribly wrong...\n"));
00852     print_stacktrace(session ? (unsigned char*) session->thread_stack : (unsigned char*) 0,
00853                      my_thread_stack_size);
00854   }
00855   if (session)
00856   {
00857     const char *kreason= "UNKNOWN";
00858     switch (session->killed) {
00859     case Session::NOT_KILLED:
00860       kreason= "NOT_KILLED";
00861       break;
00862     case Session::KILL_BAD_DATA:
00863       kreason= "KILL_BAD_DATA";
00864       break;
00865     case Session::KILL_CONNECTION:
00866       kreason= "KILL_CONNECTION";
00867       break;
00868     case Session::KILL_QUERY:
00869       kreason= "KILL_QUERY";
00870       break;
00871     case Session::KILLED_NO_VALUE:
00872       kreason= "KILLED_NO_VALUE";
00873       break;
00874     }
00875     fprintf(stderr, _("Trying to get some variables.\n"
00876                       "Some pointers may be invalid and cause the "
00877                       "dump to abort...\n"));
00878     safe_print_str("session->query", session->query, 1024);
00879     fprintf(stderr, "session->thread_id=%"PRIu32"\n", (uint32_t) session->thread_id);
00880     fprintf(stderr, "session->killed=%s\n", kreason);
00881   }
00882   fflush(stderr);
00883 #endif /* HAVE_STACKTRACE */
00884 
00885   if (calling_initgroups)
00886     fprintf(stderr, _("\nThis crash occurred while the server was calling "
00887                       "initgroups(). This is\n"
00888                       "often due to the use of a drizzled that is statically "
00889                       "linked against glibc\n"
00890                       "and configured to use LDAP in /etc/nsswitch.conf. "
00891                       "You will need to either\n"
00892                       "upgrade to a version of glibc that does not have this "
00893                       "problem (2.3.4 or\n"
00894                       "later when used with nscd), disable LDAP in your "
00895                       "nsswitch.conf, or use a\n"
00896                       "drizzled that is not statically linked.\n"));
00897 
00898   if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
00899     fprintf(stderr,
00900             _("\nYou are running a statically-linked LinuxThreads binary "
00901               "on an NPTL system.\n"
00902               "This can result in crashes on some distributions due "
00903               "to LT/NPTL conflicts.\n"
00904               "You should either build a dynamically-linked binary, or force "
00905               "LinuxThreads\n"
00906               "to be used with the LD_ASSUME_KERNEL environment variable. "
00907               "Please consult\n"
00908               "the documentation for your distribution on how to do that.\n"));
00909 
00910   if (locked_in_memory)
00911   {
00912     fprintf(stderr,
00913             _("\nThe '--memlock' argument, which was enabled, uses system "
00914               "calls that are\n"
00915               "unreliable and unstable on some operating systems and "
00916               "operating-system\n"
00917               "versions (notably, some versions of Linux).  "
00918               "This crash could be due to use\n"
00919               "of those buggy OS calls.  You should consider whether you "
00920               "really need the\n"
00921               "'--memlock' parameter and/or consult the OS "
00922               "distributor about 'mlockall'\n bugs.\n"));
00923   }
00924 
00925 #ifdef HAVE_WRITE_CORE
00926   if (test_flags.test(TEST_CORE_ON_SIGNAL))
00927   {
00928     fprintf(stderr, _("Writing a core file\n"));
00929     fflush(stderr);
00930     write_core(sig);
00931   }
00932 #endif
00933 
00934   exit(1);
00935 }
00936 
00937 #ifndef SA_RESETHAND
00938 #define SA_RESETHAND 0
00939 #endif
00940 #ifndef SA_NODEFER
00941 #define SA_NODEFER 0
00942 #endif
00943 
00944 static void init_signals(void)
00945 {
00946   sigset_t set;
00947   struct sigaction sa;
00948 
00949   if (!(test_flags.test(TEST_NO_STACKTRACE) || 
00950         test_flags.test(TEST_CORE_ON_SIGNAL)))
00951   {
00952     sa.sa_flags = SA_RESETHAND | SA_NODEFER;
00953     sigemptyset(&sa.sa_mask);
00954     sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
00955 
00956     init_stacktrace();
00957     sa.sa_handler=handle_segfault;
00958     sigaction(SIGSEGV, &sa, NULL);
00959     sigaction(SIGABRT, &sa, NULL);
00960 #ifdef SIGBUS
00961     sigaction(SIGBUS, &sa, NULL);
00962 #endif
00963     sigaction(SIGILL, &sa, NULL);
00964     sigaction(SIGFPE, &sa, NULL);
00965   }
00966 
00967   if (test_flags.test(TEST_CORE_ON_SIGNAL))
00968   {
00969     /* Change limits so that we will get a core file */
00970     struct rlimit rl;
00971     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
00972     if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
00973         errmsg_printf(ERRMSG_LVL_WARN,
00974                       _("setrlimit could not change the size of core files "
00975                         "to 'infinity';  We may not be able to generate a "
00976                         "core file on signals"));
00977   }
00978   (void) sigemptyset(&set);
00979   my_sigset(SIGPIPE,SIG_IGN);
00980   sigaddset(&set,SIGPIPE);
00981 #ifndef IGNORE_SIGHUP_SIGQUIT
00982   sigaddset(&set,SIGQUIT);
00983   sigaddset(&set,SIGHUP);
00984 #endif
00985   sigaddset(&set,SIGTERM);
00986 
00987   /* Fix signals if blocked by parents (can happen on Mac OS X) */
00988   sigemptyset(&sa.sa_mask);
00989   sa.sa_flags = 0;
00990   sa.sa_handler = print_signal_warning;
00991   sigaction(SIGTERM, &sa, (struct sigaction*) 0);
00992   sa.sa_flags = 0;
00993   sa.sa_handler = print_signal_warning;
00994   sigaction(SIGHUP, &sa, (struct sigaction*) 0);
00995 #ifdef SIGTSTP
00996   sigaddset(&set,SIGTSTP);
00997 #endif
00998   if (test_flags.test(TEST_SIGINT))
00999   {
01000     my_sigset(thr_kill_signal, end_thread_signal);
01001     // May be SIGINT
01002     sigdelset(&set, thr_kill_signal);
01003   }
01004   else
01005     sigaddset(&set,SIGINT);
01006   sigprocmask(SIG_SETMASK,&set,NULL);
01007   pthread_sigmask(SIG_SETMASK,&set,NULL);
01008   return;;
01009 }
01010 
01011 void my_message_sql(uint32_t error, const char *str, myf MyFlags);
01012 
01017 void my_message_sql(uint32_t error, const char *str, myf MyFlags)
01018 {
01019   Session *session;
01020   /*
01021     Put here following assertion when situation with EE_* error codes
01022     will be fixed
01023   */
01024   if ((session= current_session))
01025   {
01026     if (MyFlags & ME_FATALERROR)
01027       session->is_fatal_error= 1;
01028 
01029     /*
01030       TODO: There are two exceptions mechanism (Session and sp_rcontext),
01031       this could be improved by having a common stack of handlers.
01032     */
01033     if (session->handle_error(error, str,
01034                           DRIZZLE_ERROR::WARN_LEVEL_ERROR))
01035       return;;
01036 
01037     /*
01038       session->lex->current_select == 0 if lex structure is not inited
01039       (not query command (COM_QUERY))
01040     */
01041     if (! (session->lex->current_select &&
01042         session->lex->current_select->no_error && !session->is_fatal_error))
01043     {
01044       if (! session->main_da.is_error())            // Return only first message
01045       {
01046         if (error == 0)
01047           error= ER_UNKNOWN_ERROR;
01048         if (str == NULL)
01049           str= ER(error);
01050         session->main_da.set_error_status(error, str);
01051       }
01052     }
01053 
01054     if (!session->no_warnings_for_error && !session->is_fatal_error)
01055     {
01056       /*
01057         Suppress infinite recursion if there a memory allocation error
01058         inside push_warning.
01059       */
01060       session->no_warnings_for_error= true;
01061       push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
01062       session->no_warnings_for_error= false;
01063     }
01064   }
01065   if (!session || MyFlags & ME_NOREFRESH)
01066     errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",my_progname,str);
01067 }
01068 
01069 
01070 static const char *load_default_groups[]= {
01071 DRIZZLE_CONFIG_NAME, "server", 0, 0};
01072 
01073 static int show_starttime(SHOW_VAR *var, char *buff)
01074 {
01075   var->type= SHOW_LONG;
01076   var->value= buff;
01077   *((long *)buff)= (long) (time(NULL) - server_start_time);
01078   return 0;
01079 }
01080 
01081 static int show_flushstatustime(SHOW_VAR *var, char *buff)
01082 {
01083   var->type= SHOW_LONG;
01084   var->value= buff;
01085   *((long *)buff)= (long) (time(NULL) - flush_status_time);
01086   return 0;
01087 }
01088 
01089 static int show_open_tables(SHOW_VAR *var, char *buff)
01090 {
01091   var->type= SHOW_LONG;
01092   var->value= buff;
01093   *((long *)buff)= (long)cached_open_tables();
01094   return 0;
01095 }
01096 
01097 static int show_table_definitions(SHOW_VAR *var, char *buff)
01098 {
01099   var->type= SHOW_LONG;
01100   var->value= buff;
01101   *((long *)buff)= (long)cached_table_definitions();
01102   return 0;
01103 }
01104 
01105 static st_show_var_func_container
01106 show_open_tables_cont= { &show_open_tables };
01107 static st_show_var_func_container
01108 show_table_definitions_cont= { &show_table_definitions };
01109 static st_show_var_func_container
01110 show_starttime_cont= { &show_starttime };
01111 static st_show_var_func_container
01112 show_flushstatustime_cont= { &show_flushstatustime };
01113 
01114 /*
01115   Variables shown by SHOW STATUS in alphabetical order
01116 */
01117 static SHOW_VAR com_status_vars[]= {
01118   {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
01119   {"alter_db",             (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
01120   {"alter_table",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
01121   {"analyze",              (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
01122   {"begin",                (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
01123   {"change_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
01124   {"check",                (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CHECK]), SHOW_LONG_STATUS},
01125   {"checksum",             (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
01126   {"commit",               (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
01127   {"create_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
01128   {"create_index",         (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
01129   {"create_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
01130   {"delete",               (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_DELETE]), SHOW_LONG_STATUS},
01131   {"drop_db",              (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
01132   {"drop_index",           (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
01133   {"drop_table",           (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
01134   {"empty_query",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
01135   {"flush",                (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
01136   {"insert",               (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_INSERT]), SHOW_LONG_STATUS},
01137   {"insert_select",        (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
01138   {"kill",                 (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_KILL]), SHOW_LONG_STATUS},
01139   {"load",                 (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_LOAD]), SHOW_LONG_STATUS},
01140   {"release_savepoint",    (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
01141   {"rename_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
01142   {"replace",              (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
01143   {"replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
01144   {"rollback",             (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
01145   {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
01146   {"savepoint",            (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
01147   {"select",               (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SELECT]), SHOW_LONG_STATUS},
01148   {"set_option",           (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
01149   {"show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
01150   {"show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
01151   {"show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
01152   {"show_engine_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
01153   {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
01154   {"show_fields",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
01155   {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
01156   {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
01157   {"show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
01158   {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
01159   {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
01160   {"show_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
01161   {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
01162   {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
01163   {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
01164   {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
01165   {"update",               (char*) offsetof(STATUS_VAR, com_stat[(uint32_t) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
01166   {NULL, NULL, SHOW_LONGLONG}
01167 };
01168 
01169 static SHOW_VAR status_vars[]= {
01170   {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONGLONG},
01171   {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONGLONG},
01172   {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
01173   {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
01174   {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
01175   {"Connections",              (char*) &global_thread_id, SHOW_INT_NOFLUSH},
01176   {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
01177   {"Created_tmp_files",        (char*) &my_tmp_file_created,SHOW_INT},
01178   {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
01179   {"Flush_commands",           (char*) &refresh_version,    SHOW_INT_NOFLUSH},
01180   {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
01181   {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
01182   {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),  SHOW_LONG_STATUS},
01183   {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
01184   {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
01185   {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
01186   {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
01187   {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
01188   {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
01189   {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
01190   {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
01191   {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
01192   {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
01193   {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
01194   {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
01195   {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
01196   {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
01197   {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
01198   {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
01199   {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
01200   {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
01201   {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
01202   {"Max_used_connections",     (char*) &max_used_connections,  SHOW_INT},
01203   {"Open_files",               (char*) &my_file_opened,    SHOW_INT_NOFLUSH},
01204   {"Open_streams",             (char*) &my_stream_opened,  SHOW_INT_NOFLUSH},
01205   {"Open_table_definitions",   (char*) &show_table_definitions_cont, SHOW_FUNC},
01206   {"Open_tables",              (char*) &show_open_tables_cont,       SHOW_FUNC},
01207   {"Opened_files",             (char*) &my_file_total_opened, SHOW_INT_NOFLUSH},
01208   {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
01209   {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
01210   {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
01211   {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS},
01212   {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS},
01213   {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS},
01214   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
01215   {"Select_scan",        (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
01216   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
01217   {"Sort_merge_passes",        (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
01218   {"Sort_range",         (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS},
01219   {"Sort_rows",          (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS},
01220   {"Sort_scan",          (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS},
01221   {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_INT},
01222   {"Table_locks_waited",       (char*) &locks_waited,           SHOW_INT},
01223   {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
01224   {"Uptime",                   (char*) &show_starttime_cont,         SHOW_FUNC},
01225   {"Uptime_since_flush_status",(char*) &show_flushstatustime_cont,   SHOW_FUNC},
01226   {NULL, NULL, SHOW_LONGLONG}
01227 };
01228 
01229 static int init_common_variables(const char *conf_file_name, int argc,
01230                                  char **argv, const char **groups)
01231 {
01232   time_t curr_time;
01233   umask(((~my_umask) & 0666));
01234   my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
01235   tzset();      // Set tzname
01236 
01237   curr_time= time(NULL);
01238   if (curr_time == (time_t)-1)
01239     return 1;
01240 
01241   max_system_variables.pseudo_thread_id= UINT32_MAX;
01242   server_start_time= flush_status_time= curr_time;
01243 
01244   if (init_thread_environment())
01245     return 1;
01246   drizzle_init_variables();
01247 
01248   {
01249     struct tm tm_tmp;
01250     localtime_r(&server_start_time,&tm_tmp);
01251     strncpy(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
01252             sizeof(system_time_zone)-1);
01253 
01254  }
01255   /*
01256     We set SYSTEM time zone as reasonable default and
01257     also for failure of my_tz_init() and bootstrap mode.
01258     If user explicitly set time zone with --default-time-zone
01259     option we will change this value in my_tz_init().
01260   */
01261   global_system_variables.time_zone= my_tz_SYSTEM;
01262 
01263   if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
01264   {
01265     strncpy(glob_hostname, STRING_WITH_LEN("localhost"));
01266       errmsg_printf(ERRMSG_LVL_WARN, _("gethostname failed, using '%s' as hostname"),
01267                       glob_hostname);
01268     strncpy(pidfile_name, STRING_WITH_LEN("drizzle"));
01269   }
01270   else
01271     strncpy(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
01272   strcpy(fn_ext(pidfile_name),".pid");    // Add proper extension
01273 
01274   /*
01275     Add server status variables to the dynamic list of
01276     status variables that is shown by SHOW STATUS.
01277     Later, in plugin_init, new entries could be added to that list.
01278   */
01279   if (add_status_vars(status_vars))
01280     return 1; // an error was already reported
01281 
01282   load_defaults(conf_file_name, groups, &argc, &argv);
01283   defaults_argv=argv;
01284   defaults_argc=argc;
01285   get_options(&defaults_argc, defaults_argv);
01286 
01287   current_pid= getpid();    /* Save for later ref */
01288   init_time();        /* Init time-functions (read zone) */
01289 
01290   if (init_errmessage())  /* Read error messages from file */
01291     return 1;
01292   if (item_create_init())
01293     return 1;
01294   if (set_var_init())
01295     return 1;
01296   /* Creates static regex matching for temporal values */
01297   if (! init_temporal_formats())
01298     return 1;
01299 
01300   if (!(default_charset_info=
01301         get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
01302   {
01303     return 1;                           // Eof of the list
01304   }
01305 
01306   if (default_collation_name)
01307   {
01308     const CHARSET_INFO * const default_collation= get_charset_by_name(default_collation_name);
01309     if (!default_collation)
01310     {
01311           errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_UNKNOWN_COLLATION)), default_collation_name);
01312       return 1;
01313     }
01314     if (!my_charset_same(default_charset_info, default_collation))
01315     {
01316           errmsg_printf(ERRMSG_LVL_ERROR, _(ER(ER_COLLATION_CHARSET_MISMATCH)),
01317                       default_collation_name,
01318                       default_charset_info->csname);
01319       return 1;
01320     }
01321     default_charset_info= default_collation;
01322   }
01323   /* Set collactions that depends on the default collation */
01324   global_system_variables.collation_server=  default_charset_info;
01325 
01326   global_system_variables.optimizer_switch= 0;
01327 
01328   if (!(character_set_filesystem=
01329         get_charset_by_csname(character_set_filesystem_name, MY_CS_PRIMARY)))
01330     return 1;
01331   global_system_variables.character_set_filesystem= character_set_filesystem;
01332 
01333   if (!(my_default_lc_time_names=
01334         my_locale_by_name(lc_time_names_name)))
01335   {
01336       errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown locale: '%s'"), lc_time_names_name);
01337     return 1;
01338   }
01339   global_system_variables.lc_time_names= my_default_lc_time_names;
01340 
01341   /* Reset table_alias_charset */
01342   table_alias_charset= files_charset_info;
01343 
01344   return 0;
01345 }
01346 
01347 
01348 static int init_thread_environment()
01349 {
01350   (void) pthread_mutex_init(&LOCK_create_db, NULL);
01351   (void) pthread_mutex_init(&LOCK_open, NULL);
01352   (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
01353   (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
01354   (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
01355   (void) pthread_rwlock_init(&LOCK_system_variables_hash, NULL);
01356   (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
01357   (void) pthread_cond_init(&COND_thread_count,NULL);
01358   (void) pthread_cond_init(&COND_server_end,NULL);
01359   (void) pthread_cond_init(&COND_refresh,NULL);
01360   (void) pthread_cond_init(&COND_global_read_lock,NULL);
01361 
01362   if (pthread_key_create(&THR_Session,NULL) ||
01363       pthread_key_create(&THR_Mem_root,NULL))
01364   {
01365       errmsg_printf(ERRMSG_LVL_ERROR, _("Can't create thread-keys"));
01366     return 1;
01367   }
01368   return 0;
01369 }
01370 
01371 
01372 static int init_server_components(plugin::Registry &plugins)
01373 {
01374   /*
01375     We need to call each of these following functions to ensure that
01376     all things are initialized so that unireg_abort() doesn't fail
01377   */
01378   if (table_cache_init())
01379     unireg_abort(1);
01380   TableShare::cacheStart();
01381 
01382   setup_fpu();
01383   init_thr_lock();
01384 
01385   /* Setup logs */
01386 
01387   if (xid_cache_init())
01388   {
01389       errmsg_printf(ERRMSG_LVL_ERROR, _("Out of memory"));
01390     unireg_abort(1);
01391   }
01392 
01393   /* Allow storage engine to give real error messages */
01394   if (ha_init_errors())
01395     return(1);
01396 
01397   if (plugin_init(plugins, &defaults_argc, defaults_argv,
01398                   ((opt_help) ? true : false)))
01399   {
01400     errmsg_printf(ERRMSG_LVL_ERROR, _("Failed to initialize plugins."));
01401     unireg_abort(1);
01402   }
01403 
01404   if (opt_help || opt_help_extended)
01405     unireg_abort(0);
01406 
01407   /* we do want to exit if there are any other unknown options */
01408   if (defaults_argc > 1)
01409   {
01410     int ho_error;
01411     char **tmp_argv= defaults_argv;
01412     struct my_option no_opts[]=
01413     {
01414       {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
01415     };
01416     /*
01417       We need to eat any 'loose' arguments first before we conclude
01418       that there are unprocessed options.
01419       But we need to preserve defaults_argv pointer intact for
01420       free_defaults() to work. Thus we use a copy here.
01421     */
01422     my_getopt_skip_unknown= 0;
01423 
01424     if ((ho_error= handle_options(&defaults_argc, &tmp_argv, no_opts,
01425                                   drizzled_get_one_option)))
01426       unireg_abort(ho_error);
01427 
01428     if (defaults_argc)
01429     {
01430       fprintf(stderr,
01431               _("%s: Too many arguments (first extra is '%s').\n"
01432                 "Use --verbose --help to get a list of available options\n"),
01433               my_progname, *tmp_argv);
01434       unireg_abort(1);
01435     }
01436   }
01437 
01438   string scheduler_name;
01439   if (opt_scheduler)
01440   {
01441     scheduler_name= opt_scheduler;
01442   }
01443   else
01444   {
01445     scheduler_name= opt_scheduler_default;
01446   }
01447 
01448   if (plugin::Scheduler::setPlugin(scheduler_name))
01449   {
01450       errmsg_printf(ERRMSG_LVL_ERROR,
01451                    _("No scheduler found, cannot continue!\n"));
01452       unireg_abort(1);
01453   }
01454 
01455   /* We have to initialize the storage engines before CSV logging */
01456   if (ha_init())
01457   {
01458       errmsg_printf(ERRMSG_LVL_ERROR, _("Can't init databases"));
01459     unireg_abort(1);
01460   }
01461 
01462   /*
01463     This is entirely for legacy. We will create a new "disk based" engine and a
01464     "memory" engine which will be configurable longterm.
01465   */
01466   const std::string myisam_engine_name("MyISAM");
01467   const std::string heap_engine_name("MEMORY");
01468   myisam_engine= plugin::StorageEngine::findByName(myisam_engine_name);
01469   heap_engine= plugin::StorageEngine::findByName(heap_engine_name);
01470 
01471   /*
01472     Check that the default storage engine is actually available.
01473   */
01474   if (default_storage_engine_str)
01475   {
01476     const std::string name(default_storage_engine_str);
01477     plugin::StorageEngine *engine;
01478 
01479     engine= plugin::StorageEngine::findByName(name);
01480     if (engine == NULL)
01481     {
01482       errmsg_printf(ERRMSG_LVL_ERROR, _("Unknown/unsupported table type: %s"),
01483                     default_storage_engine_str);
01484       unireg_abort(1);
01485     }
01486     if (!engine->is_enabled())
01487     {
01488       errmsg_printf(ERRMSG_LVL_ERROR, _("Default storage engine (%s) is not available"),
01489                     default_storage_engine_str);
01490       unireg_abort(1);
01491       //assert(global_system_variables.storage_engine);
01492     }
01493     else
01494     {
01495       /*
01496         Need to unlock as global_system_variables.storage_engine
01497         was acquired during plugin_init()
01498       */
01499       global_system_variables.storage_engine= engine;
01500     }
01501   }
01502 
01503   if (plugin::StorageEngine::recover(0))
01504   {
01505     unireg_abort(1);
01506   }
01507 
01508 #if defined(MCL_CURRENT)
01509   if (locked_in_memory && !getuid())
01510   {
01511     if (setreuid((uid_t)-1, 0) == -1)
01512     {                        // this should never happen
01513       sql_perror("setreuid");
01514       unireg_abort(1);
01515     }
01516     if (mlockall(MCL_CURRENT))
01517     {
01518       if (global_system_variables.log_warnings)
01519             errmsg_printf(ERRMSG_LVL_WARN, _("Failed to lock memory. Errno: %d\n"),errno);
01520       locked_in_memory= 0;
01521     }
01522     if (user_info)
01523       set_user(drizzled_user, user_info);
01524   }
01525   else
01526 #endif
01527     locked_in_memory=0;
01528 
01529   init_update_queries();
01530   return(0);
01531 }
01532 
01533 
01534 int main(int argc, char **argv)
01535 {
01536 #if defined(ENABLE_NLS)
01537 # if defined(HAVE_LOCALE_H)
01538   setlocale(LC_ALL, "");
01539 # endif
01540   bindtextdomain("drizzle", LOCALEDIR);
01541   textdomain("drizzle");
01542 #endif
01543 
01544   plugin::Registry &plugins= plugin::Registry::singleton();
01545   plugin::Client *client;
01546   Session *session;
01547 
01548   MY_INIT(argv[0]);   // init my_sys library & pthreads
01549   /* nothing should come before this line ^^^ */
01550 
01551   /* Set signal used to kill Drizzle */
01552 #if defined(SIGUSR2)
01553   thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
01554 #else
01555   thr_kill_signal= SIGINT;
01556 #endif
01557 
01558   if (init_common_variables(DRIZZLE_CONFIG_NAME,
01559           argc, argv, load_default_groups))
01560     unireg_abort(1);        // Will do exit
01561 
01562   init_signals();
01563 
01564 
01565   select_thread=pthread_self();
01566   select_thread_in_use=1;
01567 
01568   if (chdir(drizzle_real_data_home) && !opt_help)
01569   {
01570     errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), drizzle_real_data_home);
01571     unireg_abort(1);
01572   }
01573   drizzle_data_home= drizzle_data_home_buff;
01574   drizzle_data_home[0]=FN_CURLIB;   // all paths are relative from here
01575   drizzle_data_home[1]=0;
01576   drizzle_data_home_len= 2;
01577 
01578   if ((user_info= check_user(drizzled_user)))
01579   {
01580 #if defined(MCL_CURRENT)
01581     if (locked_in_memory) // getuid() == 0 here
01582       set_effective_user(user_info);
01583     else
01584 #endif
01585       set_user(drizzled_user, user_info);
01586   }
01587 
01588   if (server_id == 0)
01589   {
01590     server_id= 1;
01591   }
01592 
01593   if (init_server_components(plugins))
01594     unireg_abort(1);
01595 
01596   if (plugin::Listen::setup())
01597     unireg_abort(1);
01598 
01599   /*
01600     init signals & alarm
01601     After this we can't quit by a simple unireg_abort
01602   */
01603   error_handler_hook= my_message_sql;
01604 
01605   if (drizzle_rm_tmp_tables() ||
01606       my_tz_init((Session *)0, default_tz_name))
01607   {
01608     abort_loop= true;
01609     select_thread_in_use=0;
01610     (void) pthread_kill(signal_thread, SIGTERM);
01611 
01612     (void) unlink(pidfile_name);  // Not needed anymore
01613 
01614     exit(1);
01615   }
01616 
01617   init_status_vars();
01618 
01619   errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), my_progname,
01620                 PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
01621 
01622 
01623   /* Listen for new connections and start new session for each connection
01624      accepted. The listen.getClient() method will return NULL when the server
01625      should be shutdown. */
01626   while ((client= plugin::Listen::getClient()) != NULL)
01627   {
01628     if (!(session= new Session(client)))
01629     {
01630       delete client;
01631       continue;
01632     }
01633 
01634     /* If we error on creation we drop the connection and delete the session. */
01635     if (session->schedule())
01636       Session::unlink(session);
01637   }
01638 
01639   /* (void) pthread_attr_destroy(&connection_attrib); */
01640 
01641 
01642   (void) pthread_mutex_lock(&LOCK_thread_count);
01643   select_thread_in_use=0;     // For close_connections
01644   (void) pthread_mutex_unlock(&LOCK_thread_count);
01645   (void) pthread_cond_broadcast(&COND_thread_count);
01646 
01647   /* Wait until cleanup is done */
01648   (void) pthread_mutex_lock(&LOCK_thread_count);
01649   while (!ready_to_exit)
01650     pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
01651   (void) pthread_mutex_unlock(&LOCK_thread_count);
01652 
01653   clean_up(1);
01654   plugin::Registry::shutdown();
01655   clean_up_mutexes();
01656   my_end();
01657   return 0;
01658 }
01659 
01660 
01661 /****************************************************************************
01662   Handle start options
01663 ******************************************************************************/
01664 
01665 enum options_drizzled
01666 {
01667   OPT_SOCKET=256,
01668   OPT_BIND_ADDRESS,            
01669   OPT_PID_FILE,
01670   OPT_STORAGE_ENGINE,          
01671   OPT_INIT_FILE,
01672   OPT_WANT_CORE,
01673   OPT_MEMLOCK,
01674   OPT_SERVER_ID,
01675   OPT_TC_HEURISTIC_RECOVER,
01676   OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
01677   OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
01678   OPT_DO_PSTACK,
01679   OPT_LOCAL_INFILE,
01680   OPT_BACK_LOG,
01681   OPT_JOIN_BUFF_SIZE,
01682   OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
01683   OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
01684   OPT_MAX_ALLOWED_PACKET,
01685   OPT_MAX_CONNECT_ERRORS,
01686   OPT_MAX_HEP_TABLE_SIZE,
01687   OPT_MAX_JOIN_SIZE,
01688   OPT_MAX_SORT_LENGTH,
01689   OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
01690   OPT_MAX_LENGTH_FOR_SORT_DATA,
01691   OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
01692   OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
01693   OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
01694   OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
01695   OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS,
01696   OPT_NET_BUFFER_LENGTH,
01697   OPT_PRELOAD_BUFFER_SIZE,
01698   OPT_RECORD_BUFFER,
01699   OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT,
01700   OPT_DEBUGGING,
01701   OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
01702   OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
01703   OPT_WAIT_TIMEOUT,
01704   OPT_RANGE_ALLOC_BLOCK_SIZE,
01705   OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
01706   OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
01707   OPT_OLD_ALTER_TABLE,
01708   OPT_GROUP_CONCAT_MAX_LEN,
01709   OPT_DEFAULT_COLLATION,
01710   OPT_CHARACTER_SET_FILESYSTEM,
01711   OPT_LC_TIME_NAMES,
01712   OPT_INIT_CONNECT,
01713   OPT_DEFAULT_TIME_ZONE,
01714   OPT_OPTIMIZER_SEARCH_DEPTH,
01715   OPT_SCHEDULER,
01716   OPT_PROTOCOL,
01717   OPT_OPTIMIZER_PRUNE_LEVEL,
01718   OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
01719   OPT_ENABLE_LARGE_PAGES,
01720   OPT_TIMED_MUTEXES,
01721   OPT_TABLE_LOCK_WAIT_TIMEOUT,
01722   OPT_PLUGIN_ADD,
01723   OPT_PLUGIN_LOAD,
01724   OPT_PLUGIN_DIR,
01725   OPT_PORT_OPEN_TIMEOUT,
01726   OPT_SECURE_FILE_PRIV,
01727   OPT_MIN_EXAMINED_ROW_LIMIT
01728 };
01729 
01730 
01731 struct my_option my_long_options[] =
01732 {
01733   {"help", '?', N_("Display this help and exit."),
01734    (char**) &opt_help, (char**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
01735    0, 0},
01736   {"help-extended", '?',
01737    N_("Display this help and exit after initializing plugins."),
01738    (char**) &opt_help_extended, (char**) &opt_help_extended,
01739    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
01740   {"auto-increment-increment", OPT_AUTO_INCREMENT,
01741    N_("Auto-increment columns are incremented by this"),
01742    (char**) &global_system_variables.auto_increment_increment,
01743    (char**) &max_system_variables.auto_increment_increment, 0, GET_ULL,
01744    OPT_ARG, 1, 1, UINT64_MAX, 0, 1, 0 },
01745   {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
01746    N_("Offset added to Auto-increment columns. Used when "
01747       "auto-increment-increment != 1"),
01748    (char**) &global_system_variables.auto_increment_offset,
01749    (char**) &max_system_variables.auto_increment_offset, 0, GET_ULL, OPT_ARG,
01750    1, 1, UINT64_MAX, 0, 1, 0 },
01751   {"basedir", 'b',
01752    N_("Path to installation directory. All paths are usually resolved "
01753       "relative to this."),
01754    (char**) &drizzle_home_ptr, (char**) &drizzle_home_ptr, 0, GET_STR, REQUIRED_ARG,
01755    0, 0, 0, 0, 0, 0},
01756   {"chroot", 'r',
01757    N_("Chroot drizzled daemon during startup."),
01758    (char**) &drizzled_chroot, (char**) &drizzled_chroot, 0, GET_STR, REQUIRED_ARG,
01759    0, 0, 0, 0, 0, 0},
01760   {"collation-server", OPT_DEFAULT_COLLATION,
01761    N_("Set the default collation."),
01762    (char**) &default_collation_name, (char**) &default_collation_name,
01763    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
01764   {"completion-type", OPT_COMPLETION_TYPE,
01765    N_("Default completion type."),
01766    (char**) &global_system_variables.completion_type,
01767    (char**) &max_system_variables.completion_type, 0, GET_UINT,
01768    REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
01769   {"core-file", OPT_WANT_CORE,
01770    N_("Write core on errors."),
01771    0, 0, 0, GET_NO_ARG,
01772    NO_ARG, 0, 0, 0, 0, 0, 0},
01773   {"datadir", 'h',
01774    N_("Path to the database root."),
01775    (char**) &drizzle_data_home,
01776    (char**) &drizzle_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01777   {"default-storage-engine", OPT_STORAGE_ENGINE,
01778    N_("Set the default storage engine (table type) for tables."),
01779    (char**)&default_storage_engine_str, (char**)&default_storage_engine_str,
01780    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01781   {"default-time-zone", OPT_DEFAULT_TIME_ZONE,
01782    N_("Set the default time zone."),
01783    (char**) &default_tz_name, (char**) &default_tz_name,
01784    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
01785 #ifdef HAVE_STACK_TRACE_ON_SEGV
01786   {"enable-pstack", OPT_DO_PSTACK,
01787    N_("Print a symbolic stack trace on failure."),
01788    (char**) &opt_do_pstack, (char**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
01789    0, 0, 0, 0},
01790 #endif /* HAVE_STACK_TRACE_ON_SEGV */
01791   /* See how it's handled in get_one_option() */
01792   {"exit-info", 'T',
01793    N_("Used for debugging;  Use at your own risk!"),
01794    0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
01795   /* We must always support the next option to make scripts like mysqltest
01796      easier to do */
01797   {"gdb", OPT_DEBUGGING,
01798    N_("Set up signals usable for debugging"),
01799    (char**) &opt_debugging, (char**) &opt_debugging,
01800    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
01801   {"language", 'L',
01802    N_("(IGNORED)"),
01803    (char**) &language_ptr, (char**) &language_ptr, 0, GET_STR, REQUIRED_ARG,
01804    0, 0, 0, 0, 0, 0},
01805   {"lc-time-names", OPT_LC_TIME_NAMES,
01806    N_("Set the language used for the month names and the days of the week."),
01807    (char**) &lc_time_names_name,
01808    (char**) &lc_time_names_name,
01809    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
01810   {"log-warnings", 'W',
01811    N_("Log some not critical warnings to the log file."),
01812    (char**) &global_system_variables.log_warnings,
01813    (char**) &max_system_variables.log_warnings, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
01814    0, 0, 0},
01815   {"memlock", OPT_MEMLOCK,
01816    N_("Lock drizzled in memory."),
01817    (char**) &locked_in_memory,
01818    (char**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
01819   {"pid-file", OPT_PID_FILE,
01820    N_("Pid file used by safe_mysqld."),
01821    (char**) &pidfile_name_ptr, (char**) &pidfile_name_ptr, 0, GET_STR,
01822    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01823   {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
01824    N_("Maximum time in seconds to wait for the port to become free. "
01825       "(Default: no wait)"),
01826    (char**) &drizzled_bind_timeout,
01827    (char**) &drizzled_bind_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01828   {"secure-file-priv", OPT_SECURE_FILE_PRIV,
01829    N_("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
01830       "within specified directory"),
01831    (char**) &opt_secure_file_priv, (char**) &opt_secure_file_priv, 0,
01832    GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01833   {"server-id", OPT_SERVER_ID,
01834    N_("Uniquely identifies the server instance in the community of "
01835       "replication partners."),
01836    (char**) &server_id, (char**) &server_id, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 0,
01837    0, 0, 0},
01838   {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
01839    N_("Don't print a stack trace on failure."),
01840    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
01841    0, 0, 0, 0},
01842   {"symbolic-links", 's',
01843    N_("Enable symbolic link support."),
01844    (char**) &my_use_symdir, (char**) &my_use_symdir, 0, GET_BOOL, NO_ARG,
01845    /*
01846      The system call realpath() produces warnings under valgrind and
01847      purify. These are not suppressed: instead we disable symlinks
01848      option if compiled with valgrind support.
01849    */
01850    IF_PURIFY(0,1), 0, 0, 0, 0, 0},
01851   {"timed_mutexes", OPT_TIMED_MUTEXES,
01852    N_("Specify whether to time mutexes (only InnoDB mutexes are currently "
01853       "supported)"),
01854    (char**) &timed_mutexes, (char**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
01855     0, 0, 0, 0, 0},
01856   {"tmpdir", 't',
01857    N_("Path for temporary files."),
01858    (char**) &opt_drizzle_tmpdir,
01859    (char**) &opt_drizzle_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01860   {"transaction-isolation", OPT_TX_ISOLATION,
01861    N_("Default transaction isolation level."),
01862    0, 0, 0, GET_STR, REQUIRED_ARG, 0,
01863    0, 0, 0, 0, 0},
01864   {"user", 'u',
01865    N_("Run drizzled daemon as user."),
01866    0, 0, 0, GET_STR, REQUIRED_ARG,
01867    0, 0, 0, 0, 0, 0},
01868   {"version", 'V',
01869    N_("Output version information and exit."),
01870    0, 0, 0, GET_NO_ARG,
01871    NO_ARG, 0, 0, 0, 0, 0, 0},
01872   {"back_log", OPT_BACK_LOG,
01873    N_("The number of outstanding connection requests Drizzle can have. This "
01874       "comes into play when the main Drizzle thread gets very many connection "
01875       "requests in a very short time."),
01876     (char**) &back_log, (char**) &back_log, 0, GET_UINT,
01877     REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
01878   { "bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
01879     N_("Size of tree cache used in bulk insert optimization. Note that this is "
01880        "a limit per thread!"),
01881     (char**) &global_system_variables.bulk_insert_buff_size,
01882     (char**) &max_system_variables.bulk_insert_buff_size,
01883     0, GET_ULL, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0},
01884   { "div_precision_increment", OPT_DIV_PRECINCREMENT,
01885    N_("Precision of the result of '/' operator will be increased on that "
01886       "value."),
01887    (char**) &global_system_variables.div_precincrement,
01888    (char**) &max_system_variables.div_precincrement, 0, GET_UINT,
01889    REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
01890   { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN,
01891     N_("The maximum length of the result of function  group_concat."),
01892     (char**) &global_system_variables.group_concat_max_len,
01893     (char**) &max_system_variables.group_concat_max_len, 0, GET_UINT64,
01894     REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0},
01895   { "join_buffer_size", OPT_JOIN_BUFF_SIZE,
01896     N_("The size of the buffer that is used for full joins."),
01897    (char**) &global_system_variables.join_buff_size,
01898    (char**) &max_system_variables.join_buff_size, 0, GET_UINT64,
01899    REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX,
01900    MALLOC_OVERHEAD, IO_SIZE, 0},
01901   {"key_buffer_size", OPT_KEY_BUFFER_SIZE,
01902    N_("The size of the buffer used for index blocks for MyISAM tables. "
01903       "Increase this to get better index handling (for all reads and multiple "
01904       "writes) to as much as you can afford;"),
01905    (char**) &dflt_key_cache_var.param_buff_size,
01906    (char**) 0,
01907    0, (GET_ULL),
01908    REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, SIZE_MAX, MALLOC_OVERHEAD,
01909    IO_SIZE, 0},
01910   {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
01911    N_("This characterizes the number of hits a hot block has to be untouched "
01912       "until it is considered aged enough to be downgraded to a warm block. "
01913       "This specifies the percentage ratio of that number of hits to the "
01914       "total number of blocks in key cache"),
01915    (char**) &dflt_key_cache_var.param_age_threshold,
01916    (char**) 0,
01917    0, (GET_UINT32), REQUIRED_ARG,
01918    300, 100, ULONG_MAX, 0, 100, 0},
01919   {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
01920    N_("The default size of key cache blocks"),
01921    (char**) &dflt_key_cache_var.param_block_size,
01922    (char**) 0,
01923    0, (GET_UINT32), REQUIRED_ARG,
01924    KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0},
01925   {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
01926    N_("The minimum percentage of warm blocks in key cache"),
01927    (char**) &dflt_key_cache_var.param_division_limit,
01928    (char**) 0,
01929    0, (GET_UINT32) , REQUIRED_ARG, 100,
01930    1, 100, 0, 1, 0},
01931   {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
01932    N_("Max packetlength to send/receive from to server."),
01933    (char**) &global_system_variables.max_allowed_packet,
01934    (char**) &max_system_variables.max_allowed_packet, 0, GET_UINT32,
01935    REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
01936   {"max_connect_errors", OPT_MAX_CONNECT_ERRORS,
01937    N_("If there is more than this number of interrupted connections from a "
01938       "host this host will be blocked from further connections."),
01939    (char**) &max_connect_errors, (char**) &max_connect_errors, 0, GET_UINT64,
01940    REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0},
01941   {"max_error_count", OPT_MAX_ERROR_COUNT,
01942    N_("Max number of errors/warnings to store for a statement."),
01943    (char**) &global_system_variables.max_error_count,
01944    (char**) &max_system_variables.max_error_count,
01945    0, GET_UINT64, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
01946   {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
01947    N_("Don't allow creation of heap tables bigger than this."),
01948    (char**) &global_system_variables.max_heap_table_size,
01949    (char**) &max_system_variables.max_heap_table_size, 0, GET_ULL,
01950    REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE,
01951    MALLOC_OVERHEAD, 1024, 0},
01952   {"max_join_size", OPT_MAX_JOIN_SIZE,
01953    N_("Joins that are probably going to read more than max_join_size records "
01954       "return an error."),
01955    (char**) &global_system_variables.max_join_size,
01956    (char**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
01957    INT32_MAX, 1, INT32_MAX, 0, 1, 0},
01958   {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
01959    N_("Max number of bytes in sorted records."),
01960    (char**) &global_system_variables.max_length_for_sort_data,
01961    (char**) &max_system_variables.max_length_for_sort_data, 0, GET_ULL,
01962    REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
01963   { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
01964     N_("Limit assumed max number of seeks when looking up rows based on a key"),
01965     (char**) &global_system_variables.max_seeks_for_key,
01966     (char**) &max_system_variables.max_seeks_for_key, 0, GET_UINT64,
01967     REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 },
01968   {"max_sort_length", OPT_MAX_SORT_LENGTH,
01969    N_("The number of bytes to use when sorting BLOB or TEXT values "
01970       "(only the first max_sort_length bytes of each value are used; the "
01971       "rest are ignored)."),
01972    (char**) &global_system_variables.max_sort_length,
01973    (char**) &max_system_variables.max_sort_length, 0, GET_SIZE,
01974    REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
01975   {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
01976    N_("After this many write locks, allow some read locks to run in between."),
01977    (char**) &max_write_lock_count, (char**) &max_write_lock_count, 0, GET_ULL,
01978    REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
01979   {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
01980    N_("Don't log queries which examine less than min_examined_row_limit "
01981       "rows to file."),
01982    (char**) &global_system_variables.min_examined_row_limit,
01983    (char**) &max_system_variables.min_examined_row_limit, 0, GET_ULL,
01984    REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0},
01985   {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
01986     N_("Controls the heuristic(s) applied during query optimization to prune "
01987        "less-promising partial plans from the optimizer search space. Meaning: "
01988        "false - do not apply any heuristic, thus perform exhaustive search; "
01989        "true - prune plans based on number of retrieved rows."),
01990     (char**) &global_system_variables.optimizer_prune_level,
01991     (char**) &max_system_variables.optimizer_prune_level,
01992     0, GET_BOOL, OPT_ARG, 1, 0, 1, 0, 1, 0},
01993   {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
01994    N_("Maximum depth of search performed by the query optimizer. Values "
01995       "larger than the number of relations in a query result in better query "
01996       "plans, but take longer to compile a query. Smaller values than the "
01997       "number of tables in a relation result in faster optimization, but may "
01998       "produce very bad query plans. If set to 0, the system will "
01999       "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
02000       "optimizer will switch to the original find_best (used for "
02001       "testing/comparison)."),
02002    (char**) &global_system_variables.optimizer_search_depth,
02003    (char**) &max_system_variables.optimizer_search_depth,
02004    0, GET_UINT, OPT_ARG, 0, 0, MAX_TABLES+2, 0, 1, 0},
02005   {"plugin_dir", OPT_PLUGIN_DIR,
02006    N_("Directory for plugins."),
02007    (char**) &opt_plugin_dir_ptr, (char**) &opt_plugin_dir_ptr, 0,
02008    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
02009   {"plugin_add", OPT_PLUGIN_ADD,
02010    N_("Optional comma separated list of plugins to load at startup in addition "
02011       "to the default list of plugins. "
02012       "[for example: --plugin_add=crc32,logger_gearman]"),
02013    (char**) &opt_plugin_add, (char**) &opt_plugin_add, 0,
02014    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
02015   {"plugin_load", OPT_PLUGIN_LOAD,
02016    N_("Optional comma separated list of plugins to load at starup instead of "
02017       "the default plugin load list. "
02018       "[for example: --plugin_load=crc32,logger_gearman]"),
02019    (char**) &opt_plugin_load, (char**) &opt_plugin_load, 0,
02020    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
02021   {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
02022    N_("The size of the buffer that is allocated when preloading indexes"),
02023    (char**) &global_system_variables.preload_buff_size,
02024    (char**) &max_system_variables.preload_buff_size, 0, GET_ULL,
02025    REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
02026   {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
02027    N_("Allocation block size for query parsing and execution"),
02028    (char**) &global_system_variables.query_alloc_block_size,
02029    (char**) &max_system_variables.query_alloc_block_size, 0, GET_UINT,
02030    REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
02031   {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
02032    N_("Persistent buffer for query parsing and execution"),
02033    (char**) &global_system_variables.query_prealloc_size,
02034    (char**) &max_system_variables.query_prealloc_size, 0, GET_UINT,
02035    REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
02036    ULONG_MAX, 0, 1024, 0},
02037   {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
02038    N_("Allocation block size for storing ranges during optimization"),
02039    (char**) &global_system_variables.range_alloc_block_size,
02040    (char**) &max_system_variables.range_alloc_block_size, 0, GET_SIZE,
02041    REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, SIZE_MAX,
02042    0, 1024, 0},
02043   {"read_buffer_size", OPT_RECORD_BUFFER,
02044     N_("Each thread that does a sequential scan allocates a buffer of this "
02045        "size for each table it scans. If you do many sequential scans, you may "
02046        "want to increase this value."),
02047     (char**) &global_system_variables.read_buff_size,
02048     (char**) &max_system_variables.read_buff_size,0, GET_UINT, REQUIRED_ARG,
02049     128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT32_MAX, MALLOC_OVERHEAD, IO_SIZE,
02050     0},
02051   {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
02052    N_("When reading rows in sorted order after a sort, the rows are read "
02053       "through this buffer to avoid a disk seeks. If not set, then it's set "
02054       "to the value of record_buffer."),
02055    (char**) &global_system_variables.read_rnd_buff_size,
02056    (char**) &max_system_variables.read_rnd_buff_size, 0,
02057    GET_UINT, REQUIRED_ARG, 256*1024L, 64 /*IO_SIZE*2+MALLOC_OVERHEAD*/ ,
02058    UINT32_MAX, MALLOC_OVERHEAD, 1 /* Small lower limit to be able to test MRR */, 0},
02059   {"scheduler", OPT_SCHEDULER,
02060    N_("Select scheduler to be used (by default multi-thread)."),
02061    (char**)&opt_scheduler, (char**)&opt_scheduler,
02062    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
02063   /* x8 compared to MySQL's x2. We have UTF8 to consider. */
02064   {"sort_buffer_size", OPT_SORT_BUFFER,
02065    N_("Each thread that needs to do a sort allocates a buffer of this size."),
02066    (char**) &global_system_variables.sortbuff_size,
02067    (char**) &max_system_variables.sortbuff_size, 0, GET_SIZE, REQUIRED_ARG,
02068    MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*8, SIZE_MAX,
02069    MALLOC_OVERHEAD, 1, 0},
02070   {"table_definition_cache", OPT_TABLE_DEF_CACHE,
02071    N_("The number of cached table definitions."),
02072    (char**) &table_def_size, (char**) &table_def_size,
02073    0, GET_SIZE, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0},
02074   {"table_open_cache", OPT_TABLE_OPEN_CACHE,
02075    N_("The number of cached open tables."),
02076    (char**) &table_cache_size, (char**) &table_cache_size, 0, GET_UINT64,
02077    REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
02078   {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT,
02079    N_("Timeout in seconds to wait for a table level lock before returning an "
02080       "error. Used only if the connection has active cursors."),
02081    (char**) &table_lock_wait_timeout, (char**) &table_lock_wait_timeout,
02082    0, GET_ULL, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
02083   {"thread_stack", OPT_THREAD_STACK,
02084    N_("The stack size for each thread."),
02085    (char**) &my_thread_stack_size,
02086    (char**) &my_thread_stack_size, 0, GET_SIZE,
02087    REQUIRED_ARG,DEFAULT_THREAD_STACK,
02088    UINT32_C(1024*512), SIZE_MAX, 0, 1024, 0},
02089   {"tmp_table_size", OPT_TMP_TABLE_SIZE,
02090    N_("If an internal in-memory temporary table exceeds this size, Drizzle will"
02091       " automatically convert it to an on-disk MyISAM table."),
02092    (char**) &global_system_variables.tmp_table_size,
02093    (char**) &max_system_variables.tmp_table_size, 0, GET_ULL,
02094    REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
02095   {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
02096    N_("Allocation block size for transactions to be stored in binary log"),
02097    (char**) &global_system_variables.trans_alloc_block_size,
02098    (char**) &max_system_variables.trans_alloc_block_size, 0, GET_UINT,
02099    REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
02100   {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
02101    N_("Persistent buffer for transactions to be stored in binary log"),
02102    (char**) &global_system_variables.trans_prealloc_size,
02103    (char**) &max_system_variables.trans_prealloc_size, 0, GET_UINT,
02104    REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
02105   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
02106 };
02107 
02108 static void print_version(void)
02109 {
02110   /*
02111     Note: the instance manager keys off the string 'Ver' so it can find the
02112     version from the output of 'drizzled --version', so don't change it!
02113   */
02114   printf("%s  Ver %s for %s-%s on %s (%s)\n",my_progname,
02115    PANDORA_RELEASE_VERSION, HOST_VENDOR, HOST_OS, HOST_CPU,
02116          COMPILATION_COMMENT);
02117 }
02118 
02119 static void usage(void)
02120 {
02121   if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
02122     exit(1);
02123   if (!default_collation_name)
02124     default_collation_name= (char*) default_charset_info->name;
02125   print_version();
02126   puts(_("Copyright (C) 2008 Sun Microsystems\n"
02127          "This software comes with ABSOLUTELY NO WARRANTY. "
02128          "This is free software,\n"
02129          "and you are welcome to modify and redistribute it under the GPL "
02130          "license\n\n"
02131          "Starts the Drizzle database server\n"));
02132 
02133   printf(_("Usage: %s [OPTIONS]\n"), my_progname);
02134   {
02135      print_defaults(DRIZZLE_CONFIG_NAME,load_default_groups);
02136      puts("");
02137  
02138      /* Print out all the options including plugin supplied options */
02139      my_print_help_inc_plugins(my_long_options);
02140   }
02141 }
02142 
02143 
02160 static void drizzle_init_variables(void)
02161 {
02162   /* Things reset to zero */
02163   drizzle_home[0]= pidfile_name[0]= 0;
02164   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
02165   opt_secure_file_priv= 0;
02166   segfaulted= 0;
02167   cleanup_done= 0;
02168   defaults_argc= 0;
02169   defaults_argv= 0;
02170   dropping_tables= ha_open_options=0;
02171   test_flags.reset();
02172   wake_thread=0;
02173   abort_loop= select_thread_in_use= false;
02174   ready_to_exit= shutdown_in_progress= 0;
02175   aborted_threads= aborted_connects= 0;
02176   max_used_connections= 0;
02177   drizzled_user= drizzled_chroot= 0;
02178   memset(&global_status_var, 0, sizeof(global_status_var));
02179   key_map_full.set();
02180 
02181   /* Character sets */
02182   system_charset_info= &my_charset_utf8_general_ci;
02183   files_charset_info= &my_charset_utf8_general_ci;
02184   table_alias_charset= &my_charset_bin;
02185   character_set_filesystem= &my_charset_bin;
02186 
02187   /* Things with default values that are not zero */
02188   drizzle_home_ptr= drizzle_home;
02189   pidfile_name_ptr= pidfile_name;
02190   language_ptr= language;
02191   drizzle_data_home= drizzle_real_data_home;
02192   session_startup_options= (OPTION_AUTO_IS_NULL | OPTION_SQL_NOTES);
02193   refresh_version= 1L;  /* Increments on each reload */
02194   global_thread_id= 1UL;
02195   getSessionList().clear();
02196 
02197   /* Set directory paths */
02198   strncpy(language, LANGUAGE, sizeof(language)-1);
02199   strncpy(drizzle_real_data_home, get_relative_path(LOCALSTATEDIR),
02200           sizeof(drizzle_real_data_home)-1);
02201   drizzle_data_home_buff[0]=FN_CURLIB;  // all paths are relative from here
02202   drizzle_data_home_buff[1]=0;
02203   drizzle_data_home_len= 2;
02204 
02205   /* Variables in libraries */
02206   default_character_set_name= "utf8";
02207   default_collation_name= (char *)compiled_default_collation_name;
02208   character_set_filesystem_name= "binary";
02209   lc_time_names_name= (char*) "en_US";
02210   /* Set default values for some option variables */
02211   default_storage_engine_str= (char*) "innodb";
02212   global_system_variables.storage_engine= NULL;
02213   global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
02214   global_system_variables.select_limit= (uint64_t) HA_POS_ERROR;
02215   max_system_variables.select_limit=    (uint64_t) HA_POS_ERROR;
02216   global_system_variables.max_join_size= (uint64_t) HA_POS_ERROR;
02217   max_system_variables.max_join_size=   (uint64_t) HA_POS_ERROR;
02218 
02219   /* Variables that depends on compile options */
02220 #ifdef HAVE_BROKEN_REALPATH
02221   have_symlink=SHOW_OPTION_NO;
02222 #else
02223   have_symlink=SHOW_OPTION_YES;
02224 #endif
02225 
02226   const char *tmpenv;
02227   if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
02228     tmpenv = PREFIX;
02229   (void) strncpy(drizzle_home, tmpenv, sizeof(drizzle_home)-1);
02230   
02231   connection_count= 0;
02232 }
02233 
02234 
02235 extern "C" bool
02236 drizzled_get_one_option(int optid, const struct my_option *opt,
02237                         char *argument)
02238 {
02239   switch(optid) {
02240   case 'a':
02241     global_system_variables.tx_isolation= ISO_SERIALIZABLE;
02242     break;
02243   case 'b':
02244     strncpy(drizzle_home,argument,sizeof(drizzle_home)-1);
02245     break;
02246   case 'C':
02247     if (default_collation_name == compiled_default_collation_name)
02248       default_collation_name= 0;
02249     break;
02250   case 'h':
02251     strncpy(drizzle_real_data_home,argument, sizeof(drizzle_real_data_home)-1);
02252     /* Correct pointer set by my_getopt (for embedded library) */
02253     drizzle_data_home= drizzle_real_data_home;
02254     drizzle_data_home_len= strlen(drizzle_data_home);
02255     break;
02256   case 'u':
02257     if (!drizzled_user || !strcmp(drizzled_user, argument))
02258       drizzled_user= argument;
02259     else
02260       errmsg_printf(ERRMSG_LVL_WARN, _("Ignoring user change to '%s' because the user was "
02261                           "set to '%s' earlier on the command line\n"),
02262                         argument, drizzled_user);
02263     break;
02264   case 'L':
02265     strncpy(language, argument, sizeof(language)-1);
02266     break;
02267   case 'V':
02268     print_version();
02269     exit(0);
02270   case 'W':
02271     if (!argument)
02272       global_system_variables.log_warnings++;
02273     else if (argument == disabled_my_option)
02274       global_system_variables.log_warnings= 0L;
02275     else
02276       global_system_variables.log_warnings= atoi(argument);
02277     break;
02278   case 'T':
02279     if (argument)
02280     {
02281       test_flags.set((uint32_t) atoi(argument));
02282     }
02283     break;
02284   case (int) OPT_WANT_CORE:
02285     test_flags.set(TEST_CORE_ON_SIGNAL);
02286     break;
02287   case (int) OPT_SKIP_STACK_TRACE:
02288     test_flags.set(TEST_NO_STACKTRACE);
02289     break;
02290   case (int) OPT_SKIP_SYMLINKS:
02291     my_use_symdir=0;
02292     break;
02293   case (int) OPT_BIND_ADDRESS:
02294     {
02295       struct addrinfo *res_lst, hints;
02296 
02297       memset(&hints, 0, sizeof(struct addrinfo));
02298       hints.ai_socktype= SOCK_STREAM;
02299       hints.ai_protocol= IPPROTO_TCP;
02300 
02301       if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0)
02302       {
02303           errmsg_printf(ERRMSG_LVL_ERROR, _("Can't start server: cannot resolve hostname!"));
02304         exit(1);
02305       }
02306 
02307       if (res_lst->ai_next)
02308       {
02309           errmsg_printf(ERRMSG_LVL_ERROR, _("Can't start server: bind-address refers to "
02310                           "multiple interfaces!"));
02311         exit(1);
02312       }
02313       freeaddrinfo(res_lst);
02314     }
02315     break;
02316   case (int) OPT_PID_FILE:
02317     strncpy(pidfile_name, argument, sizeof(pidfile_name)-1);
02318     break;
02319   case OPT_SERVER_ID:
02320     break;
02321   case OPT_TX_ISOLATION:
02322     {
02323       int type;
02324       type= find_type_or_exit(argument, &tx_isolation_typelib, opt->name);
02325       global_system_variables.tx_isolation= (type-1);
02326       break;
02327     }
02328   case OPT_TC_HEURISTIC_RECOVER:
02329     tc_heuristic_recover= find_type_or_exit(argument,
02330                                             &tc_heuristic_recover_typelib,
02331                                             opt->name);
02332     break;
02333   }
02334 
02335   return 0;
02336 }
02337 
02338 extern "C" void option_error_reporter(enum loglevel level, const char *format, ...);
02339 
02340 extern "C" void option_error_reporter(enum loglevel level, const char *format, ...)
02341 {
02342   va_list args;
02343   va_start(args, format);
02344 
02345   /* Don't print warnings for --loose options during bootstrap */
02346   if (level == ERROR_LEVEL || global_system_variables.log_warnings)
02347   {
02348     plugin::ErrorMessage::vprintf(current_session, ERROR_LEVEL, format, args);
02349   }
02350   va_end(args);
02351 }
02352 
02353 
02358 static void get_options(int *argc,char **argv)
02359 {
02360   int ho_error;
02361 
02362   my_getopt_error_reporter= option_error_reporter;
02363 
02364   string progname(argv[0]);
02365 
02366   /* Skip unknown options so that they may be processed later by plugins */
02367   my_getopt_skip_unknown= true;
02368 
02369   if ((ho_error= handle_options(argc, &argv, my_long_options,
02370                                 drizzled_get_one_option)))
02371     exit(ho_error);
02372   (*argc)++; /* add back one for the progname handle_options removes */
02373              /* no need to do this for argv as we are discarding it. */
02374 
02375 #if defined(HAVE_BROKEN_REALPATH)
02376   my_use_symdir=0;
02377   my_disable_symlinks=1;
02378   have_symlink=SHOW_OPTION_NO;
02379 #else
02380   if (!my_use_symdir)
02381   {
02382     my_disable_symlinks=1;
02383     have_symlink=SHOW_OPTION_DISABLED;
02384   }
02385 #endif
02386   if (opt_debugging)
02387   {
02388     /* Allow break with SIGINT, no core or stack trace */
02389     test_flags.set(TEST_SIGINT);
02390     test_flags.set(TEST_NO_STACKTRACE);
02391     test_flags.reset(TEST_CORE_ON_SIGNAL);
02392   }
02393 
02394   if (drizzled_chroot)
02395     set_root(drizzled_chroot);
02396   fix_paths(progname);
02397 
02398   /*
02399     Set some global variables from the global_system_variables
02400     In most cases the global variables will not be used
02401   */
02402   my_default_record_cache_size=global_system_variables.read_buff_size;
02403 }
02404 
02405 
02406 static const char *get_relative_path(const char *path)
02407 {
02408   if (test_if_hard_path(path) &&
02409       (strncmp(path, PREFIX, strlen(PREFIX)) == 0) &&
02410       strcmp(PREFIX,FN_ROOTDIR))
02411   {
02412     if (strlen(PREFIX) < strlen(path))
02413       path+=(size_t) strlen(PREFIX);
02414     while (*path == FN_LIBCHAR)
02415       path++;
02416   }
02417   return path;
02418 }
02419 
02420 
02421 static void fix_paths(string &progname)
02422 {
02423   char buff[FN_REFLEN],*pos,rp_buff[PATH_MAX];
02424   convert_dirname(drizzle_home,drizzle_home,NULL);
02425   /* Resolve symlinks to allow 'drizzle_home' to be a relative symlink */
02426 #if defined(HAVE_BROKEN_REALPATH)
02427    my_load_path(drizzle_home, drizzle_home, NULL);
02428 #else
02429   if (!realpath(drizzle_home,rp_buff))
02430     my_load_path(rp_buff, drizzle_home, NULL);
02431   rp_buff[FN_REFLEN-1]= '\0';
02432   strcpy(drizzle_home,rp_buff);
02433   /* Ensure that drizzle_home ends in FN_LIBCHAR */
02434   pos= strchr(drizzle_home, '\0');
02435 #endif
02436   if (pos[-1] != FN_LIBCHAR)
02437   {
02438     pos[0]= FN_LIBCHAR;
02439     pos[1]= 0;
02440   }
02441   convert_dirname(drizzle_real_data_home,drizzle_real_data_home,NULL);
02442   (void) fn_format(buff, drizzle_real_data_home, "", "",
02443                    (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
02444   (void) unpack_dirname(drizzle_unpacked_real_data_home, buff);
02445   convert_dirname(language,language,NULL);
02446   (void) my_load_path(drizzle_home, drizzle_home,""); // Resolve current dir
02447   (void) my_load_path(drizzle_real_data_home, drizzle_real_data_home,drizzle_home);
02448   (void) my_load_path(pidfile_name, pidfile_name,drizzle_real_data_home);
02449 
02450   if (opt_plugin_dir_ptr == NULL)
02451   {
02452     /* No plugin dir has been specified. Figure out where the plugins are */
02453     if (progname[0] != FN_LIBCHAR)
02454     {
02455       /* We have a relative path and need to find the absolute */
02456       char working_dir[FN_REFLEN];
02457       char *working_dir_ptr= working_dir;
02458       working_dir_ptr= getcwd(working_dir_ptr, FN_REFLEN);
02459       string new_path(working_dir);
02460       if (*(new_path.end()-1) != '/')
02461         new_path.push_back('/');
02462       if (progname[0] == '.' && progname[1] == '/')
02463         new_path.append(progname.substr(2));
02464       else
02465         new_path.append(progname);
02466       progname.swap(new_path);
02467     }
02468 
02469     /* Now, trim off the exe name */
02470     string progdir(progname.substr(0, progname.rfind(FN_LIBCHAR)+1));
02471     if (progdir.rfind(".libs/") != string::npos)
02472     {
02473       progdir.assign(progdir.substr(0, progdir.rfind(".libs/")));
02474     }
02475     string testfile(progdir);
02476     testfile.append("drizzled.o");
02477     struct stat testfile_stat;
02478     if (stat(testfile.c_str(), &testfile_stat))
02479     {
02480       /* drizzled.o doesn't exist - we are not in a source dir.
02481        * Go on as usual
02482        */
02483       (void) my_load_path(opt_plugin_dir, get_relative_path(PKGPLUGINDIR),
02484                                           drizzle_home);
02485     }
02486     else
02487     {
02488       /* We are in a source dir! Plugin dir is ../plugin/.libs */
02489       size_t last_libchar_pos= progdir.rfind(FN_LIBCHAR,progdir.size()-2)+1;
02490       string source_plugindir(progdir.substr(0,last_libchar_pos));
02491       source_plugindir.append("plugin/.libs");
02492       (void) my_load_path(opt_plugin_dir, source_plugindir.c_str(), "");
02493     }
02494   }
02495   else
02496   {
02497     (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr, drizzle_home);
02498   }
02499   opt_plugin_dir_ptr= opt_plugin_dir;
02500 
02501   const char *sharedir= get_relative_path(PKGDATADIR);
02502   if (test_if_hard_path(sharedir))
02503     strncpy(buff,sharedir,sizeof(buff)-1);
02504   else
02505   {
02506     strcpy(buff, drizzle_home);
02507     strncat(buff, sharedir, sizeof(buff)-strlen(drizzle_home)-1);
02508   }
02509   convert_dirname(buff,buff,NULL);
02510   (void) my_load_path(language,language,buff);
02511 
02512   {
02513     char *tmp_string;
02514     struct stat buf;
02515 
02516     tmp_string= getenv("TMPDIR");
02517 
02518     if (opt_drizzle_tmpdir)
02519       drizzle_tmpdir= strdup(opt_drizzle_tmpdir);
02520     else if (tmp_string == NULL)
02521       drizzle_tmpdir= strdup(P_tmpdir);
02522     else
02523       drizzle_tmpdir= strdup(tmp_string);
02524 
02525     assert(drizzle_tmpdir);
02526 
02527     if (stat(drizzle_tmpdir, &buf) || (S_ISDIR(buf.st_mode) == false))
02528     {
02529       exit(1);
02530     }
02531   }
02532 
02533   /*
02534     Convert the secure-file-priv option to system format, allowing
02535     a quick strcmp to check if read or write is in an allowed dir
02536    */
02537   if (opt_secure_file_priv)
02538   {
02539     convert_dirname(buff, opt_secure_file_priv, NULL);
02540     free(opt_secure_file_priv);
02541     opt_secure_file_priv= strdup(buff);
02542     if (opt_secure_file_priv == NULL)
02543       exit(1);
02544   }
02545 }
02546 

Generated on Tue Jan 5 10:49:02 2010 for drizzle by  doxygen 1.5.8