Drizzled Public API Documentation

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, Inc.
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 
00022 #include <drizzled/configmake.h>
00023 #include <drizzled/atomics.h>
00024 #include <drizzled/data_home.h>
00025 
00026 #include <netdb.h>
00027 #include <sys/types.h>
00028 #include <netinet/tcp.h>
00029 #include <netinet/in.h>
00030 #include <signal.h>
00031 #include <limits.h>
00032 #include <stdexcept>
00033 
00034 #include <boost/program_options.hpp>
00035 #include <drizzled/program_options/config_file.h>
00036 #include <boost/thread/recursive_mutex.hpp>
00037 #include <boost/thread/mutex.hpp>
00038 #include <boost/thread/shared_mutex.hpp>
00039 #include <boost/thread/condition_variable.hpp>
00040 #include <boost/filesystem.hpp>
00041 #include <boost/detail/atomic_count.hpp>
00042 
00043 #include <drizzled/cached_directory.h>
00044 #include <drizzled/charset.h>
00045 #include <drizzled/data_home.h>
00046 #include <drizzled/debug.h>
00047 #include <drizzled/definition/cache.h>
00048 #include <drizzled/drizzled.h>
00049 #include <drizzled/errmsg_print.h>
00050 #include <drizzled/error.h>
00051 #include <drizzled/global_buffer.h>
00052 #include <drizzled/internal/my_bit.h>
00053 #include <drizzled/internal/my_sys.h>
00054 #include <drizzled/item/cmpfunc.h>
00055 #include <drizzled/item/create.h>
00056 #include <drizzled/message/cache.h>
00057 #include <drizzled/module/load_list.h>
00058 #include <drizzled/module/registry.h>
00059 #include <drizzled/plugin/client.h>
00060 #include <drizzled/plugin/error_message.h>
00061 #include <drizzled/plugin/event_observer.h>
00062 #include <drizzled/plugin/listen.h>
00063 #include <drizzled/plugin/monitored_in_transaction.h>
00064 #include <drizzled/plugin/scheduler.h>
00065 #include <drizzled/plugin/storage_engine.h>
00066 #include <drizzled/plugin/xa_resource_manager.h>
00067 #include <drizzled/probes.h>
00068 #include <drizzled/replication_services.h> /* For ReplicationServices::evaluateRegisteredPlugins() */
00069 #include <drizzled/session.h>
00070 #include <drizzled/session/cache.h>
00071 #include <drizzled/show.h>
00072 #include <drizzled/sql_base.h>
00073 #include <drizzled/sql_parse.h>
00074 #include <drizzled/temporal_format.h> /* For init_temporal_formats() */
00075 #include <drizzled/tztime.h>
00076 #include <drizzled/unireg.h>
00077 #include <plugin/myisam/myisam.h>
00078 #include <drizzled/typelib.h>
00079 #include <drizzled/visibility.h>
00080 
00081 #include <google/protobuf/stubs/common.h>
00082 
00083 #include <drizzled/refresh_version.h>
00084 
00085 #if TIME_WITH_SYS_TIME
00086 # include <sys/time.h>
00087 # include <time.h>
00088 #else
00089 # if HAVE_SYS_TIME_H
00090 #  include <sys/time.h>
00091 # else
00092 #  include <time.h>
00093 # endif
00094 #endif
00095 
00096 #ifdef HAVE_SYS_PRCTL_H
00097 #include <sys/prctl.h>
00098 #endif
00099 #include <sys/socket.h>
00100 
00101 
00102 #include <errno.h>
00103 #include <sys/stat.h>
00104 #include <drizzled/option.h>
00105 #ifdef HAVE_SYSENT_H
00106 #include <sysent.h>
00107 #endif
00108 #include <pwd.h>        // For getpwent
00109 #include <grp.h>
00110 
00111 #ifdef HAVE_SELECT_H
00112 #  include <select.h>
00113 #endif
00114 
00115 #ifdef HAVE_SYS_SELECT_H
00116 #include <sys/select.h>
00117 #endif
00118 
00119 #include <sys/utsname.h>
00120 
00121 #ifdef HAVE_SYS_MMAN_H
00122 #include <sys/mman.h>
00123 #endif
00124 
00125 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
00126 #include <ieeefp.h>
00127 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
00128 
00129 #ifdef HAVE_FPU_CONTROL_H
00130 #include <fpu_control.h>
00131 #endif
00132 
00133 #ifdef HAVE_SYS_FPU_H
00134 /* for IRIX to use set_fpc_csr() */
00135 #include <sys/fpu.h>
00136 #endif
00137 
00138 #include <drizzled/internal/my_pthread.h>     // For thr_setconcurency()
00139 #include <drizzled/constrained_value.h>
00140 
00141 #include <drizzled/gettext.h>
00142 
00143 
00144 #ifdef HAVE_VALGRIND
00145 #define IF_PURIFY(A,B) (A)
00146 #else
00147 #define IF_PURIFY(A,B) (B)
00148 #endif
00149 
00150 #define MAX_MEM_TABLE_SIZE SIZE_MAX
00151 #include <iostream>
00152 #include <fstream>
00153 
00154 
00155 using namespace std;
00156 namespace fs=boost::filesystem;
00157 namespace po=boost::program_options;
00158 namespace dpo=drizzled::program_options;
00159 
00160 bool opt_daemon= false;
00161 
00162 namespace drizzled
00163 {
00164 
00165 inline void setup_fpu()
00166 {
00167 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
00168   /*
00169      We can't handle floating point exceptions with threads, so disable
00170      this on freebsd.
00171      Don't fall for overflow, underflow,divide-by-zero or loss of precision
00172   */
00173 #if defined(__i386__)
00174   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
00175         FP_X_IMP));
00176 #else
00177   fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
00178               FP_X_IMP));
00179 #endif /* __i386__ */
00180 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
00181 
00182   /*
00183     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit for
00184     portable results of floating point operations
00185   */
00186 #if defined(__i386__) && defined(HAVE_FPU_CONTROL_H) && defined(_FPU_DOUBLE)
00187   fpu_control_t cw;
00188   _FPU_GETCW(cw);
00189   cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
00190   _FPU_SETCW(cw);
00191 #endif /* __i386__ && HAVE_FPU_CONTROL_H && _FPU_DOUBLE */
00192 }
00193 
00194 #ifdef SOLARIS
00195 extern "C" int gethostname(char *name, int namelen);
00196 #endif
00197 
00198 const char *first_keyword= "first";
00199 const char * const DRIZZLE_CONFIG_NAME= "drizzled";
00200 
00201 #define GET_HA_ROWS GET_ULL
00202 
00203 const char *tx_isolation_names[] =
00204 { "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
00205   NULL};
00206 
00207 TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
00208                                tx_isolation_names, NULL};
00209 
00210 /*
00211   Used with --help for detailed option
00212 */
00213 bool opt_help= false;
00214 
00215 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
00216 {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
00217  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
00218  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
00219  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
00220  {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
00221 
00222 /* static variables */
00223 
00224 static bool opt_debugging= false;
00225 static uint32_t wake_thread;
00226 static char *drizzled_chroot;
00227 static const char *default_character_set_name;
00228 static const char *character_set_filesystem_name;
00229 static char *lc_time_names_name;
00230 static char *default_collation_name;
00231 static char *default_storage_engine_str;
00232 static const char *compiled_default_collation_name= "utf8_general_ci";
00233 
00234 /* Global variables */
00235 
00236 char *drizzled_user;
00237 bool volatile select_thread_in_use;
00238 bool volatile abort_loop;
00239 DRIZZLED_API bool volatile shutdown_in_progress;
00240 char *opt_scheduler_default;
00241 const char *opt_scheduler= NULL;
00242 
00243 DRIZZLED_API size_t my_thread_stack_size= 0;
00244 
00245 /*
00246   Legacy global plugin::StorageEngine. These will be removed (please do not add more).
00247 */
00248 plugin::StorageEngine *heap_engine;
00249 plugin::StorageEngine *myisam_engine;
00250 
00251 bool calling_initgroups= false; 
00253 uint32_t drizzled_bind_timeout;
00254 uint32_t dropping_tables, ha_open_options;
00255 uint32_t tc_heuristic_recover= 0;
00256 uint64_t session_startup_options;
00257 back_log_constraints back_log(50);
00258 DRIZZLED_API uint32_t server_id;
00259 uint64_t table_cache_size;
00260 size_t table_def_size;
00261 uint32_t global_thread_id= 1UL;
00262 pid_t current_pid;
00263 
00264 extern const double log_10[309];
00265 
00266 const double log_10[] = {
00267   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
00268   1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
00269   1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
00270   1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
00271   1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
00272   1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
00273   1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
00274   1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
00275   1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
00276   1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
00277   1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
00278   1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
00279   1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
00280   1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
00281   1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
00282   1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
00283   1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
00284   1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
00285   1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
00286   1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
00287   1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
00288   1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
00289   1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
00290   1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
00291   1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
00292   1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
00293   1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
00294   1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
00295   1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
00296   1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
00297   1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
00298 };
00299 
00300 time_t server_start_time;
00301 time_t flush_status_time;
00302 
00303 fs::path basedir(PREFIX);
00304 fs::path pid_file;
00305 fs::path secure_file_priv("");
00306 fs::path plugin_dir;
00307 fs::path system_config_dir(SYSCONFDIR);
00308 
00309 
00310 char *opt_tc_log_file;
00311 const key_map key_map_empty(0);
00312 key_map key_map_full(0);                        // Will be initialized later
00313 
00314 std::string drizzle_tmpdir;
00315 char *opt_drizzle_tmpdir= NULL;
00316 
00318 const char *in_left_expr_name= "<left expr>";
00320 const char *in_additional_cond= "<IN COND>";
00321 const char *in_having_cond= "<IN HAVING>";
00322 
00323 /* classes for comparation parsing/processing */
00324 
00325 FILE *stderror_file=0;
00326 
00327 drizzle_system_variables global_system_variables;
00328 drizzle_system_variables max_system_variables;
00329 global_counters current_global_counters;
00330 
00331 DRIZZLED_API const CHARSET_INFO *system_charset_info;
00332 const CHARSET_INFO *files_charset_info;
00333 const CHARSET_INFO *table_alias_charset;
00334 const CHARSET_INFO *character_set_filesystem;
00335 
00336 MY_LOCALE *my_default_lc_time_names;
00337 
00338 SHOW_COMP_OPTION have_symlink;
00339 
00340 boost::condition_variable_any COND_refresh;
00341 boost::condition_variable COND_thread_count;
00342 pthread_t signal_thread;
00343 
00344 /* Static variables */
00345 
00346 int cleanup_done;
00347 
00348 passwd *user_info;
00349 
00350 boost::detail::atomic_count connection_count(0);
00351 
00352 global_buffer_constraint<uint64_t> global_sort_buffer(0);
00353 global_buffer_constraint<uint64_t> global_join_buffer(0);
00354 global_buffer_constraint<uint64_t> global_read_rnd_buffer(0);
00355 global_buffer_constraint<uint64_t> global_read_buffer(0);
00356 
00357 DRIZZLED_API size_t transaction_message_threshold;
00358 
00359 static void drizzle_init_variables(void);
00360 static void get_options();
00361 static void fix_paths();
00362 
00363 static void usage(void);
00364 void close_connections(void);
00365 
00366 fs::path base_plugin_dir(PKGPLUGINDIR);
00367 
00368 po::options_description config_options(_("Config File Options"));
00369 po::options_description long_options(_("Kernel Options"));
00370 po::options_description plugin_load_options(_("Plugin Loading Options"));
00371 po::options_description plugin_options(_("Plugin Options"));
00372 po::options_description initial_options(_("Config and Plugin Loading"));
00373 po::options_description full_options(_("Kernel and Plugin Loading and Plugin"));
00374 vector<string> unknown_options;
00375 vector<string> defaults_file_list;
00376 po::variables_map vm;
00377 
00378 po::variables_map &getVariablesMap()
00379 {
00380   return vm;
00381 }
00382 
00383 namespace
00384 {
00385 
00386 std::string &getGlobHostname()
00387 {
00388   static std::string glob_hostname("localhost");
00389   return glob_hostname;
00390 }
00391 
00392 void setServerHostname(const std::string &hostname)
00393 {
00394   getGlobHostname()= hostname;
00395 }
00396 }
00397 
00398 const std::string &getServerHostname()
00399 {
00400   return getGlobHostname();
00401 }
00402 
00403 /****************************************************************************
00404 ** Code to end drizzled
00405 ****************************************************************************/
00406 
00407 void close_connections(void)
00408 {
00409   /* Abort listening to new connections */
00410   plugin::Listen::shutdown();
00411 
00412   /* kill connection thread */
00413   {
00414     boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
00415 
00416     while (select_thread_in_use)
00417     {
00418       boost::xtime xt;
00419       xtime_get(&xt, boost::TIME_UTC);
00420       xt.sec += 2;
00421 
00422       for (uint32_t tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
00423       {
00424         bool success= COND_thread_count.timed_wait(scopedLock, xt);
00425         if (not success)
00426           break;
00427       }
00428     }
00429   }
00430 
00431 
00432   /*
00433     First signal all threads that it's time to die
00434     This will give the threads some time to gracefully abort their
00435     statements and inform their clients that the server is about to die.
00436   */
00437 
00438   {
00439     boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
00440     session::Cache::list list= session::Cache::singleton().getCache();
00441 
00442     for (session::Cache::list::iterator it= list.begin(); it != list.end(); ++it )
00443     {
00444       Session::shared_ptr tmp(*it);
00445 
00446       tmp->setKilled(Session::KILL_CONNECTION);
00447       tmp->scheduler->killSession(tmp.get());
00448       DRIZZLE_CONNECTION_DONE(tmp->thread_id);
00449 
00450       tmp->lockOnSys();
00451     }
00452   }
00453 
00454   if (session::Cache::singleton().count())
00455     sleep(2);                                   // Give threads time to die
00456 
00457   /*
00458     Force remaining threads to die by closing the connection to the client
00459     This will ensure that threads that are waiting for a command from the
00460     client on a blocking read call are aborted.
00461   */
00462   for (;;)
00463   {
00464     boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
00465     session::Cache::list list= session::Cache::singleton().getCache();
00466 
00467     if (list.empty())
00468     {
00469       break;
00470     }
00471     /* Close before unlock, avoiding crash. See LP bug#436685 */
00472     list.front()->getClient()->close();
00473   }
00474 }
00475 
00476 
00477 void unireg_abort(int exit_code)
00478 {
00479 
00480   if (exit_code)
00481   {
00482     errmsg_printf(error::ERROR, _("Aborting"));
00483   }
00484   else if (opt_help)
00485   {
00486     usage();
00487   }
00488 
00489   clean_up(!opt_help && (exit_code));
00490   internal::my_end();
00491   exit(exit_code);
00492 }
00493 
00494 
00495 void clean_up(bool print_message)
00496 {
00497   if (cleanup_done++)
00498     return;
00499 
00500   table_cache_free();
00501   free_charsets();
00502   module::Registry &modules= module::Registry::singleton();
00503   modules.shutdownModules();
00504 
00505   deinit_temporal_formats();
00506 
00507 #if GOOGLE_PROTOBUF_VERSION >= 2001000
00508   google::protobuf::ShutdownProtobufLibrary();
00509 #endif
00510 
00511   (void) unlink(pid_file.file_string().c_str());  // This may not always exist
00512 
00513   if (print_message && server_start_time)
00514     errmsg_printf(drizzled::error::INFO, _(ER(ER_SHUTDOWN_COMPLETE)),internal::my_progname);
00515 
00516   session::Cache::singleton().shutdownFirst();
00517 
00518   /*
00519     The following lines may never be executed as the main thread may have
00520     killed us
00521   */
00522 } /* clean_up */
00523 
00524 
00525 /* Change to run as another user if started with --user */
00526 
00527 passwd *check_user(const char *user)
00528 {
00529   passwd *tmp_user_info;
00530   uid_t user_id= geteuid();
00531 
00532   // Don't bother if we aren't superuser
00533   if (user_id)
00534   {
00535     if (user)
00536     {
00537       /* Don't give a warning, if real user is same as given with --user */
00538       tmp_user_info= getpwnam(user);
00539       if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
00540           global_system_variables.log_warnings)
00541             errmsg_printf(error::WARN, _("One can only use the --user switch "
00542                             "if running as root\n"));
00543     }
00544     return NULL;
00545   }
00546   if (not user)
00547   {
00548       errmsg_printf(error::ERROR, _("Fatal error: Please read \"Security\" section of "
00549                                     "the manual to find out how to run drizzled as root"));
00550     unireg_abort(1);
00551   }
00552 
00553   if (not strcmp(user, "root"))
00554     return NULL;                        // Avoid problem with dynamic libraries
00555 
00556   if (!(tmp_user_info= getpwnam(user)))
00557   {
00558     // Allow a numeric uid to be used
00559     const char *pos;
00560     for (pos= user; my_isdigit(&my_charset_utf8_general_ci,*pos); pos++) ;
00561     if (*pos)                                   // Not numeric id
00562       goto err;
00563     if (!(tmp_user_info= getpwuid(atoi(user))))
00564       goto err;
00565   }
00566   return tmp_user_info;
00567 
00568 err:
00569   errmsg_printf(error::ERROR, _("Fatal error: Can't change to run as user '%s' ;  "
00570                     "Please check that the user exists!\n"),user);
00571   unireg_abort(1);
00572 
00573 #ifdef PR_SET_DUMPABLE
00574   if (getDebug().test(debug::CORE_ON_SIGNAL))
00575   {
00576     /* inform kernel that process is dumpable */
00577     (void) prctl(PR_SET_DUMPABLE, 1);
00578   }
00579 #endif
00580 
00581 /* Sun Studio 5.10 doesn't like this line.  5.9 requires it */
00582 #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x590)
00583   return NULL;
00584 #endif
00585 
00586 }
00587 
00588 void set_user(const char *user, passwd *user_info_arg)
00589 {
00590   assert(user_info_arg != 0);
00591   initgroups((char*) user, user_info_arg->pw_gid);
00592   if (setgid(user_info_arg->pw_gid) == -1)
00593   {
00594     sql_perror(_("Set process group ID failed"));
00595     unireg_abort(1);
00596   }
00597   if (setuid(user_info_arg->pw_uid) == -1)
00598   {
00599     sql_perror(_("Set process user ID failed"));
00600     unireg_abort(1);
00601   }
00602 }
00603 
00604 
00605 
00607 static void set_root(const char *path)
00608 {
00609   if ((chroot(path) == -1) || !chdir("/"))
00610   {
00611     sql_perror(_("Process chroot failed"));
00612     unireg_abort(1);
00613   }
00614 }
00615 
00616 
00617 /*
00618   Unlink session from global list of available connections and free session
00619 
00620   SYNOPSIS
00621     Session::unlink()
00622     session    Thread handler
00623 */
00624 
00625 void drizzled::Session::unlink(session_id_t &session_id)
00626 {
00627   Session::shared_ptr session= session::Cache::singleton().find(session_id);
00628 
00629   if (session)
00630     unlink(session);
00631 }
00632 
00633 void drizzled::Session::unlink(Session::shared_ptr &session)
00634 {
00635   --connection_count;
00636 
00637   session->cleanup();
00638 
00639   boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
00640 
00641   if (unlikely(plugin::EventObserver::disconnectSession(*session)))
00642   {
00643     // We should do something about an error...
00644   }
00645   session::Cache::singleton().erase(session);
00646 }
00647 
00648 
00649 #ifndef SA_RESETHAND
00650 #define SA_RESETHAND 0
00651 #endif
00652 #ifndef SA_NODEFER
00653 #define SA_NODEFER 0
00654 #endif
00655 
00656 
00657 
00658 
00659 const char *load_default_groups[]=
00660 {
00661   DRIZZLE_CONFIG_NAME, "server", 0, 0
00662 };
00663 
00664 static void find_plugin_dir(string progname)
00665 {
00666   fs::path full_progname(fs::system_complete(progname));
00667 
00668   fs::path progdir(full_progname.parent_path());
00669   if (progdir.filename() == ".libs")
00670   {
00671     progdir= progdir.parent_path();
00672   }
00673 
00674   if (fs::exists(progdir / "drizzled.lo") || fs::exists(progdir / "drizzled.o"))
00675   {
00676     /* We are in a source dir! Plugin dir is ../plugin/.libs */
00677     base_plugin_dir= progdir.parent_path();
00678     base_plugin_dir /= "plugin";
00679     base_plugin_dir /= ".libs";
00680   }
00681 
00682   if (plugin_dir.root_directory() == "")
00683   {
00684     fs::path full_plugin_dir(fs::system_complete(base_plugin_dir));
00685     full_plugin_dir /= plugin_dir;
00686     plugin_dir= full_plugin_dir;
00687   }
00688 }
00689 
00690 static void notify_plugin_dir(fs::path in_plugin_dir)
00691 {
00692   plugin_dir= in_plugin_dir;
00693   if (plugin_dir.root_directory() == "")
00694   {
00695     fs::path full_plugin_dir(fs::system_complete(basedir));
00696     full_plugin_dir /= plugin_dir;
00697     plugin_dir= full_plugin_dir;
00698   }
00699 }
00700 
00701 static void expand_secure_file_priv(fs::path in_secure_file_priv)
00702 {
00703   secure_file_priv= fs::system_complete(in_secure_file_priv);
00704 }
00705 
00706 static void check_limits_aii(uint64_t in_auto_increment_increment)
00707 {
00708   global_system_variables.auto_increment_increment= 1;
00709   if (in_auto_increment_increment < 1 || in_auto_increment_increment > UINT64_MAX)
00710   {
00711     cout << _("Error: Invalid Value for auto_increment_increment");
00712     exit(-1);
00713   }
00714   global_system_variables.auto_increment_increment= in_auto_increment_increment;
00715 }
00716 
00717 static void check_limits_aio(uint64_t in_auto_increment_offset)
00718 {
00719   global_system_variables.auto_increment_offset= 1;
00720   if (in_auto_increment_offset < 1 || in_auto_increment_offset > UINT64_MAX)
00721   {
00722     cout << _("Error: Invalid Value for auto_increment_offset");
00723     exit(-1);
00724   }
00725   global_system_variables.auto_increment_offset= in_auto_increment_offset;
00726 }
00727 
00728 static void check_limits_completion_type(uint32_t in_completion_type)
00729 {
00730   global_system_variables.completion_type= 0;
00731   if (in_completion_type > 2)
00732   {
00733     cout << _("Error: Invalid Value for completion_type");
00734     exit(-1);
00735   }
00736   global_system_variables.completion_type= in_completion_type;
00737 }
00738 
00739 
00740 static void check_limits_dpi(uint32_t in_div_precincrement)
00741 {
00742   global_system_variables.div_precincrement= 4;
00743   if (in_div_precincrement > DECIMAL_MAX_SCALE)
00744   {
00745     cout << _("Error: Invalid Value for div-precision-increment");
00746     exit(-1);
00747   }
00748   global_system_variables.div_precincrement= in_div_precincrement;
00749 }
00750 
00751 static void check_limits_gcml(uint64_t in_group_concat_max_len)
00752 {
00753   global_system_variables.group_concat_max_len= 1024;
00754   if (in_group_concat_max_len > ULONG_MAX || in_group_concat_max_len < 4)
00755   {
00756     cout << _("Error: Invalid Value for group_concat_max_len");
00757     exit(-1);
00758   }
00759   global_system_variables.group_concat_max_len= in_group_concat_max_len;
00760 }
00761 
00762 static void check_limits_join_buffer_size(uint64_t in_join_buffer_size)
00763 {
00764   global_system_variables.join_buff_size= (128*1024L);
00765   if (in_join_buffer_size < IO_SIZE*2 || in_join_buffer_size > ULONG_MAX)
00766   {
00767     cout << _("Error: Invalid Value for join_buffer_size");
00768     exit(-1);
00769   }
00770   in_join_buffer_size-= in_join_buffer_size % IO_SIZE;
00771   global_system_variables.join_buff_size= in_join_buffer_size;
00772 }
00773 
00774 static void check_limits_map(uint32_t in_max_allowed_packet)
00775 {
00776   global_system_variables.max_allowed_packet= (64*1024*1024L);
00777   if (in_max_allowed_packet < 1024 || in_max_allowed_packet > 1024*1024L*1024L)
00778   {
00779     cout << _("Error: Invalid Value for max_allowed_packet");
00780     exit(-1);
00781   }
00782   in_max_allowed_packet-= in_max_allowed_packet % 1024;
00783   global_system_variables.max_allowed_packet= in_max_allowed_packet;
00784 }
00785 
00786 static void check_limits_max_err_cnt(uint64_t in_max_error_count)
00787 {
00788   global_system_variables.max_error_count= DEFAULT_ERROR_COUNT;
00789   if (in_max_error_count > 65535)
00790   {
00791     cout << _("Error: Invalid Value for max_error_count");
00792     exit(-1);
00793   }
00794   global_system_variables.max_error_count= in_max_error_count;
00795 }
00796 
00797 static void check_limits_mhts(uint64_t in_max_heap_table_size)
00798 {
00799   global_system_variables.max_heap_table_size= (16*1024*1024L);
00800   if (in_max_heap_table_size < 16384 || in_max_heap_table_size > MAX_MEM_TABLE_SIZE)
00801   {
00802     cout << _("Error: Invalid Value for max_heap_table_size");
00803     exit(-1);
00804   }
00805   in_max_heap_table_size-= in_max_heap_table_size % 1024;
00806   global_system_variables.max_heap_table_size= in_max_heap_table_size;
00807 }
00808 
00809 static void check_limits_merl(uint64_t in_min_examined_row_limit)
00810 {
00811   global_system_variables.min_examined_row_limit= 0;
00812   if (in_min_examined_row_limit > ULONG_MAX)
00813   {
00814     cout << _("Error: Invalid Value for min_examined_row_limit");
00815     exit(-1);
00816   }
00817   global_system_variables.min_examined_row_limit= in_min_examined_row_limit;
00818 }
00819 
00820 static void check_limits_max_join_size(drizzled::ha_rows in_max_join_size)
00821 {
00822   global_system_variables.max_join_size= INT32_MAX;
00823   if ((uint64_t)in_max_join_size < 1 || (uint64_t)in_max_join_size > INT32_MAX)
00824   {
00825     cout << _("Error: Invalid Value for max_join_size");
00826     exit(-1);
00827   }
00828   global_system_variables.max_join_size= in_max_join_size;
00829 }
00830 
00831 static void check_limits_mlfsd(int64_t in_max_length_for_sort_data)
00832 {
00833   global_system_variables.max_length_for_sort_data= 1024;
00834   if (in_max_length_for_sort_data < 4 || in_max_length_for_sort_data > 8192*1024L)
00835   {
00836     cout << _("Error: Invalid Value for max_length_for_sort_data");
00837     exit(-1);
00838   }
00839   global_system_variables.max_length_for_sort_data= in_max_length_for_sort_data;
00840 }
00841 
00842 static void check_limits_msfk(uint64_t in_max_seeks_for_key)
00843 {
00844   global_system_variables.max_seeks_for_key= ULONG_MAX;
00845   if (in_max_seeks_for_key < 1 || in_max_seeks_for_key > ULONG_MAX)
00846   {
00847     cout << _("Error: Invalid Value for max_seeks_for_key");
00848     exit(-1);
00849   }
00850   global_system_variables.max_seeks_for_key= in_max_seeks_for_key;
00851 }
00852 
00853 static void check_limits_max_sort_length(size_t in_max_sort_length)
00854 {
00855   global_system_variables.max_sort_length= 1024;
00856   if ((int64_t)in_max_sort_length < 4 || (int64_t)in_max_sort_length > 8192*1024L)
00857   {
00858     cout << _("Error: Invalid Value for max_sort_length");
00859     exit(-1);
00860   }
00861   global_system_variables.max_sort_length= in_max_sort_length;
00862 }
00863 
00864 static void check_limits_osd(uint32_t in_optimizer_search_depth)
00865 {
00866   global_system_variables.optimizer_search_depth= 0;
00867   if (in_optimizer_search_depth > MAX_TABLES + 2)
00868   {
00869     cout << _("Error: Invalid Value for optimizer_search_depth");
00870     exit(-1);
00871   }
00872   global_system_variables.optimizer_search_depth= in_optimizer_search_depth;
00873 }
00874 
00875 static void check_limits_pbs(uint64_t in_preload_buff_size)
00876 {
00877   global_system_variables.preload_buff_size= (32*1024L);
00878   if (in_preload_buff_size < 1024 || in_preload_buff_size > 1024*1024*1024L)
00879   {
00880     cout << _("Error: Invalid Value for preload_buff_size");
00881     exit(-1);
00882   }
00883   global_system_variables.preload_buff_size= in_preload_buff_size;
00884 }
00885 
00886 static void check_limits_qabs(uint32_t in_query_alloc_block_size)
00887 {
00888   global_system_variables.query_alloc_block_size= QUERY_ALLOC_BLOCK_SIZE;
00889   if (in_query_alloc_block_size < 1024)
00890   {
00891     cout << _("Error: Invalid Value for query_alloc_block_size");
00892     exit(-1);
00893   }
00894   in_query_alloc_block_size-= in_query_alloc_block_size % 1024;
00895   global_system_variables.query_alloc_block_size= in_query_alloc_block_size;
00896 }
00897 
00898 static void check_limits_qps(uint32_t in_query_prealloc_size)
00899 {
00900   global_system_variables.query_prealloc_size= QUERY_ALLOC_PREALLOC_SIZE;
00901   if (in_query_prealloc_size < QUERY_ALLOC_PREALLOC_SIZE)
00902   {
00903     cout << _("Error: Invalid Value for query_prealloc_size");
00904     exit(-1);
00905   }
00906   in_query_prealloc_size-= in_query_prealloc_size % 1024;
00907   global_system_variables.query_prealloc_size= in_query_prealloc_size;
00908 }
00909 
00910 static void check_limits_rabs(size_t in_range_alloc_block_size)
00911 {
00912   global_system_variables.range_alloc_block_size= RANGE_ALLOC_BLOCK_SIZE;
00913   if (in_range_alloc_block_size < RANGE_ALLOC_BLOCK_SIZE)
00914   {
00915     cout << _("Error: Invalid Value for range_alloc_block_size");
00916     exit(-1);
00917   }
00918   in_range_alloc_block_size-= in_range_alloc_block_size % 1024;
00919   global_system_variables.range_alloc_block_size= in_range_alloc_block_size;
00920 }
00921 
00922 static void check_limits_read_buffer_size(int32_t in_read_buff_size)
00923 {
00924   global_system_variables.read_buff_size= (128*1024L);
00925   if (in_read_buff_size < IO_SIZE*2 || in_read_buff_size > INT32_MAX)
00926   {
00927     cout << _("Error: Invalid Value for read_buff_size");
00928     exit(-1);
00929   }
00930   in_read_buff_size-= in_read_buff_size % IO_SIZE;
00931   global_system_variables.read_buff_size= in_read_buff_size;
00932 }
00933 
00934 static void check_limits_read_rnd_buffer_size(uint32_t in_read_rnd_buff_size)
00935 {
00936   global_system_variables.read_rnd_buff_size= (256*1024L);
00937   if (in_read_rnd_buff_size < 64 || in_read_rnd_buff_size > UINT32_MAX)
00938   {
00939     cout << _("Error: Invalid Value for read_rnd_buff_size");
00940     exit(-1);
00941   }
00942   global_system_variables.read_rnd_buff_size= in_read_rnd_buff_size;
00943 }
00944 
00945 static void check_limits_sort_buffer_size(size_t in_sortbuff_size)
00946 {
00947   global_system_variables.sortbuff_size= MAX_SORT_MEMORY;
00948   if ((uint32_t)in_sortbuff_size < MIN_SORT_MEMORY)
00949   {
00950     cout << _("Error: Invalid Value for sort_buff_size");
00951     exit(-1);
00952   }
00953   global_system_variables.sortbuff_size= in_sortbuff_size;
00954 }
00955 
00956 static void check_limits_tdc(uint32_t in_table_def_size)
00957 {
00958   table_def_size= 128;
00959   if (in_table_def_size < 1 || in_table_def_size > 512*1024L)
00960   {
00961     cout << _("Error: Invalid Value for table_def_size");
00962     exit(-1);
00963   }
00964   table_def_size= in_table_def_size;
00965 }
00966 
00967 static void check_limits_toc(uint32_t in_table_cache_size)
00968 {
00969   table_cache_size= TABLE_OPEN_CACHE_DEFAULT;
00970   if (in_table_cache_size < TABLE_OPEN_CACHE_MIN || in_table_cache_size > 512*1024L)
00971   {
00972     cout << _("Error: Invalid Value for table_cache_size");
00973     exit(-1);
00974   }
00975   table_cache_size= in_table_cache_size;
00976 }
00977 
00978 static void check_limits_tlwt(uint64_t in_table_lock_wait_timeout)
00979 {
00980   table_lock_wait_timeout= 50;
00981   if (in_table_lock_wait_timeout < 1 || in_table_lock_wait_timeout > 1024*1024*1024)
00982   {
00983     cout << _("Error: Invalid Value for table_lock_wait_timeout");
00984     exit(-1);
00985   }
00986   table_lock_wait_timeout= in_table_lock_wait_timeout;
00987 }
00988 
00989 static void check_limits_thread_stack(uint32_t in_my_thread_stack_size)
00990 {
00991   my_thread_stack_size= in_my_thread_stack_size - (in_my_thread_stack_size % 1024);
00992 }
00993 
00994 static void check_limits_tmp_table_size(uint64_t in_tmp_table_size)
00995 {
00996   global_system_variables.tmp_table_size= 16*1024*1024L;
00997   if (in_tmp_table_size < 1024 || in_tmp_table_size > MAX_MEM_TABLE_SIZE)
00998   {
00999     cout << _("Error: Invalid Value for table_lock_wait_timeout");
01000     exit(-1);
01001   }
01002   global_system_variables.tmp_table_size= in_tmp_table_size;
01003 }
01004 
01005 static void check_limits_transaction_message_threshold(size_t in_transaction_message_threshold)
01006 {
01007   transaction_message_threshold= 1024*1024;
01008   if ((int64_t) in_transaction_message_threshold < 128*1024 || (int64_t)in_transaction_message_threshold > 1024*1024)
01009   {
01010     cout << _("Error: Invalid Value for transaction_message_threshold valid values are between 131072 - 1048576 bytes");
01011     exit(-1);
01012   }
01013   transaction_message_threshold= in_transaction_message_threshold;
01014 }
01015 
01016 static void process_defaults_files()
01017 {
01018   for (vector<string>::iterator iter= defaults_file_list.begin();
01019        iter != defaults_file_list.end();
01020        ++iter)
01021   {
01022     fs::path file_location= *iter;
01023 
01024     ifstream input_defaults_file(file_location.file_string().c_str());
01025 
01026     po::parsed_options file_parsed=
01027       dpo::parse_config_file(input_defaults_file, full_options, true);
01028     vector<string> file_unknown=
01029       po::collect_unrecognized(file_parsed.options, po::include_positional);
01030 
01031     for (vector<string>::iterator it= file_unknown.begin();
01032          it != file_unknown.end();
01033          ++it)
01034     {
01035       string new_unknown_opt("--");
01036       new_unknown_opt.append(*it);
01037       ++it;
01038       if (it != file_unknown.end())
01039       {
01040         if ((*it) != "true")
01041         {
01042           new_unknown_opt.push_back('=');
01043           new_unknown_opt.append(*it);
01044         }
01045       }
01046       else
01047       {
01048         break;
01049       }
01050       unknown_options.push_back(new_unknown_opt);
01051     }
01052     store(file_parsed, vm);
01053   }
01054 }
01055 
01056 static void compose_defaults_file_list(vector<string> in_options)
01057 {
01058   for (vector<string>::iterator it= in_options.begin();
01059        it != in_options.end();
01060        ++it)
01061   {
01062     fs::path p(*it);
01063     if (fs::is_regular_file(p))
01064       defaults_file_list.push_back(*it);
01065     else
01066     {
01067       errmsg_printf(error::ERROR,
01068                   _("Defaults file '%s' not found\n"), (*it).c_str());
01069       unireg_abort(1);
01070     }
01071 
01072   }
01073 }
01074 
01075 int init_basic_variables(int argc, char **argv)
01076 {
01077   time_t curr_time;
01078   umask(((~internal::my_umask) & 0666));
01079   decimal_zero.set_zero(); // set decimal_zero constant;
01080   tzset();      // Set tzname
01081 
01082   curr_time= time(NULL);
01083   if (curr_time == (time_t)-1)
01084     return 1;
01085 
01086   max_system_variables.pseudo_thread_id= UINT32_MAX;
01087   server_start_time= flush_status_time= curr_time;
01088 
01089   drizzle_init_variables();
01090 
01091   find_plugin_dir(argv[0]);
01092 
01093   /*
01094     We set SYSTEM time zone as reasonable default and
01095     also for failure of my_tz_init() and bootstrap mode.
01096     If user explicitly set time zone with --default-time-zone
01097     option we will change this value in my_tz_init().
01098   */
01099   global_system_variables.time_zone= my_tz_SYSTEM;
01100 
01101   char ret_hostname[FN_REFLEN];
01102   if (gethostname(ret_hostname,sizeof(ret_hostname)) < 0)
01103   {
01104     errmsg_printf(error::WARN,
01105                   _("gethostname failed, using '%s' as hostname"),
01106                   getServerHostname().c_str());
01107     pid_file= "drizzle";
01108   }
01109   else
01110   {
01111     setServerHostname(ret_hostname);
01112     pid_file= getServerHostname();
01113   }
01114   pid_file.replace_extension(".pid");
01115 
01116   system_config_dir /= "drizzle";
01117 
01118   config_options.add_options()
01119   ("help,?", po::value<bool>(&opt_help)->default_value(false)->zero_tokens(),
01120   _("Display this help and exit."))
01121   ("daemon,d", po::value<bool>(&opt_daemon)->default_value(false)->zero_tokens(),
01122   _("Run as a daemon."))
01123   ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
01124   _("Configuration file defaults are not used if no-defaults is set"))
01125   ("defaults-file", po::value<vector<string> >()->composing()->notifier(&compose_defaults_file_list),
01126   _("Configuration file to use"))
01127   ("config-dir", po::value<fs::path>(&system_config_dir),
01128   _("Base location for config files"))
01129   ("plugin-dir", po::value<fs::path>(&plugin_dir)->notifier(&notify_plugin_dir),
01130   _("Directory for plugins."))
01131   ;
01132 
01133   plugin_load_options.add_options()
01134   ("plugin-add", po::value<vector<string> >()->composing()->notifier(&compose_plugin_add),
01135   _("Optional comma separated list of plugins to load at startup in addition "
01136      "to the default list of plugins. "
01137      "[for example: --plugin_add=crc32,logger_gearman]"))
01138   ("plugin-remove", po::value<vector<string> >()->composing()->notifier(&compose_plugin_remove),
01139   _("Optional comma separated list of plugins to not load at startup. Effectively "
01140      "removes a plugin from the list of plugins to be loaded. "
01141      "[for example: --plugin_remove=crc32,logger_gearman]"))
01142   ("plugin-load", po::value<string>()->notifier(&notify_plugin_load)->default_value(PANDORA_PLUGIN_LIST),
01143   _("Optional comma separated list of plugins to load at starup instead of "
01144      "the default plugin load list. "
01145      "[for example: --plugin_load=crc32,logger_gearman]"))
01146   ;
01147 
01148   long_options.add_options()
01149   ("auto-increment-increment", po::value<uint64_t>(&global_system_variables.auto_increment_increment)->default_value(1)->notifier(&check_limits_aii),
01150   _("Auto-increment columns are incremented by this"))
01151   ("auto-increment-offset", po::value<uint64_t>(&global_system_variables.auto_increment_offset)->default_value(1)->notifier(&check_limits_aio),
01152   _("Offset added to Auto-increment columns. Used when auto-increment-increment != 1"))
01153   ("basedir,b", po::value<fs::path>(&basedir),
01154   _("Path to installation directory. All paths are usually resolved "
01155      "relative to this."))
01156   ("chroot,r", po::value<string>(),
01157   _("Chroot drizzled daemon during startup."))
01158   ("collation-server", po::value<string>(),
01159   _("Set the default collation."))
01160   ("completion-type", po::value<uint32_t>(&global_system_variables.completion_type)->default_value(0)->notifier(&check_limits_completion_type),
01161   _("Default completion type."))
01162   ("core-file",  _("Write core on errors."))
01163   ("datadir", po::value<fs::path>(&getDataHome()),
01164   _("Path to the database root."))
01165   ("default-storage-engine", po::value<string>(),
01166   _("Set the default storage engine for tables."))
01167   ("default-time-zone", po::value<string>(),
01168   _("Set the default time zone."))
01169   ("exit-info,T", po::value<long>(),
01170   _("Used for debugging;  Use at your own risk!"))
01171   ("gdb", po::value<bool>(&opt_debugging)->default_value(false)->zero_tokens(),
01172   _("Set up signals usable for debugging"))
01173   ("lc-time-name", po::value<string>(),
01174   _("Set the language used for the month names and the days of the week."))
01175   ("log-warnings,W", po::value<bool>(&global_system_variables.log_warnings)->default_value(false)->zero_tokens(),
01176   _("Log some not critical warnings to the log file."))
01177   ("pid-file", po::value<fs::path>(&pid_file),
01178   _("Pid file used by drizzled."))
01179   ("port-open-timeout", po::value<uint32_t>(&drizzled_bind_timeout)->default_value(0),
01180   _("Maximum time in seconds to wait for the port to become free. "))
01181   ("replicate-query", po::value<bool>(&global_system_variables.replicate_query)->default_value(false)->zero_tokens(),
01182   _("Include the SQL query in replicated protobuf messages."))
01183   ("secure-file-priv", po::value<fs::path>(&secure_file_priv)->notifier(expand_secure_file_priv),
01184   _("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
01185      "within specified directory"))
01186   ("server-id", po::value<uint32_t>(&server_id)->default_value(0),
01187   _("Uniquely identifies the server instance in the community of "
01188      "replication partners."))
01189   ("skip-stack-trace",
01190   _("Don't print a stack trace on failure."))
01191   ("symbolic-links,s", po::value<bool>(&internal::my_use_symdir)->default_value(IF_PURIFY(false,true))->zero_tokens(),
01192   _("Enable symbolic link support."))
01193   ("timed-mutexes", po::value<bool>(&internal::timed_mutexes)->default_value(false)->zero_tokens(),
01194   _("Specify whether to time mutexes (only InnoDB mutexes are currently "
01195      "supported)"))
01196   ("tmpdir,t", po::value<string>(),
01197   _("Path for temporary files."))
01198   ("transaction-isolation", po::value<string>(),
01199   _("Default transaction isolation level."))
01200   ("transaction-message-threshold", po::value<size_t>(&transaction_message_threshold)->default_value(1024*1024)->notifier(&check_limits_transaction_message_threshold),
01201   _("Max message size written to transaction log, valid values 131072 - 1048576 bytes."))
01202   ("user,u", po::value<string>(),
01203   _("Run drizzled daemon as user."))
01204   ("version,V",
01205   _("Output version information and exit."))
01206   ("back-log", po::value<back_log_constraints>(&back_log),
01207   _("The number of outstanding connection requests Drizzle can have. This "
01208      "comes into play when the main Drizzle thread gets very many connection "
01209      "requests in a very short time."))
01210   ("bulk-insert-buffer-size",
01211   po::value<uint64_t>(&global_system_variables.bulk_insert_buff_size)->default_value(8192*1024),
01212   _("Size of tree cache used in bulk insert optimization. Note that this is "
01213      "a limit per thread!"))
01214   ("div-precision-increment",  po::value<uint32_t>(&global_system_variables.div_precincrement)->default_value(4)->notifier(&check_limits_dpi),
01215   _("Precision of the result of '/' operator will be increased on that "
01216      "value."))
01217   ("group-concat-max-len", po::value<uint64_t>(&global_system_variables.group_concat_max_len)->default_value(1024)->notifier(&check_limits_gcml),
01218   _("The maximum length of the result of function  group_concat."))
01219   ("join-buffer-size", po::value<uint64_t>(&global_system_variables.join_buff_size)->default_value(128*1024L)->notifier(&check_limits_join_buffer_size),
01220   _("The size of the buffer that is used for full joins."))
01221   ("join-heap-threshold",
01222   po::value<uint64_t>()->default_value(0),
01223   _("A global cap on the amount of memory that can be allocated by session join buffers (0 means unlimited)"))
01224   ("max-allowed-packet", po::value<uint32_t>(&global_system_variables.max_allowed_packet)->default_value(64*1024*1024L)->notifier(&check_limits_map),
01225   _("Max packetlength to send/receive from to server."))
01226   ("max-error-count", po::value<uint64_t>(&global_system_variables.max_error_count)->default_value(DEFAULT_ERROR_COUNT)->notifier(&check_limits_max_err_cnt),
01227   _("Max number of errors/warnings to store for a statement."))
01228   ("max-heap-table-size", po::value<uint64_t>(&global_system_variables.max_heap_table_size)->default_value(16*1024*1024L)->notifier(&check_limits_mhts),
01229   _("Don't allow creation of heap tables bigger than this."))
01230   ("max-join-size", po::value<drizzled::ha_rows>(&global_system_variables.max_join_size)->default_value(INT32_MAX)->notifier(&check_limits_max_join_size),
01231   _("Joins that are probably going to read more than max_join_size records "
01232      "return an error."))
01233   ("max-length-for-sort-data", po::value<uint64_t>(&global_system_variables.max_length_for_sort_data)->default_value(1024)->notifier(&check_limits_mlfsd),
01234   _("Max number of bytes in sorted records."))
01235   ("max-seeks-for-key", po::value<uint64_t>(&global_system_variables.max_seeks_for_key)->default_value(ULONG_MAX)->notifier(&check_limits_msfk),
01236   _("Limit assumed max number of seeks when looking up rows based on a key"))
01237   ("max-sort-length", po::value<size_t>(&global_system_variables.max_sort_length)->default_value(1024)->notifier(&check_limits_max_sort_length),
01238   _("The number of bytes to use when sorting BLOB or TEXT values "
01239      "(only the first max_sort_length bytes of each value are used; the "
01240      "rest are ignored)."))
01241   ("max-write-lock-count", po::value<uint64_t>(&max_write_lock_count)->default_value(UINT64_MAX),
01242   _("After this many write locks, allow some read locks to run in between."))
01243   ("min-examined-row-limit", po::value<uint64_t>(&global_system_variables.min_examined_row_limit)->default_value(0)->notifier(&check_limits_merl),
01244   _("Don't log queries which examine less than min_examined_row_limit "
01245      "rows to file."))
01246   ("disable-optimizer-prune",
01247   _("Do not apply any heuristic(s) during query optimization to prune, "
01248      "thus perform an exhaustive search from the optimizer search space."))
01249   ("optimizer-search-depth", po::value<uint32_t>(&global_system_variables.optimizer_search_depth)->default_value(0)->notifier(&check_limits_osd),
01250   _("Maximum depth of search performed by the query optimizer. Values "
01251      "larger than the number of relations in a query result in better query "
01252      "plans, but take longer to compile a query. Smaller values than the "
01253      "number of tables in a relation result in faster optimization, but may "
01254      "produce very bad query plans. If set to 0, the system will "
01255      "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
01256      "optimizer will switch to the original find_best (used for "
01257      "testing/comparison)."))
01258   ("preload-buffer-size", po::value<uint64_t>(&global_system_variables.preload_buff_size)->default_value(32*1024L)->notifier(&check_limits_pbs),
01259   _("The size of the buffer that is allocated when preloading indexes"))
01260   ("query-alloc-block-size",
01261   po::value<uint32_t>(&global_system_variables.query_alloc_block_size)->default_value(QUERY_ALLOC_BLOCK_SIZE)->notifier(&check_limits_qabs),
01262   _("Allocation block size for query parsing and execution"))
01263   ("query-prealloc-size",
01264   po::value<uint32_t>(&global_system_variables.query_prealloc_size)->default_value(QUERY_ALLOC_PREALLOC_SIZE)->notifier(&check_limits_qps),
01265   _("Persistent buffer for query parsing and execution"))
01266   ("range-alloc-block-size",
01267   po::value<size_t>(&global_system_variables.range_alloc_block_size)->default_value(RANGE_ALLOC_BLOCK_SIZE)->notifier(&check_limits_rabs),
01268   _("Allocation block size for storing ranges during optimization"))
01269   ("read-buffer-size",
01270   po::value<uint32_t>(&global_system_variables.read_buff_size)->default_value(128*1024L)->notifier(&check_limits_read_buffer_size),
01271   _("Each thread that does a sequential scan allocates a buffer of this "
01272       "size for each table it scans. If you do many sequential scans, you may "
01273       "want to increase this value."))
01274   ("read-buffer-threshold",
01275   po::value<uint64_t>()->default_value(0),
01276   _("A global cap on the size of read-buffer-size (0 means unlimited)"))
01277   ("read-rnd-buffer-size",
01278   po::value<uint32_t>(&global_system_variables.read_rnd_buff_size)->default_value(256*1024L)->notifier(&check_limits_read_rnd_buffer_size),
01279   _("When reading rows in sorted order after a sort, the rows are read "
01280      "through this buffer to avoid a disk seeks. If not set, then it's set "
01281      "to the value of record_buffer."))
01282   ("read-rnd-threshold",
01283   po::value<uint64_t>()->default_value(0),
01284   _("A global cap on the size of read-rnd-buffer-size (0 means unlimited)"))
01285   ("scheduler", po::value<string>(),
01286   _("Select scheduler to be used (by default multi-thread)."))
01287   ("sort-buffer-size",
01288   po::value<size_t>(&global_system_variables.sortbuff_size)->default_value(MAX_SORT_MEMORY)->notifier(&check_limits_sort_buffer_size),
01289   _("Each thread that needs to do a sort allocates a buffer of this size."))
01290   ("sort-heap-threshold",
01291   po::value<uint64_t>()->default_value(0),
01292   _("A global cap on the amount of memory that can be allocated by session sort buffers (0 means unlimited)"))
01293   ("table-definition-cache", po::value<size_t>(&table_def_size)->default_value(128)->notifier(&check_limits_tdc),
01294   _("The number of cached table definitions."))
01295   ("table-open-cache", po::value<uint64_t>(&table_cache_size)->default_value(TABLE_OPEN_CACHE_DEFAULT)->notifier(&check_limits_toc),
01296   _("The number of cached open tables."))
01297   ("table-lock-wait-timeout", po::value<uint64_t>(&table_lock_wait_timeout)->default_value(50)->notifier(&check_limits_tlwt),
01298   _("Timeout in seconds to wait for a table level lock before returning an "
01299      "error. Used only if the connection has active cursors."))
01300   ("thread-stack", po::value<size_t>(&my_thread_stack_size)->default_value(DEFAULT_THREAD_STACK)->notifier(&check_limits_thread_stack),
01301   _("The stack size for each thread."))
01302   ("tmp-table-size",
01303   po::value<uint64_t>(&global_system_variables.tmp_table_size)->default_value(16*1024*1024L)->notifier(&check_limits_tmp_table_size),
01304   _("If an internal in-memory temporary table exceeds this size, Drizzle will"
01305      " automatically convert it to an on-disk MyISAM table."))
01306   ("verbose", po::value<std::string>()->default_value(error::verbose_string())->notifier(&error::check_verbosity),
01307   _("The verbosity of messages from drizzled.  Possible values are INSPECT, INFO, WARN or ERROR"))
01308   ;
01309 
01310   full_options.add(long_options);
01311   full_options.add(plugin_load_options);
01312 
01313   initial_options.add(config_options);
01314   initial_options.add(plugin_load_options);
01315 
01316   int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
01317   /* Get options about where config files and the like are */
01318   po::parsed_options parsed= po::command_line_parser(argc, argv).style(style).
01319     options(initial_options).allow_unregistered().run();
01320   unknown_options=
01321     po::collect_unrecognized(parsed.options, po::include_positional);
01322 
01323   try
01324   {
01325     po::store(parsed, vm);
01326   }
01327   catch (std::exception&)
01328   {
01329     errmsg_printf(error::ERROR, _("Duplicate entry for command line option\n"));
01330     unireg_abort(1);
01331   }
01332 
01333   if (not vm["no-defaults"].as<bool>())
01334   {
01335     fs::path system_config_file_drizzle(system_config_dir);
01336     system_config_file_drizzle /= "drizzled.cnf";
01337     defaults_file_list.insert(defaults_file_list.begin(),
01338                               system_config_file_drizzle.file_string());
01339 
01340     fs::path config_conf_d_location(system_config_dir);
01341     config_conf_d_location /= "conf.d";
01342 
01343 
01344     CachedDirectory config_conf_d(config_conf_d_location.file_string());
01345     if (not config_conf_d.fail())
01346     {
01347 
01348       for (CachedDirectory::Entries::const_iterator iter= config_conf_d.getEntries().begin();
01349            iter != config_conf_d.getEntries().end();
01350            ++iter)
01351       {
01352         string file_entry((*iter)->filename);
01353 
01354         if (not file_entry.empty()
01355             && file_entry != "."
01356             && file_entry != "..")
01357         {
01358           fs::path the_entry(config_conf_d_location);
01359           the_entry /= file_entry;
01360           defaults_file_list.push_back(the_entry.file_string());
01361         }
01362       }
01363     }
01364   }
01365 
01366   /* TODO: here is where we should add a process_env_vars */
01367 
01368   /* We need a notify here so that plugin_init will work properly */
01369   try
01370   {
01371     po::notify(vm);
01372   }
01373   catch (po::validation_error &err)
01374   {
01375     errmsg_printf(error::ERROR,
01376                   _("%s: %s.\n"
01377                     "Use --help to get a list of available options\n"),
01378                   internal::my_progname, err.what());
01379     unireg_abort(1);
01380   }
01381 
01382   process_defaults_files();
01383 
01384   /* Process with notify a second time because a config file may contain
01385      plugin loader options */
01386 
01387   try
01388   {
01389     po::notify(vm);
01390   }
01391   catch (po::validation_error &err)
01392   {
01393     errmsg_printf(error::ERROR,
01394                   _("%s: %s.\n"
01395                     "Use --help to get a list of available options\n"),
01396                   internal::my_progname, err.what());
01397     unireg_abort(1);
01398   }
01399 
01400   return 0;
01401 }
01402 
01403 int init_remaining_variables(module::Registry &plugins)
01404 {
01405   int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
01406 
01407   current_pid= getpid();    /* Save for later ref */
01408 
01409   /* At this point, we've read all the options we need to read from files and
01410      collected most of them into unknown options - now let's load everything
01411   */
01412 
01413   if (plugin_init(plugins, plugin_options))
01414   {
01415     errmsg_printf(error::ERROR, _("Failed to initialize plugins\n"));
01416     unireg_abort(1);
01417   }
01418 
01419   full_options.add(plugin_options);
01420 
01421   vector<string> final_unknown_options;
01422   try
01423   {
01424     po::parsed_options final_parsed=
01425       po::command_line_parser(unknown_options).style(style).
01426       options(full_options).extra_parser(dpo::parse_size_arg).run();
01427 
01428     final_unknown_options=
01429       po::collect_unrecognized(final_parsed.options, po::include_positional);
01430 
01431     po::store(final_parsed, vm);
01432 
01433   }
01434   catch (po::validation_error &err)
01435   {
01436     errmsg_printf(error::ERROR,
01437                   _("%s: %s.\n"
01438                     "Use --help to get a list of available options\n"),
01439                   internal::my_progname, err.what());
01440     unireg_abort(1);
01441   }
01442   catch (po::invalid_command_line_syntax &err)
01443   {
01444     errmsg_printf(error::ERROR,
01445                   _("%s: %s.\n"
01446                     "Use --help to get a list of available options\n"),
01447                   internal::my_progname, err.what());
01448     unireg_abort(1);
01449   }
01450   catch (po::unknown_option &err)
01451   {
01452     errmsg_printf(error::ERROR,
01453                   _("%s\nUse --help to get a list of available options\n"),
01454                   err.what());
01455     unireg_abort(1);
01456   }
01457 
01458   try
01459   {
01460     po::notify(vm);
01461   }
01462   catch (po::validation_error &err)
01463   {
01464     errmsg_printf(error::ERROR,
01465                   _("%s: %s.\n"
01466                     "Use --help to get a list of available options\n"),
01467                   internal::my_progname, err.what());
01468     unireg_abort(1);
01469   }
01470 
01471   get_options();
01472 
01473   /* Inverted Booleans */
01474 
01475   global_system_variables.optimizer_prune_level=
01476     vm.count("disable-optimizer-prune") ? false : true;
01477 
01478   if (! vm["help"].as<bool>())
01479   {
01480     if ((user_info= check_user(drizzled_user)))
01481     {
01482       set_user(drizzled_user, user_info);
01483     }
01484   }
01485 
01486   fix_paths();
01487 
01488   init_time();        /* Init time-functions (read zone) */
01489 
01490   if (item_create_init())
01491     return 1;
01492   if (sys_var_init())
01493     return 1;
01494   /* Creates static regex matching for temporal values */
01495   if (! init_temporal_formats())
01496     return 1;
01497 
01498   if (!(default_charset_info=
01499         get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
01500   {
01501     errmsg_printf(error::ERROR, _("Error getting default charset"));
01502     return 1;                           // Eof of the list
01503   }
01504 
01505   if (vm.count("scheduler"))
01506     opt_scheduler= vm["scheduler"].as<string>().c_str();
01507 
01508   if (default_collation_name)
01509   {
01510     const CHARSET_INFO * const default_collation= get_charset_by_name(default_collation_name);
01511     if (not default_collation)
01512     {
01513       errmsg_printf(error::ERROR, _(ER(ER_UNKNOWN_COLLATION)), default_collation_name);
01514       return 1;
01515     }
01516     if (not my_charset_same(default_charset_info, default_collation))
01517     {
01518       errmsg_printf(error::ERROR, _(ER(ER_COLLATION_CHARSET_MISMATCH)),
01519                     default_collation_name,
01520                     default_charset_info->csname);
01521       return 1;
01522     }
01523     default_charset_info= default_collation;
01524   }
01525   /* Set collactions that depends on the default collation */
01526   global_system_variables.collation_server=  default_charset_info;
01527 
01528   if (not (character_set_filesystem=
01529            get_charset_by_csname(character_set_filesystem_name, MY_CS_PRIMARY)))
01530   {
01531     errmsg_printf(error::ERROR, _("Error setting collation"));
01532     return 1;
01533   }
01534   global_system_variables.character_set_filesystem= character_set_filesystem;
01535 
01536   if (!(my_default_lc_time_names=
01537         my_locale_by_name(lc_time_names_name)))
01538   {
01539     errmsg_printf(error::ERROR, _("Unknown locale: '%s'"), lc_time_names_name);
01540     return 1;
01541   }
01542   global_system_variables.lc_time_names= my_default_lc_time_names;
01543 
01544   /* Reset table_alias_charset */
01545   table_alias_charset= files_charset_info;
01546 
01547   return 0;
01548 }
01549 
01550 
01551 int init_server_components(module::Registry &plugins)
01552 {
01553   /*
01554     We need to call each of these following functions to ensure that
01555     all things are initialized so that unireg_abort() doesn't fail
01556   */
01557   if (table_cache_init())
01558   {
01559     errmsg_printf(error::ERROR, _("Could not initialize table cache\n"));
01560     unireg_abort(1);
01561   }
01562 
01563   // Resize the definition Cache at startup
01564   table::Cache::singleton().rehash(table_def_size);
01565   definition::Cache::singleton().rehash(table_def_size);
01566   message::Cache::singleton().rehash(table_def_size);
01567 
01568   setup_fpu();
01569 
01570   /* Allow storage engine to give real error messages */
01571   ha_init_errors();
01572 
01573 
01574   if (opt_help)
01575     unireg_abort(0);
01576 
01577   if (plugin_finalize(plugins))
01578   {
01579     unireg_abort(1);
01580   }
01581 
01582   string scheduler_name;
01583   if (opt_scheduler)
01584   {
01585     scheduler_name= opt_scheduler;
01586   }
01587   else
01588   {
01589     scheduler_name= opt_scheduler_default;
01590     opt_scheduler= opt_scheduler_default;
01591   }
01592 
01593   if (plugin::Scheduler::setPlugin(scheduler_name))
01594   {
01595       errmsg_printf(error::ERROR,
01596                    _("No scheduler found, cannot continue!\n"));
01597       unireg_abort(1);
01598   }
01599 
01600   /*
01601     This is entirely for legacy. We will create a new "disk based" engine and a
01602     "memory" engine which will be configurable longterm.
01603   */
01604   const std::string myisam_engine_name("MyISAM");
01605   const std::string heap_engine_name("MEMORY");
01606   myisam_engine= plugin::StorageEngine::findByName(myisam_engine_name);
01607   heap_engine= plugin::StorageEngine::findByName(heap_engine_name);
01608 
01609   /*
01610     Check that the default storage engine is actually available.
01611   */
01612   if (default_storage_engine_str)
01613   {
01614     const std::string name(default_storage_engine_str);
01615     plugin::StorageEngine *engine;
01616 
01617     engine= plugin::StorageEngine::findByName(name);
01618     if (engine == NULL)
01619     {
01620       errmsg_printf(error::ERROR, _("Unknown/unsupported storage engine: %s\n"),
01621                     default_storage_engine_str);
01622       unireg_abort(1);
01623     }
01624     global_system_variables.storage_engine= engine;
01625   }
01626 
01627   if (plugin::XaResourceManager::recoverAllXids())
01628   {
01629     /* This function alredy generates error messages */
01630     unireg_abort(1);
01631   }
01632 
01633   init_update_queries();
01634 
01635   return(0);
01636 }
01637 
01638 
01639 /****************************************************************************
01640   Handle start options
01641 ******************************************************************************/
01642 
01643 enum options_drizzled
01644 {
01645   OPT_SOCKET=256,
01646   OPT_BIND_ADDRESS,
01647   OPT_PID_FILE,
01648   OPT_STORAGE_ENGINE,
01649   OPT_INIT_FILE,
01650   OPT_WANT_CORE,
01651   OPT_MEMLOCK,
01652   OPT_SERVER_ID,
01653   OPT_TC_HEURISTIC_RECOVER,
01654   OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
01655   OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
01656   OPT_DO_PSTACK,
01657   OPT_LOCAL_INFILE,
01658   OPT_BACK_LOG,
01659   OPT_JOIN_BUFF_SIZE,
01660   OPT_MAX_ALLOWED_PACKET,
01661   OPT_MAX_HEP_TABLE_SIZE,
01662   OPT_MAX_JOIN_SIZE,
01663   OPT_MAX_SORT_LENGTH,
01664   OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
01665   OPT_MAX_LENGTH_FOR_SORT_DATA,
01666   OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
01667   OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
01668   OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
01669   OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
01670   OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS,
01671   OPT_NET_BUFFER_LENGTH,
01672   OPT_PRELOAD_BUFFER_SIZE,
01673   OPT_RECORD_BUFFER,
01674   OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT,
01675   OPT_DEBUGGING,
01676   OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
01677   OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
01678   OPT_WAIT_TIMEOUT,
01679   OPT_RANGE_ALLOC_BLOCK_SIZE,
01680   OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
01681   OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
01682   OPT_OLD_ALTER_TABLE,
01683   OPT_GROUP_CONCAT_MAX_LEN,
01684   OPT_DEFAULT_COLLATION,
01685   OPT_CHARACTER_SET_FILESYSTEM,
01686   OPT_LC_TIME_NAMES,
01687   OPT_INIT_CONNECT,
01688   OPT_DEFAULT_TIME_ZONE,
01689   OPT_OPTIMIZER_SEARCH_DEPTH,
01690   OPT_SCHEDULER,
01691   OPT_PROTOCOL,
01692   OPT_OPTIMIZER_PRUNE_LEVEL,
01693   OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
01694   OPT_ENABLE_LARGE_PAGES,
01695   OPT_TIMED_MUTEXES,
01696   OPT_TABLE_LOCK_WAIT_TIMEOUT,
01697   OPT_PLUGIN_ADD,
01698   OPT_PLUGIN_REMOVE,
01699   OPT_PLUGIN_LOAD,
01700   OPT_PLUGIN_DIR,
01701   OPT_PORT_OPEN_TIMEOUT,
01702   OPT_SECURE_FILE_PRIV,
01703   OPT_MIN_EXAMINED_ROW_LIMIT,
01704   OPT_PRINT_DEFAULTS
01705 };
01706 
01707 
01708 struct option my_long_options[] =
01709 {
01710 
01711   {"help", '?', N_("Display this help and exit."),
01712    (char**) &opt_help, (char**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
01713    0, 0},
01714   {"daemon", 'd', N_("Run as daemon."),
01715    (char**) &opt_daemon, (char**) &opt_daemon, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
01716    0, 0},
01717   {"auto-increment-increment", OPT_AUTO_INCREMENT,
01718    N_("Auto-increment columns are incremented by this"),
01719    (char**) &global_system_variables.auto_increment_increment,
01720    (char**) &max_system_variables.auto_increment_increment, 0, GET_ULL,
01721    OPT_ARG, 1, 1, INT64_MAX, 0, 1, 0 },
01722   {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
01723    N_("Offset added to Auto-increment columns. Used when "
01724       "auto-increment-increment != 1"),
01725    (char**) &global_system_variables.auto_increment_offset,
01726    (char**) &max_system_variables.auto_increment_offset, 0, GET_ULL, OPT_ARG,
01727    1, 1, INT64_MAX, 0, 1, 0 },
01728   {"basedir", 'b',
01729    N_("Path to installation directory. All paths are usually resolved "
01730       "relative to this."),
01731    NULL, NULL, 0, GET_STR, REQUIRED_ARG,
01732    0, 0, 0, 0, 0, 0},
01733   {"chroot", 'r',
01734    N_("Chroot drizzled daemon during startup."),
01735    (char**) &drizzled_chroot, (char**) &drizzled_chroot, 0, GET_STR, REQUIRED_ARG,
01736    0, 0, 0, 0, 0, 0},
01737   {"collation-server", OPT_DEFAULT_COLLATION,
01738    N_("Set the default collation."),
01739    (char**) &default_collation_name, (char**) &default_collation_name,
01740    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
01741   {"completion-type", OPT_COMPLETION_TYPE,
01742    N_("Default completion type."),
01743    (char**) &global_system_variables.completion_type,
01744    (char**) &max_system_variables.completion_type, 0, GET_UINT,
01745    REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
01746   {"core-file", OPT_WANT_CORE,
01747    N_("Write core on errors."),
01748    0, 0, 0, GET_NO_ARG,
01749    NO_ARG, 0, 0, 0, 0, 0, 0},
01750   {"datadir", 'h',
01751    N_("Path to the database root."),
01752    NULL, NULL, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01753   /* See how it's handled in get_one_option() */
01754   {"exit-info", 'T',
01755    N_("Used for debugging;  Use at your own risk!"),
01756    0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
01757   /* We must always support the next option to make scripts like mysqltest
01758      easier to do */
01759   {"gdb", OPT_DEBUGGING,
01760    N_("Set up signals usable for debugging"),
01761    (char**) &opt_debugging, (char**) &opt_debugging,
01762    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
01763   {"log-warnings", 'W',
01764    N_("Log some not critical warnings to the log file."),
01765    (char**) &global_system_variables.log_warnings,
01766    (char**) &max_system_variables.log_warnings, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
01767    0, 0, 0},
01768   {"pid-file", OPT_PID_FILE,
01769    N_("Pid file used by drizzled."),
01770    NULL, NULL, 0, GET_STR,
01771    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01772   {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
01773    N_("Maximum time in seconds to wait for the port to become free. "
01774       "(Default: no wait)"),
01775    (char**) &drizzled_bind_timeout,
01776    (char**) &drizzled_bind_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01777   {"secure-file-priv", OPT_SECURE_FILE_PRIV,
01778    N_("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
01779       "within specified directory"),
01780    NULL, NULL, 0,
01781    GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01782   {"server-id", OPT_SERVER_ID,
01783    N_("Uniquely identifies the server instance in the community of "
01784       "replication partners."),
01785    (char**) &server_id, (char**) &server_id, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 0,
01786    0, 0, 0},
01787   {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
01788    N_("Don't print a stack trace on failure."),
01789    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
01790    0, 0, 0, 0},
01791   {"symbolic-links", 's',
01792    N_("Enable symbolic link support."),
01793    (char**) &internal::my_use_symdir, (char**) &internal::my_use_symdir, 0, GET_BOOL, NO_ARG,
01794    /*
01795      The system call realpath() produces warnings under valgrind and
01796      purify. These are not suppressed: instead we disable symlinks
01797      option if compiled with valgrind support.
01798    */
01799    IF_PURIFY(0,1), 0, 0, 0, 0, 0},
01800   {"timed_mutexes", OPT_TIMED_MUTEXES,
01801    N_("Specify whether to time mutexes (only InnoDB mutexes are currently "
01802       "supported)"),
01803    (char**) &internal::timed_mutexes, (char**) &internal::timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
01804     0, 0, 0, 0, 0},
01805   {"transaction-isolation", OPT_TX_ISOLATION,
01806    N_("Default transaction isolation level."),
01807    0, 0, 0, GET_STR, REQUIRED_ARG, 0,
01808    0, 0, 0, 0, 0},
01809   {"user", 'u',
01810    N_("Run drizzled daemon as user."),
01811    0, 0, 0, GET_STR, REQUIRED_ARG,
01812    0, 0, 0, 0, 0, 0},
01813   {"back_log", OPT_BACK_LOG,
01814    N_("The number of outstanding connection requests Drizzle can have. This "
01815       "comes into play when the main Drizzle thread gets very many connection "
01816       "requests in a very short time."),
01817     (char**) &back_log, (char**) &back_log, 0, GET_UINT,
01818     REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
01819   { "bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
01820     N_("Size of tree cache used in bulk insert optimization. Note that this is "
01821        "a limit per thread!"),
01822     (char**) &global_system_variables.bulk_insert_buff_size,
01823     (char**) &max_system_variables.bulk_insert_buff_size,
01824     0, GET_ULL, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0},
01825   { "div_precision_increment", OPT_DIV_PRECINCREMENT,
01826    N_("Precision of the result of '/' operator will be increased on that "
01827       "value."),
01828    (char**) &global_system_variables.div_precincrement,
01829    (char**) &max_system_variables.div_precincrement, 0, GET_UINT,
01830    REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
01831   { "join_buffer_size", OPT_JOIN_BUFF_SIZE,
01832     N_("The size of the buffer that is used for full joins."),
01833    (char**) &global_system_variables.join_buff_size,
01834    (char**) &max_system_variables.join_buff_size, 0, GET_UINT64,
01835    REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX,
01836    MALLOC_OVERHEAD, IO_SIZE, 0},
01837   {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
01838    N_("Max packetlength to send/receive from to server."),
01839    (char**) &global_system_variables.max_allowed_packet,
01840    (char**) &max_system_variables.max_allowed_packet, 0, GET_UINT32,
01841    REQUIRED_ARG, 64*1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
01842   {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
01843    N_("Don't allow creation of heap tables bigger than this."),
01844    (char**) &global_system_variables.max_heap_table_size,
01845    (char**) &max_system_variables.max_heap_table_size, 0, GET_ULL,
01846    REQUIRED_ARG, 16*1024*1024L, 16384, (int64_t)MAX_MEM_TABLE_SIZE,
01847    MALLOC_OVERHEAD, 1024, 0},
01848   {"max_join_size", OPT_MAX_JOIN_SIZE,
01849    N_("Joins that are probably going to read more than max_join_size records "
01850       "return an error."),
01851    (char**) &global_system_variables.max_join_size,
01852    (char**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
01853    INT32_MAX, 1, INT32_MAX, 0, 1, 0},
01854   {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
01855    N_("Max number of bytes in sorted records."),
01856    (char**) &global_system_variables.max_length_for_sort_data,
01857    (char**) &max_system_variables.max_length_for_sort_data, 0, GET_ULL,
01858    REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
01859   { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
01860     N_("Limit assumed max number of seeks when looking up rows based on a key"),
01861     (char**) &global_system_variables.max_seeks_for_key,
01862     (char**) &max_system_variables.max_seeks_for_key, 0, GET_UINT64,
01863     REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 },
01864   {"max_sort_length", OPT_MAX_SORT_LENGTH,
01865    N_("The number of bytes to use when sorting BLOB or TEXT values "
01866       "(only the first max_sort_length bytes of each value are used; the "
01867       "rest are ignored)."),
01868    (char**) &global_system_variables.max_sort_length,
01869    (char**) &max_system_variables.max_sort_length, 0, GET_SIZE,
01870    REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
01871   {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
01872    N_("After this many write locks, allow some read locks to run in between."),
01873    (char**) &max_write_lock_count, (char**) &max_write_lock_count, 0, GET_ULL,
01874    REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0},
01875   {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
01876    N_("Don't log queries which examine less than min_examined_row_limit "
01877       "rows to file."),
01878    (char**) &global_system_variables.min_examined_row_limit,
01879    (char**) &max_system_variables.min_examined_row_limit, 0, GET_ULL,
01880    REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0},
01881   {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
01882     N_("Controls the heuristic(s) applied during query optimization to prune "
01883        "less-promising partial plans from the optimizer search space. Meaning: "
01884        "false - do not apply any heuristic, thus perform exhaustive search; "
01885        "true - prune plans based on number of retrieved rows."),
01886     (char**) &global_system_variables.optimizer_prune_level,
01887     (char**) &max_system_variables.optimizer_prune_level,
01888     0, GET_BOOL, OPT_ARG, 1, 0, 1, 0, 1, 0},
01889   {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
01890    N_("Maximum depth of search performed by the query optimizer. Values "
01891       "larger than the number of relations in a query result in better query "
01892       "plans, but take longer to compile a query. Smaller values than the "
01893       "number of tables in a relation result in faster optimization, but may "
01894       "produce very bad query plans. If set to 0, the system will "
01895       "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
01896       "optimizer will switch to the original find_best (used for "
01897       "testing/comparison)."),
01898    (char**) &global_system_variables.optimizer_search_depth,
01899    (char**) &max_system_variables.optimizer_search_depth,
01900    0, GET_UINT, OPT_ARG, 0, 0, MAX_TABLES+2, 0, 1, 0},
01901   {"plugin_dir", OPT_PLUGIN_DIR,
01902    N_("Directory for plugins."),
01903    NULL, NULL, 0,
01904    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01905   {"plugin_add", OPT_PLUGIN_ADD,
01906    N_("Optional comma separated list of plugins to load at startup in addition "
01907       "to the default list of plugins. "
01908       "[for example: --plugin_add=crc32,logger_gearman]"),
01909    NULL, NULL, 0,
01910    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01911   {"plugin_remove", OPT_PLUGIN_ADD,
01912    N_("Optional comma separated list of plugins to not load at startup. Effectively "
01913       "removes a plugin from the list of plugins to be loaded. "
01914       "[for example: --plugin_remove=crc32,logger_gearman]"),
01915    NULL, NULL, 0,
01916    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01917   {"plugin_load", OPT_PLUGIN_LOAD,
01918    N_("Optional comma separated list of plugins to load at starup instead of "
01919       "the default plugin load list. "
01920       "[for example: --plugin_load=crc32,logger_gearman]"),
01921    NULL, NULL, 0,
01922    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
01923   {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
01924    N_("The size of the buffer that is allocated when preloading indexes"),
01925    (char**) &global_system_variables.preload_buff_size,
01926    (char**) &max_system_variables.preload_buff_size, 0, GET_ULL,
01927    REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
01928   {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
01929    N_("Allocation block size for query parsing and execution"),
01930    (char**) &global_system_variables.query_alloc_block_size,
01931    (char**) &max_system_variables.query_alloc_block_size, 0, GET_UINT,
01932    REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0},
01933   {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
01934    N_("Persistent buffer for query parsing and execution"),
01935    (char**) &global_system_variables.query_prealloc_size,
01936    (char**) &max_system_variables.query_prealloc_size, 0, GET_UINT,
01937    REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
01938    ULONG_MAX, 0, 1024, 0},
01939   {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
01940    N_("Allocation block size for storing ranges during optimization"),
01941    (char**) &global_system_variables.range_alloc_block_size,
01942    (char**) &max_system_variables.range_alloc_block_size, 0, GET_SIZE,
01943    REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, (int64_t)SIZE_MAX,
01944    0, 1024, 0},
01945   {"read_buffer_size", OPT_RECORD_BUFFER,
01946     N_("Each thread that does a sequential scan allocates a buffer of this "
01947        "size for each table it scans. If you do many sequential scans, you may "
01948        "want to increase this value."),
01949     (char**) &global_system_variables.read_buff_size,
01950     (char**) &max_system_variables.read_buff_size,0, GET_UINT, REQUIRED_ARG,
01951     128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT32_MAX, MALLOC_OVERHEAD, IO_SIZE,
01952     0},
01953   {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
01954    N_("When reading rows in sorted order after a sort, the rows are read "
01955       "through this buffer to avoid a disk seeks. If not set, then it's set "
01956       "to the value of record_buffer."),
01957    (char**) &global_system_variables.read_rnd_buff_size,
01958    (char**) &max_system_variables.read_rnd_buff_size, 0,
01959    GET_UINT, REQUIRED_ARG, 256*1024L, 64 /*IO_SIZE*2+MALLOC_OVERHEAD*/ ,
01960    UINT32_MAX, MALLOC_OVERHEAD, 1 /* Small lower limit to be able to test MRR */, 0},
01961   /* x8 compared to MySQL's x2. We have UTF8 to consider. */
01962   {"sort_buffer_size", OPT_SORT_BUFFER,
01963    N_("Each thread that needs to do a sort allocates a buffer of this size."),
01964    (char**) &global_system_variables.sortbuff_size,
01965    (char**) &max_system_variables.sortbuff_size, 0, GET_SIZE, REQUIRED_ARG,
01966    MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*8, (int64_t)SIZE_MAX,
01967    MALLOC_OVERHEAD, 1, 0},
01968   {"table_definition_cache", OPT_TABLE_DEF_CACHE,
01969    N_("The number of cached table definitions."),
01970    (char**) &table_def_size, (char**) &table_def_size,
01971    0, GET_SIZE, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0},
01972   {"table_open_cache", OPT_TABLE_OPEN_CACHE,
01973    N_("The number of cached open tables."),
01974    (char**) &table_cache_size, (char**) &table_cache_size, 0, GET_UINT64,
01975    REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, TABLE_OPEN_CACHE_MIN, 512*1024L, 0, 1, 0},
01976   {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT,
01977    N_("Timeout in seconds to wait for a table level lock before returning an "
01978       "error. Used only if the connection has active cursors."),
01979    (char**) &table_lock_wait_timeout, (char**) &table_lock_wait_timeout,
01980    0, GET_ULL, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
01981   {"thread_stack", OPT_THREAD_STACK,
01982    N_("The stack size for each thread."),
01983    (char**) &my_thread_stack_size,
01984    (char**) &my_thread_stack_size, 0, GET_SIZE,
01985    REQUIRED_ARG,DEFAULT_THREAD_STACK,
01986    UINT32_C(1024*512), (int64_t)SIZE_MAX, 0, 1024, 0},
01987   {"tmp_table_size", OPT_TMP_TABLE_SIZE,
01988    N_("If an internal in-memory temporary table exceeds this size, Drizzle will"
01989       " automatically convert it to an on-disk MyISAM table."),
01990    (char**) &global_system_variables.tmp_table_size,
01991    (char**) &max_system_variables.tmp_table_size, 0, GET_ULL,
01992    REQUIRED_ARG, 16*1024*1024L, 1024, (int64_t)MAX_MEM_TABLE_SIZE, 0, 1, 0},
01993   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
01994 };
01995 
01996 static void print_version(void)
01997 {
01998   /*
01999     Note: the instance manager keys off the string 'Ver' so it can find the
02000     version from the output of 'drizzled --version', so don't change it!
02001   */
02002   printf("%s  Ver %s for %s-%s on %s (%s)\n",internal::my_progname,
02003    PANDORA_RELEASE_VERSION, HOST_VENDOR, HOST_OS, HOST_CPU,
02004          COMPILATION_COMMENT);
02005 }
02006 
02007 static void usage(void)
02008 {
02009   if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
02010     exit(1);
02011   if (!default_collation_name)
02012     default_collation_name= (char*) default_charset_info->name;
02013   print_version();
02014   puts(_("Copyright (C) 2008 Sun Microsystems\n"
02015          "This software comes with ABSOLUTELY NO WARRANTY. "
02016          "This is free software,\n"
02017          "and you are welcome to modify and redistribute it under the GPL "
02018          "license\n\n"));
02019 
02020 
02021   printf(_("Usage: %s [OPTIONS]\n"), internal::my_progname);
02022 
02023   po::options_description all_options("Drizzled Options");
02024   all_options.add(config_options);
02025   all_options.add(plugin_load_options);
02026   all_options.add(long_options);
02027   all_options.add(plugin_options);
02028   cout << all_options << endl;
02029 
02030 }
02031 
02048 static void drizzle_init_variables(void)
02049 {
02050   /* Things reset to zero */
02051   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
02052   cleanup_done= 0;
02053   dropping_tables= ha_open_options=0;
02054   getDebug().reset();
02055   wake_thread=0;
02056   abort_loop= select_thread_in_use= false;
02057   shutdown_in_progress= 0;
02058   drizzled_user= drizzled_chroot= 0;
02059   memset(&current_global_counters, 0, sizeof(current_global_counters));
02060   key_map_full.set();
02061 
02062   /* Character sets */
02063   system_charset_info= &my_charset_utf8_general_ci;
02064   files_charset_info= &my_charset_utf8_general_ci;
02065   table_alias_charset= &my_charset_bin;
02066   character_set_filesystem= &my_charset_bin;
02067 
02068   /* Things with default values that are not zero */
02069   session_startup_options= (OPTION_AUTO_IS_NULL | OPTION_SQL_NOTES);
02070   refresh_version= 1L;  /* Increments on each reload */
02071   global_thread_id= 1UL;
02072   session::Cache::singleton().getCache().clear();
02073 
02074   /* Variables in libraries */
02075   default_character_set_name= "utf8";
02076   default_collation_name= (char *)compiled_default_collation_name;
02077   character_set_filesystem_name= "binary";
02078   lc_time_names_name= (char*) "en_US";
02079   /* Set default values for some option variables */
02080   default_storage_engine_str= (char*) "innodb";
02081   global_system_variables.storage_engine= NULL;
02082   global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
02083   global_system_variables.select_limit= (uint64_t) HA_POS_ERROR;
02084   max_system_variables.select_limit=    (uint64_t) HA_POS_ERROR;
02085   global_system_variables.max_join_size= (uint64_t) HA_POS_ERROR;
02086   max_system_variables.max_join_size=   (uint64_t) HA_POS_ERROR;
02087   max_system_variables.auto_increment_increment= UINT64_MAX;
02088   max_system_variables.auto_increment_offset= UINT64_MAX;
02089   max_system_variables.completion_type= 2;
02090   max_system_variables.log_warnings= true;
02091   max_system_variables.bulk_insert_buff_size= ULONG_MAX;
02092   max_system_variables.div_precincrement= DECIMAL_MAX_SCALE;
02093   max_system_variables.group_concat_max_len= ULONG_MAX;
02094   max_system_variables.join_buff_size= ULONG_MAX;
02095   max_system_variables.max_allowed_packet= 1024L*1024L*1024L;
02096   max_system_variables.max_error_count= 65535;
02097   max_system_variables.max_heap_table_size= MAX_MEM_TABLE_SIZE;
02098   max_system_variables.max_join_size= INT32_MAX;
02099   max_system_variables.max_length_for_sort_data= 8192*1024L;
02100   max_system_variables.max_seeks_for_key= ULONG_MAX;
02101   max_system_variables.max_sort_length= 8192*1024L;
02102   max_system_variables.min_examined_row_limit= ULONG_MAX;
02103   max_system_variables.optimizer_prune_level= 1;
02104   max_system_variables.optimizer_search_depth= MAX_TABLES+2;
02105   max_system_variables.preload_buff_size= 1024*1024*1024L;
02106   max_system_variables.query_alloc_block_size= UINT32_MAX;
02107   max_system_variables.query_prealloc_size= UINT32_MAX;
02108   max_system_variables.range_alloc_block_size= SIZE_MAX;
02109   max_system_variables.read_buff_size= INT32_MAX;
02110   max_system_variables.read_rnd_buff_size= UINT32_MAX;
02111   max_system_variables.sortbuff_size= SIZE_MAX;
02112   max_system_variables.tmp_table_size= MAX_MEM_TABLE_SIZE;
02113 
02114   opt_scheduler_default= (char*) "multi_thread";
02115 
02116   /* Variables that depends on compile options */
02117 #ifdef HAVE_BROKEN_REALPATH
02118   have_symlink=SHOW_OPTION_NO;
02119 #else
02120   have_symlink=SHOW_OPTION_YES;
02121 #endif
02122 }
02123 
02124 
02129 static void get_options()
02130 {
02131 
02132   fs::path &data_home_catalog= getDataHomeCatalog();
02133   data_home_catalog= getDataHome();
02134   data_home_catalog /= "local";
02135 
02136   if (vm.count("user"))
02137   {
02138     if (! drizzled_user || ! strcmp(drizzled_user, vm["user"].as<string>().c_str()))
02139       drizzled_user= (char *)vm["user"].as<string>().c_str();
02140 
02141     else
02142       errmsg_printf(error::WARN, _("Ignoring user change to '%s' because the user was "
02143                                        "set to '%s' earlier on the command line\n"),
02144                     vm["user"].as<string>().c_str(), drizzled_user);
02145   }
02146 
02147   if (vm.count("version"))
02148   {
02149     print_version();
02150     exit(0);
02151   }
02152 
02153   if (vm.count("sort-heap-threshold"))
02154   {
02155     if ((vm["sort-heap-threshold"].as<uint64_t>() > 0) and
02156       (vm["sort-heap-threshold"].as<uint64_t>() <
02157       global_system_variables.sortbuff_size))
02158     {
02159       cout << _("Error: sort-heap-threshold cannot be less than sort-buffer-size") << endl;
02160       exit(-1);
02161     }
02162 
02163     global_sort_buffer.setMaxSize(vm["sort-heap-threshold"].as<uint64_t>());
02164   }
02165 
02166   if (vm.count("join-heap-threshold"))
02167   {
02168     if ((vm["join-heap-threshold"].as<uint64_t>() > 0) and
02169       (vm["join-heap-threshold"].as<uint64_t>() <
02170       global_system_variables.join_buff_size))
02171     {
02172       cout << _("Error: join-heap-threshold cannot be less than join-buffer-size") << endl;
02173       exit(-1);
02174     }
02175 
02176     global_join_buffer.setMaxSize(vm["join-heap-threshold"].as<uint64_t>());
02177   }
02178 
02179   if (vm.count("read-rnd-threshold"))
02180   {
02181     if ((vm["read-rnd-threshold"].as<uint64_t>() > 0) and
02182       (vm["read-rnd-threshold"].as<uint64_t>() <
02183       global_system_variables.read_rnd_buff_size))
02184     {
02185       cout << _("Error: read-rnd-threshold cannot be less than read-rnd-buffer-size") << endl;
02186       exit(-1);
02187     }
02188 
02189     global_read_rnd_buffer.setMaxSize(vm["read-rnd-threshold"].as<uint64_t>());
02190   }
02191 
02192   if (vm.count("read-buffer-threshold"))
02193   {
02194     if ((vm["read-buffer-threshold"].as<uint64_t>() > 0) and
02195       (vm["read-buffer-threshold"].as<uint64_t>() <
02196       global_system_variables.read_buff_size))
02197     {
02198       cout << _("Error: read-buffer-threshold cannot be less than read-buffer-size") << endl;
02199       exit(-1);
02200     }
02201 
02202     global_read_buffer.setMaxSize(vm["read-buffer-threshold"].as<uint64_t>());
02203   }
02204 
02205   if (vm.count("exit-info"))
02206   {
02207     if (vm["exit-info"].as<long>())
02208     {
02209       getDebug().set((uint32_t) vm["exit-info"].as<long>());
02210     }
02211   }
02212 
02213   if (vm.count("want-core"))
02214   {
02215     getDebug().set(debug::CORE_ON_SIGNAL);
02216   }
02217 
02218   if (vm.count("skip-stack-trace"))
02219   {
02220     getDebug().set(debug::NO_STACKTRACE);
02221   }
02222 
02223   if (vm.count("skip-symlinks"))
02224   {
02225     internal::my_use_symdir=0;
02226   }
02227 
02228   if (vm.count("transaction-isolation"))
02229   {
02230     int type= tx_isolation_typelib.find_type_or_exit(vm["transaction-isolation"].as<string>().c_str(), "transaction-isolation");
02231     global_system_variables.tx_isolation= type - 1;
02232   }
02233 
02234   /* @TODO Make this all strings */
02235   if (vm.count("default-storage-engine"))
02236   {
02237     default_storage_engine_str= (char *)vm["default-storage-engine"].as<string>().c_str();
02238   }
02239 
02240   /* Skip unknown options so that they may be processed later by plugins */
02241   my_getopt_skip_unknown= true;
02242 
02243 
02244 #if defined(HAVE_BROKEN_REALPATH)
02245   internal::my_use_symdir=0;
02246   internal::my_disable_symlinks=1;
02247   have_symlink=SHOW_OPTION_NO;
02248 #else
02249   if (!internal::my_use_symdir)
02250   {
02251     internal::my_disable_symlinks=1;
02252     have_symlink=SHOW_OPTION_DISABLED;
02253   }
02254 #endif
02255   if (opt_debugging)
02256   {
02257     /* Allow break with SIGINT, no core or stack trace */
02258     getDebug().set(debug::ALLOW_SIGINT);
02259     getDebug().set(debug::NO_STACKTRACE);
02260     getDebug().reset(debug::CORE_ON_SIGNAL);
02261   }
02262 
02263   if (drizzled_chroot)
02264     set_root(drizzled_chroot);
02265 
02266   /*
02267     Set some global variables from the global_system_variables
02268     In most cases the global variables will not be used
02269   */
02270   internal::my_default_record_cache_size=global_system_variables.read_buff_size;
02271 }
02272 
02273 
02274 static void fix_paths()
02275 {
02276   fs::path pid_file_path(pid_file);
02277   if (pid_file_path.root_path().string() == "")
02278   {
02279     pid_file_path= getDataHome();
02280     pid_file_path /= pid_file;
02281   }
02282   pid_file= fs::system_complete(pid_file_path);
02283 
02284   if (not opt_help)
02285   {
02286     const char *tmp_string= getenv("TMPDIR") ? getenv("TMPDIR") : NULL;
02287     struct stat buf;
02288     drizzle_tmpdir.clear();
02289 
02290     if (vm.count("tmpdir"))
02291     {
02292       drizzle_tmpdir.append(vm["tmpdir"].as<string>());
02293     }
02294     else if (tmp_string == NULL)
02295     {
02296       drizzle_tmpdir.append(getDataHome().file_string());
02297       drizzle_tmpdir.push_back(FN_LIBCHAR);
02298       drizzle_tmpdir.append(GLOBAL_TEMPORARY_EXT);
02299     }
02300     else
02301     {
02302       drizzle_tmpdir.append(tmp_string);
02303     }
02304 
02305     drizzle_tmpdir= fs::path(fs::system_complete(fs::path(drizzle_tmpdir))).file_string();
02306     assert(drizzle_tmpdir.size());
02307 
02308     if (mkdir(drizzle_tmpdir.c_str(), 0777) == -1)
02309     {
02310       if (errno != EEXIST)
02311       {
02312         errmsg_printf(error::ERROR, _("There was an error creating the '%s' part of the path '%s'.  Please check the path exists and is writable.\n"), fs::path(drizzle_tmpdir).leaf().c_str(), drizzle_tmpdir.c_str());
02313         exit(1);
02314       }
02315     }
02316 
02317     if (stat(drizzle_tmpdir.c_str(), &buf) || (S_ISDIR(buf.st_mode) == false))
02318     {
02319       errmsg_printf(error::ERROR, _("There was an error opening the path '%s', please check the path exists and is writable.\n"), drizzle_tmpdir.c_str());
02320       exit(1);
02321     }
02322   }
02323 
02324 }
02325 
02326 } /* namespace drizzled */
02327