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