Drizzled Public API Documentation

drizzled.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <config.h>
21 
22 #include <drizzled/configmake.h>
23 #include <drizzled/atomics.h>
24 #include <drizzled/data_home.h>
25 
26 #include <climits>
27 #include <fcntl.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
31 #include <signal.h>
32 #include <stdexcept>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <sys/types.h>
36 
37 #include <boost/program_options.hpp>
38 #include <drizzled/program_options/config_file.h>
39 #include <boost/thread/recursive_mutex.hpp>
40 #include <boost/thread/mutex.hpp>
41 #include <boost/thread/shared_mutex.hpp>
42 #include <boost/thread/condition_variable.hpp>
43 #include <boost/filesystem.hpp>
44 #include <boost/detail/atomic_count.hpp>
45 
47 #include <drizzled/charset.h>
48 #include <drizzled/data_home.h>
49 #include <drizzled/debug.h>
50 #include <drizzled/definition/cache.h>
51 #include <drizzled/drizzled.h>
52 #include <drizzled/errmsg_print.h>
53 #include <drizzled/error.h>
54 #include <drizzled/global_buffer.h>
55 #include <drizzled/internal/my_bit.h>
56 #include <drizzled/internal/my_sys.h>
57 #include <drizzled/item/cmpfunc.h>
58 #include <drizzled/item/create.h>
59 #include <drizzled/message/cache.h>
60 #include <drizzled/module/load_list.h>
61 #include <drizzled/module/registry.h>
62 #include <drizzled/plugin/client.h>
63 #include <drizzled/plugin/error_message.h>
64 #include <drizzled/plugin/event_observer.h>
65 #include <drizzled/plugin/listen.h>
66 #include <drizzled/plugin/monitored_in_transaction.h>
67 #include <drizzled/plugin/scheduler.h>
68 #include <drizzled/plugin/storage_engine.h>
69 #include <drizzled/plugin/xa_resource_manager.h>
70 #include <drizzled/probes.h>
71 #include <drizzled/replication_services.h> /* For ReplicationServices::evaluateRegisteredPlugins() */
72 #include <drizzled/session.h>
73 #include <drizzled/session/cache.h>
74 #include <drizzled/show.h>
75 #include <drizzled/sql_base.h>
76 #include <drizzled/sql_parse.h>
77 #include <drizzled/statistics_variables.h>
78 #include <drizzled/table/cache.h>
79 #include <drizzled/temporal_format.h> /* For init_temporal_formats() */
80 #include <drizzled/unireg.h>
81 #include <plugin/myisam/myisam.h>
82 #include <drizzled/typelib.h>
83 #include <drizzled/visibility.h>
84 #include <drizzled/system_variables.h>
85 #include <drizzled/open_tables_state.h>
86 
87 #include <google/protobuf/stubs/common.h>
88 
89 #if TIME_WITH_SYS_TIME
90 # include <sys/time.h>
91 # include <time.h>
92 #else
93 # if HAVE_SYS_TIME_H
94 # include <sys/time.h>
95 # else
96 # include <time.h>
97 # endif
98 #endif
99 
100 #ifdef HAVE_SYS_PRCTL_H
101 #include <sys/prctl.h>
102 #endif
103 #include <sys/socket.h>
104 
105 
106 #include <errno.h>
107 #include <sys/stat.h>
108 #include <drizzled/option.h>
109 #ifdef HAVE_SYSENT_H
110 #include <sysent.h>
111 #endif
112 #include <pwd.h> // For getpwent
113 #include <grp.h>
114 
115 #ifdef HAVE_SELECT_H
116 # include <select.h>
117 #endif
118 
119 #ifdef HAVE_SYS_SELECT_H
120 #include <sys/select.h>
121 #endif
122 
123 #include <sys/utsname.h>
124 
125 #ifdef HAVE_SYS_MMAN_H
126 #include <sys/mman.h>
127 #endif
128 
129 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
130 #include <ieeefp.h>
131 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
132 
133 #ifdef HAVE_FPU_CONTROL_H
134 #include <fpu_control.h>
135 #endif
136 
137 #ifdef HAVE_SYS_FPU_H
138 /* for IRIX to use set_fpc_csr() */
139 #include <sys/fpu.h>
140 #endif
141 
142 #include <drizzled/internal/my_pthread.h> // For thr_setconcurency()
143 #include <drizzled/constrained_value.h>
144 
145 #include <drizzled/gettext.h>
146 
147 
148 #ifdef HAVE_VALGRIND
149 #define IF_PURIFY(A,B) (A)
150 #else
151 #define IF_PURIFY(A,B) (B)
152 #endif
153 
154 #define MAX_MEM_TABLE_SIZE SIZE_MAX
155 #include <iostream>
156 #include <fstream>
157 
158 
159 using namespace std;
160 namespace fs=boost::filesystem;
161 namespace po=boost::program_options;
162 namespace dpo=drizzled::program_options;
163 
164 bool opt_daemon= false;
165 
166 namespace drizzled {
167 
168 inline void setup_fpu()
169 {
170 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
171  /*
172  We can't handle floating point exceptions with threads, so disable
173  this on freebsd.
174  Don't fall for overflow, underflow,divide-by-zero or loss of precision
175  */
176 #if defined(__i386__)
177  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
178  FP_X_IMP));
179 #else
180  fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
181  FP_X_IMP));
182 #endif /* __i386__ */
183 #endif /* __FreeBSD__ && HAVE_IEEEFP_H */
184 
185  /*
186  x86 (32-bit) requires FPU precision to be explicitly set to 64 bit for
187  portable results of floating point operations
188  */
189 #if defined(__i386__) && defined(HAVE_FPU_CONTROL_H) && defined(_FPU_DOUBLE)
190  fpu_control_t cw;
191  _FPU_GETCW(cw);
192  cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
193  _FPU_SETCW(cw);
194 #endif /* __i386__ && HAVE_FPU_CONTROL_H && _FPU_DOUBLE */
195 }
196 
197 #ifdef SOLARIS
198 extern "C" int gethostname(char *name, int namelen);
199 #endif
200 
201 const char *first_keyword= "first";
202 const char * const DRIZZLE_CONFIG_NAME= "drizzled";
203 
204 #define GET_HA_ROWS GET_ULL
205 
206 const char *tx_isolation_names[] = {"READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE", NULL};
207 
208 TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names) - 1, "", tx_isolation_names, NULL};
209 
210 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
211 {{&Arg_comparator::compare_string, &Arg_comparator::compare_e_string},
212  {&Arg_comparator::compare_real, &Arg_comparator::compare_e_real},
213  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
214  {&Arg_comparator::compare_row, &Arg_comparator::compare_e_row},
215  {&Arg_comparator::compare_decimal, &Arg_comparator::compare_e_decimal}};
216 
217 /* static variables */
218 
219 static bool opt_debugging= false;
220 static uint32_t wake_thread;
221 static const char* drizzled_chroot;
222 static const char* default_character_set_name= "utf8";
223 static const char* lc_time_names_name= "en_US";
224 static const char* default_storage_engine_str= "innodb";
225 static const char* const compiled_default_collation_name= "utf8_general_ci";
226 static const char* default_collation_name= compiled_default_collation_name;
227 
228 /* Global variables */
229 
230 const char *drizzled_user;
231 bool volatile select_thread_in_use;
232 bool volatile abort_loop;
233 DRIZZLED_API bool volatile shutdown_in_progress;
234 const char* opt_scheduler= "multi_thread";
235 
236 DRIZZLED_API size_t my_thread_stack_size= 0;
237 
238 /*
239  Legacy global plugin::StorageEngine. These will be removed (please do not add more).
240 */
241 plugin::StorageEngine *heap_engine;
242 plugin::StorageEngine *myisam_engine;
243 
244 bool calling_initgroups= false;
246 uint32_t drizzled_bind_timeout;
247 uint32_t dropping_tables, ha_open_options;
248 uint32_t tc_heuristic_recover= 0;
249 uint64_t session_startup_options;
250 back_log_constraints back_log(SOMAXCONN);
251 DRIZZLED_API uint32_t server_id;
252 DRIZZLED_API string server_uuid;
253 uint64_t table_cache_size;
254 size_t table_def_size;
255 uint32_t global_thread_id= 1UL;
256 pid_t current_pid;
257 
258 extern const double log_10[309];
259 
260 const double log_10[] = {
261  1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
262  1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
263  1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
264  1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
265  1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
266  1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
267  1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
268  1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
269  1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
270  1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
271  1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
272  1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
273  1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
274  1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
275  1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
276  1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
277  1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
278  1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
279  1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
280  1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
281  1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
282  1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
283  1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
284  1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
285  1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
286  1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
287  1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
288  1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
289  1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
290  1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
291  1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
292 };
293 
294 time_t server_start_time;
296 
297 fs::path basedir(PREFIX);
298 fs::path pid_file;
299 fs::path secure_file_priv;
300 fs::path plugin_dir;
301 fs::path system_config_dir(SYSCONFDIR);
302 
303 const key_map key_map_empty(0);
304 key_map key_map_full(0); // Will be initialized later
305 
306 std::string drizzle_tmpdir;
307 char *opt_drizzle_tmpdir= NULL;
308 
310 const char *in_left_expr_name= "<left expr>";
312 const char *in_additional_cond= "<IN COND>";
313 const char *in_having_cond= "<IN HAVING>";
314 
315 /* classes for comparation parsing/processing */
316 
317 FILE *stderror_file=0;
318 
319 drizzle_system_variables global_system_variables;
320 drizzle_system_variables max_system_variables;
321 global_counters current_global_counters;
322 
323 DRIZZLED_API const charset_info_st *system_charset_info;
324 const charset_info_st *files_charset_info;
325 const charset_info_st *table_alias_charset;
326 const charset_info_st *character_set_filesystem;
327 
328 MY_LOCALE *my_default_lc_time_names;
329 
330 SHOW_COMP_OPTION have_symlink;
331 
332 boost::condition_variable_any COND_refresh;
333 boost::condition_variable COND_thread_count;
334 pthread_t signal_thread;
335 
336 /* Static variables */
337 
338 int cleanup_done;
339 
340 passwd *user_info;
341 
342 boost::detail::atomic_count connection_count(0);
343 
344 global_buffer_constraint<uint64_t> global_sort_buffer(0);
345 global_buffer_constraint<uint64_t> global_join_buffer(0);
346 global_buffer_constraint<uint64_t> global_read_rnd_buffer(0);
347 global_buffer_constraint<uint64_t> global_read_buffer(0);
348 
349 DRIZZLED_API size_t transaction_message_threshold;
350 
351 static void drizzle_init_variables();
352 static void get_options();
353 static void fix_paths();
354 
355 void close_connections();
356 
357 fs::path base_plugin_dir(PKGPLUGINDIR);
358 
359 po::options_description general_options(_("General Options"));
360 po::options_description config_options(_("Config File Options"));
361 po::options_description long_options(_("Kernel Options"));
362 po::options_description plugin_load_options(_("Plugin Loading Options"));
363 po::options_description plugin_options(_("Plugin Options"));
364 po::options_description initial_options(_("Config and Plugin Loading"));
365 po::options_description full_options(_("Kernel and Plugin Loading and Plugin"));
366 vector<string> unknown_options;
367 vector<string> defaults_file_list;
368 po::variables_map vm;
369 
370 po::variables_map &getVariablesMap()
371 {
372  return vm;
373 }
374 
375 static std::string g_hostname= "localhost";
376 
377 const std::string& getServerHostname()
378 {
379  return g_hostname;
380 }
381 
382 static void print_version()
383 {
384  /*
385  Note: the instance manager keys off the string 'Ver' so it can find the
386  version from the output of 'drizzled --version', so don't change it!
387  */
388  printf("%s Ver %s for %s-%s on %s (%s)\n", internal::my_progname,
389  PANDORA_RELEASE_VERSION, HOST_VENDOR, HOST_OS, HOST_CPU, COMPILATION_COMMENT);
390 }
391 
392 extern "C" {
393 
394  char at_exit_pid_file[1024 * 4]= { 0 };
395 
396  static void remove_pidfile(void)
397  {
398  if (at_exit_pid_file[0])
399  {
400  if (unlink(at_exit_pid_file) == -1)
401  {
402  std::cerr << "Could not remove pidfile: " << at_exit_pid_file << "(" << strerror(errno) << ")" << std::endl;
403  }
404 
405  at_exit_pid_file[0]= 0;
406  }
407  }
408 }
409 
414 #ifndef O_CLOEXEC
415 #define O_CLOEXEC 0
416 #define DEFINED_O_CLOEXEC
417 #endif
418 
419 static void create_pid_file()
420 {
421  int file;
422 
423  if ((file = open(pid_file.file_string().c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, S_IRWXU|S_IRGRP|S_IROTH)) > 0)
424  {
425  char buff[1024];
426  int length= snprintf(buff, sizeof(buff), "%ld\n", (long) getpid());
427 
428  if ((write(file, buff, length)) == length)
429  {
430  if (close(file) != -1)
431  {
432  snprintf(at_exit_pid_file, sizeof(at_exit_pid_file), "%s", pid_file.file_string().c_str());
433  atexit(remove_pidfile);
434  return;
435  }
436  }
437  (void)close(file); /* We can ignore the error, since we are going to error anyway at this point */
438  }
439 
440  unireg_abort << "Can't start server, was unable to create PID file: " << pid_file.file_string();
441 }
442 
443 #ifdef DEFINED_O_CLOEXEC
444 #undef O_CLOEXEC
445 #endif
446 
447 /****************************************************************************
448 ** Code to end drizzled
449 ****************************************************************************/
450 
451 void close_connections()
452 {
453  /* Abort listening to new connections */
454  plugin::Listen::shutdown();
455 
456  /* kill connection thread */
457  {
458  boost::mutex::scoped_lock scopedLock(session::Cache::mutex());
459 
460  while (select_thread_in_use)
461  {
462  boost::xtime xt;
463  xtime_get(&xt, boost::TIME_UTC_);
464  xt.sec += 2;
465 
466  for (uint32_t tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
467  {
468  bool success= COND_thread_count.timed_wait(scopedLock, xt);
469  if (not success)
470  break;
471  }
472  }
473  }
474 
475 
476  /*
477  First signal all threads that it's time to die
478  This will give the threads some time to gracefully abort their
479  statements and inform their clients that the server is about to die.
480  */
481 
482  {
483  boost::mutex::scoped_lock scopedLock(session::Cache::mutex());
484  session::Cache::list list= session::Cache::getCache();
485 
486  BOOST_FOREACH(session::Cache::list::reference tmp, list)
487  {
488  tmp->setKilled(Session::KILL_CONNECTION);
489  tmp->scheduler->killSession(tmp.get());
490  DRIZZLE_CONNECTION_DONE(tmp->thread_id);
491 
492  tmp->lockOnSys();
493  }
494  }
495 
496  if (session::Cache::count()) // Give threads time to die
497  {
498  struct timespec requested;
499  requested.tv_sec= 2;
500  requested.tv_nsec= 0;
501  nanosleep(&requested, NULL);
502  }
503 
504  /*
505  Force remaining threads to die by closing the connection to the client
506  This will ensure that threads that are waiting for a command from the
507  client on a blocking read call are aborted.
508  */
509  for (;;)
510  {
511  boost::mutex::scoped_lock scopedLock(session::Cache::mutex());
512  session::Cache::list list= session::Cache::getCache();
513 
514  if (list.empty())
515  {
516  break;
517  }
518  /* Close before unlock, avoiding crash. See LP bug#436685 */
519  list.front()->getClient()->close();
520  }
521 }
522 
523 static bool unireg_startup_completed= false;
524 void unireg_startup_finished()
525 {
526  unireg_startup_completed= true;
527 }
528 
529 void unireg_exit()
530 {
531  internal::my_end();
532  assert(unireg_startup_completed == false);
533  exit(EXIT_SUCCESS);
534 }
535 
536 void unireg_actual_abort(const char *file, int line, const char *func, const std::string& message)
537 {
538  std::stringstream temp;
539  temp << _("Aborting:") << "\"" << message << "\"" << ". Abort was called from " << file << ":" << line << " in " << func << "()";
540  errmsg_printf(error::ERROR, "%s", temp.str().c_str());
541 
542  clean_up(vm.count("help") == 0);
543  internal::my_end();
544 
545  assert(unireg_startup_completed == false);
546  exit(EXIT_FAILURE);
547 }
548 
549 
550 void clean_up(bool print_message)
551 {
552  if (cleanup_done++)
553  {
554  return;
555  }
556 
557  table_cache_free();
558  free_charsets();
559  module::Registry &modules= module::Registry::singleton();
560  modules.shutdownModules();
561 
563 
564 #if GOOGLE_PROTOBUF_VERSION >= 2001000
565  google::protobuf::ShutdownProtobufLibrary();
566 #endif
567 
568  if (print_message && server_start_time)
569  {
570  errmsg_printf(drizzled::error::INFO, _(ER(ER_SHUTDOWN_COMPLETE)),internal::my_progname);
571  }
572 
573  session::Cache::shutdownFirst();
574 
575  /*
576  The following lines may never be executed as the main thread may have
577  killed us
578  */
579 } /* clean_up */
580 
581 
582 /* Change to run as another user if started with --user */
583 
584 passwd *check_user(const char *user)
585 {
586  passwd *tmp_user_info;
587  uid_t user_id= geteuid();
588 
589  // Don't bother if we aren't superuser
590  if (user_id)
591  {
592  if (user)
593  {
594  /* Don't give a warning, if real user is same as given with --user */
595  tmp_user_info= getpwnam(user);
596  if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
597  global_system_variables.log_warnings)
598  {
599  errmsg_printf(error::WARN, _("One can only use the --user switch if running as root"));
600  }
601  }
602  return NULL;
603  }
604  if (not user)
605  {
606  unireg_abort << _("drizzled cannot be run as root, use --user to start drizzled up as another user");
607  }
608 
609  if (strcmp(user, "root") == 0)
610  {
611  return NULL; // Avoid problem with dynamic libraries
612  }
613 
614  bool failed= false;
615  if ((tmp_user_info= getpwnam(user)) == NULL)
616  {
617  // Allow a numeric uid to be used
618  const char *pos= user;
619  for (; my_charset_utf8_general_ci.isdigit(*pos); pos++)
620  { }
621  if (*pos) // Not numeric id
622  {
623  failed= true;
624  }
625 
626  if ((tmp_user_info= getpwuid(atoi(user))) == NULL)
627  {
628  failed= true;
629  }
630  }
631 
632  if (failed)
633  {
634  unireg_abort << "Fatal error: Can't change to run as user '" << user << "' ; Please check that the user exists!";
635 
636 #ifdef PR_SET_DUMPABLE
637  if (getDebug().test(debug::CORE_ON_SIGNAL))
638  {
639  /* inform kernel that process is dumpable */
640  (void) prctl(PR_SET_DUMPABLE, 1);
641  }
642 #endif
643 
644  return NULL;
645  }
646 
647  return tmp_user_info;
648 }
649 
650 void set_user(const char *user, passwd *user_info_arg)
651 {
652  assert(user_info_arg != 0);
653  initgroups(user, user_info_arg->pw_gid);
654  if (setgid(user_info_arg->pw_gid) == -1)
655  {
656  unireg_abort << _("Set process group ID failed ") << strerror(errno);
657  }
658  if (setuid(user_info_arg->pw_uid) == -1)
659  {
660  unireg_abort << _("Set process user ID failed") << strerror(errno);
661  }
662 }
663 
664 
665 
667 static void set_root(const char *path)
668 {
669  if ((chroot(path) == -1) or chdir("/") == 0)
670  {
671  unireg_abort << _("Process chroot failed");
672  }
673 }
674 
675 
676 /*
677  Unlink session from global list of available connections and free session
678 
679  SYNOPSIS
680  Session::unlink()
681  session Thread handler
682 */
683 
684 void Session::unlink(session_id_t &session_id)
685 {
686  Session::shared_ptr session= session::Cache::find(session_id);
687 
688  if (session)
689  unlink(session);
690 }
691 
692 void Session::unlink(const Session::shared_ptr& session)
693 {
694  --connection_count;
695 
696  session->cleanup();
697 
698  boost::mutex::scoped_lock scopedLock(session::Cache::mutex());
699 
700  if (unlikely(plugin::EventObserver::disconnectSession(*session)))
701  {
702  // We should do something about an error...
703  }
704  session::Cache::erase(session);
705 }
706 
707 
708 #ifndef SA_RESETHAND
709 #define SA_RESETHAND 0
710 #endif
711 #ifndef SA_NODEFER
712 #define SA_NODEFER 0
713 #endif
714 
715 
716 
717 
718 const char *load_default_groups[]=
719 {
720  DRIZZLE_CONFIG_NAME, "server", 0, 0
721 };
722 
723 static void find_plugin_dir(string progname)
724 {
725  fs::path full_progname(fs::system_complete(progname));
726 
727  fs::path progdir(full_progname.parent_path());
728  if (progdir.filename() == ".libs")
729  {
730  progdir= progdir.parent_path();
731  }
732 
733  if (fs::exists(progdir / "drizzled.lo") || fs::exists(progdir / "drizzled.o"))
734  {
735  /* We are in a source dir! Plugin dir is ../plugin/.libs */
736  base_plugin_dir= progdir.parent_path();
737  base_plugin_dir /= "plugin";
738  base_plugin_dir /= ".libs";
739  }
740 
741  if (plugin_dir.root_directory() == "")
742  {
743  fs::path full_plugin_dir(fs::system_complete(base_plugin_dir));
744  full_plugin_dir /= plugin_dir;
745  plugin_dir= full_plugin_dir;
746  }
747 }
748 
749 static void notify_plugin_dir(fs::path in_plugin_dir)
750 {
751  plugin_dir= in_plugin_dir;
752  if (plugin_dir.root_directory() == "")
753  {
754  fs::path full_plugin_dir(fs::system_complete(basedir));
755  full_plugin_dir /= plugin_dir;
756  plugin_dir= full_plugin_dir;
757  }
758 }
759 
760 static void expand_secure_file_priv(fs::path in_secure_file_priv)
761 {
762  secure_file_priv= fs::system_complete(in_secure_file_priv);
763 }
764 
765 static void check_limits_aii(uint64_t in_auto_increment_increment)
766 {
767  global_system_variables.auto_increment_increment= 1;
768  if (in_auto_increment_increment < 1 || in_auto_increment_increment > UINT64_MAX)
769  {
770  unireg_abort << _("Invalid Value for auto_increment_increment");
771  }
772  global_system_variables.auto_increment_increment= in_auto_increment_increment;
773 }
774 
775 static void check_limits_aio(uint64_t in_auto_increment_offset)
776 {
777  global_system_variables.auto_increment_offset= 1;
778  if (in_auto_increment_offset < 1 || in_auto_increment_offset > UINT64_MAX)
779  {
780  unireg_abort << _("Invalid Value for auto_increment_offset");
781  }
782  global_system_variables.auto_increment_offset= in_auto_increment_offset;
783 }
784 
785 static void check_limits_completion_type(uint32_t in_completion_type)
786 {
787  global_system_variables.completion_type= 0;
788  if (in_completion_type > 2)
789  {
790  unireg_abort << _("Invalid Value for completion_type");
791  }
792  global_system_variables.completion_type= in_completion_type;
793 }
794 
795 
796 static void check_limits_dpi(uint32_t in_div_precincrement)
797 {
798  global_system_variables.div_precincrement= 4;
799  if (in_div_precincrement > DECIMAL_MAX_SCALE)
800  {
801  unireg_abort << _("Invalid Value for div-precision-increment");
802  }
803  global_system_variables.div_precincrement= in_div_precincrement;
804 }
805 
806 static void check_limits_gcml(uint64_t in_group_concat_max_len)
807 {
808  global_system_variables.group_concat_max_len= 1024;
809  if (in_group_concat_max_len > ULONG_MAX || in_group_concat_max_len < 4)
810  {
811  unireg_abort << _("Invalid Value for group_concat_max_len");
812  }
813  global_system_variables.group_concat_max_len= in_group_concat_max_len;
814 }
815 
816 static void check_limits_join_buffer_size(uint64_t in_join_buffer_size)
817 {
818  global_system_variables.join_buff_size= (128*1024L);
819  if (in_join_buffer_size < IO_SIZE*2 || in_join_buffer_size > ULONG_MAX)
820  {
821  unireg_abort << _("Invalid Value for join_buffer_size");
822  }
823  in_join_buffer_size-= in_join_buffer_size % IO_SIZE;
824  global_system_variables.join_buff_size= in_join_buffer_size;
825 }
826 
827 static void check_limits_map(uint32_t in_max_allowed_packet)
828 {
829  global_system_variables.max_allowed_packet= (64*1024*1024L);
830  if (in_max_allowed_packet < 1024 || in_max_allowed_packet > 1024*1024L*1024L)
831  {
832  unireg_abort << _("Invalid Value for max_allowed_packet");
833  }
834  in_max_allowed_packet-= in_max_allowed_packet % 1024;
835  global_system_variables.max_allowed_packet= in_max_allowed_packet;
836 }
837 
838 static void check_limits_max_err_cnt(uint64_t in_max_error_count)
839 {
840  global_system_variables.max_error_count= DEFAULT_ERROR_COUNT;
841  if (in_max_error_count > 65535)
842  {
843  unireg_abort << _("Invalid Value for max_error_count");
844  }
845  global_system_variables.max_error_count= in_max_error_count;
846 }
847 
848 static void check_limits_mhts(uint64_t in_max_heap_table_size)
849 {
850  global_system_variables.max_heap_table_size= (16*1024*1024L);
851  if (in_max_heap_table_size < 16384 || in_max_heap_table_size > MAX_MEM_TABLE_SIZE)
852  {
853  unireg_abort << _("Invalid Value for max_heap_table_size");
854  }
855  in_max_heap_table_size-= in_max_heap_table_size % 1024;
856  global_system_variables.max_heap_table_size= in_max_heap_table_size;
857 }
858 
859 static void check_limits_merl(uint64_t in_min_examined_row_limit)
860 {
861  global_system_variables.min_examined_row_limit= 0;
862  if (in_min_examined_row_limit > ULONG_MAX)
863  {
864  unireg_abort << _("Invalid Value for min_examined_row_limit");
865  }
866  global_system_variables.min_examined_row_limit= in_min_examined_row_limit;
867 }
868 
869 static void check_limits_max_join_size(ha_rows in_max_join_size)
870 {
871  global_system_variables.max_join_size= INT32_MAX;
872  if ((uint64_t)in_max_join_size < 1 || (uint64_t)in_max_join_size > INT32_MAX)
873  {
874  unireg_abort << _("Invalid Value for max_join_size");
875  }
876  global_system_variables.max_join_size= in_max_join_size;
877 }
878 
879 static void check_limits_mlfsd(int64_t in_max_length_for_sort_data)
880 {
881  global_system_variables.max_length_for_sort_data= 1024;
882  if (in_max_length_for_sort_data < 4 || in_max_length_for_sort_data > 8192*1024L)
883  {
884  unireg_abort << _("Invalid Value for max_length_for_sort_data");
885  }
886  global_system_variables.max_length_for_sort_data= in_max_length_for_sort_data;
887 }
888 
889 static void check_limits_msfk(uint64_t in_max_seeks_for_key)
890 {
891  global_system_variables.max_seeks_for_key= ULONG_MAX;
892  if (in_max_seeks_for_key < 1 || in_max_seeks_for_key > ULONG_MAX)
893  {
894  unireg_abort << _("Invalid Value for max_seeks_for_key");
895  }
896  global_system_variables.max_seeks_for_key= in_max_seeks_for_key;
897 }
898 
899 static void check_limits_max_sort_length(size_t in_max_sort_length)
900 {
901  global_system_variables.max_sort_length= 1024;
902  if ((int64_t)in_max_sort_length < 4 || (int64_t)in_max_sort_length > 8192*1024L)
903  {
904  unireg_abort << _("Invalid Value for max_sort_length");
905  }
906  global_system_variables.max_sort_length= in_max_sort_length;
907 }
908 
909 static void check_limits_osd(uint32_t in_optimizer_search_depth)
910 {
911  global_system_variables.optimizer_search_depth= 0;
912  if (in_optimizer_search_depth > MAX_TABLES + 2)
913  {
914  unireg_abort << _("Invalid Value for optimizer_search_depth");
915  }
916  global_system_variables.optimizer_search_depth= in_optimizer_search_depth;
917 }
918 
919 static void check_limits_pbs(uint64_t in_preload_buff_size)
920 {
921  global_system_variables.preload_buff_size= (32*1024L);
922  if (in_preload_buff_size < 1024 || in_preload_buff_size > 1024*1024*1024L)
923  {
924  unireg_abort << _("Invalid Value for preload_buff_size");
925  }
926  global_system_variables.preload_buff_size= in_preload_buff_size;
927 }
928 
929 static void check_limits_qabs(uint32_t in_query_alloc_block_size)
930 {
931  global_system_variables.query_alloc_block_size= QUERY_ALLOC_BLOCK_SIZE;
932  if (in_query_alloc_block_size < 1024)
933  {
934  unireg_abort << _("Invalid Value for query_alloc_block_size");
935  }
936  in_query_alloc_block_size-= in_query_alloc_block_size % 1024;
937  global_system_variables.query_alloc_block_size= in_query_alloc_block_size;
938 }
939 
940 static void check_limits_qps(uint32_t in_query_prealloc_size)
941 {
942  global_system_variables.query_prealloc_size= QUERY_ALLOC_PREALLOC_SIZE;
943  if (in_query_prealloc_size < QUERY_ALLOC_PREALLOC_SIZE)
944  {
945  unireg_abort << _("Invalid Value for query_prealloc_size");
946  }
947  in_query_prealloc_size-= in_query_prealloc_size % 1024;
948  global_system_variables.query_prealloc_size= in_query_prealloc_size;
949 }
950 
951 static void check_limits_rabs(size_t in_range_alloc_block_size)
952 {
953  global_system_variables.range_alloc_block_size= RANGE_ALLOC_BLOCK_SIZE;
954  if (in_range_alloc_block_size < RANGE_ALLOC_BLOCK_SIZE)
955  {
956  unireg_abort << _("Invalid Value for range_alloc_block_size");
957  }
958  in_range_alloc_block_size-= in_range_alloc_block_size % 1024;
959  global_system_variables.range_alloc_block_size= in_range_alloc_block_size;
960 }
961 
962 static void check_limits_read_buffer_size(int32_t in_read_buff_size)
963 {
964  global_system_variables.read_buff_size= (128*1024L);
965  if (in_read_buff_size < IO_SIZE*2 || in_read_buff_size > INT32_MAX)
966  {
967  unireg_abort << _("Invalid Value for read_buff_size");
968  }
969  in_read_buff_size-= in_read_buff_size % IO_SIZE;
970  global_system_variables.read_buff_size= in_read_buff_size;
971 }
972 
973 static void check_limits_read_rnd_buffer_size(uint32_t in_read_rnd_buff_size)
974 {
975  global_system_variables.read_rnd_buff_size= (256*1024L);
976  if (in_read_rnd_buff_size < 64 || in_read_rnd_buff_size > UINT32_MAX)
977  {
978  unireg_abort << _("Invalid Value for read_rnd_buff_size");
979  }
980  global_system_variables.read_rnd_buff_size= in_read_rnd_buff_size;
981 }
982 
983 static void check_limits_sort_buffer_size(size_t in_sortbuff_size)
984 {
985  global_system_variables.sortbuff_size= MAX_SORT_MEMORY;
986  if ((uint32_t)in_sortbuff_size < MIN_SORT_MEMORY)
987  {
988  unireg_abort << _("Invalid Value for sort_buff_size");
989  }
990  global_system_variables.sortbuff_size= in_sortbuff_size;
991 }
992 
993 static void check_limits_tdc(uint32_t in_table_def_size)
994 {
995  table_def_size= 128;
996  if (in_table_def_size < 1 || in_table_def_size > 512*1024L)
997  {
998  unireg_abort << _("Invalid Value for table_def_size");
999  }
1000  table_def_size= in_table_def_size;
1001 }
1002 
1003 static void check_limits_toc(uint32_t in_table_cache_size)
1004 {
1005  table_cache_size= TABLE_OPEN_CACHE_DEFAULT;
1006  if (in_table_cache_size < TABLE_OPEN_CACHE_MIN || in_table_cache_size > 512*1024L)
1007  {
1008  unireg_abort << _("Invalid Value for table_cache_size");
1009  }
1010  table_cache_size= in_table_cache_size;
1011 }
1012 
1013 static void check_limits_tlwt(uint64_t in_table_lock_wait_timeout)
1014 {
1015  table_lock_wait_timeout= 50;
1016  if (in_table_lock_wait_timeout < 1 || in_table_lock_wait_timeout > 1024*1024*1024)
1017  {
1018  unireg_abort << _("Invalid Value for table_lock_wait_timeout");
1019  }
1020  table_lock_wait_timeout= in_table_lock_wait_timeout;
1021 }
1022 
1023 static void check_limits_thread_stack(uint32_t in_my_thread_stack_size)
1024 {
1025  my_thread_stack_size= in_my_thread_stack_size - (in_my_thread_stack_size % 1024);
1026 }
1027 
1028 static void check_limits_tmp_table_size(uint64_t in_tmp_table_size)
1029 {
1030  global_system_variables.tmp_table_size= 16*1024*1024L;
1031  if (in_tmp_table_size < 1024 || in_tmp_table_size > MAX_MEM_TABLE_SIZE)
1032  {
1033  unireg_abort << _("Invalid Value for table_lock_wait_timeout");
1034  }
1035  global_system_variables.tmp_table_size= in_tmp_table_size;
1036 }
1037 
1038 static void check_limits_transaction_message_threshold(size_t in_transaction_message_threshold)
1039 {
1040  transaction_message_threshold= 1024*1024;
1041  if ((int64_t) in_transaction_message_threshold < 128*1024 || (int64_t)in_transaction_message_threshold > 1024*1024)
1042  {
1043  unireg_abort << _("Invalid Value for transaction_message_threshold valid values are between 131072 - 1048576 bytes");
1044  }
1045  transaction_message_threshold= in_transaction_message_threshold;
1046 }
1047 
1048 static void process_defaults_files()
1049 {
1050  BOOST_FOREACH(vector<string>::reference iter, defaults_file_list)
1051  {
1052  fs::path file_location= iter;
1053 
1054  ifstream input_defaults_file(file_location.file_string().c_str());
1055 
1056  po::parsed_options file_parsed= dpo::parse_config_file(input_defaults_file, full_options, true);
1057  vector<string> file_unknown= po::collect_unrecognized(file_parsed.options, po::include_positional);
1058 
1059  for (vector<string>::iterator it= file_unknown.begin(); it != file_unknown.end(); ++it)
1060  {
1061  string new_unknown_opt("--" + *it);
1062  ++it;
1063 
1064  if (it == file_unknown.end())
1065  {
1066  break;
1067  }
1068 
1069  if (*it != "true")
1070  {
1071  new_unknown_opt += "=" + *it;
1072  }
1073 
1074  unknown_options.push_back(new_unknown_opt);
1075  }
1076  store(file_parsed, vm);
1077  }
1078 }
1079 
1080 static void compose_defaults_file_list(const vector<string>& in_options)
1081 {
1082  BOOST_FOREACH(const string& it, in_options)
1083  {
1084  fs::path p(it);
1085  if (fs::is_regular_file(p))
1086  {
1087  defaults_file_list.push_back(it);
1088  }
1089  else
1090  {
1091  unireg_abort << "Defaults file '" << it << "' not found";
1092  }
1093  }
1094 }
1095 
1096 bool init_variables_before_daemonizing(int argc, char **argv)
1097 {
1098  umask(((~internal::my_umask) & 0666));
1099  decimal_zero.set_zero(); // set decimal_zero constant;
1100  tzset(); // Set tzname
1101 
1102  time_t curr_time= time(NULL);
1103  if (curr_time == (time_t)-1)
1104  {
1105  return false;
1106  }
1107 
1108  max_system_variables.pseudo_thread_id= UINT32_MAX;
1109  server_start_time= flush_status_time= curr_time;
1110 
1112 
1113  find_plugin_dir(argv[0]);
1114 
1115  char ret_hostname[FN_REFLEN];
1116  if (gethostname(ret_hostname,sizeof(ret_hostname)) < 0)
1117  {
1118  errmsg_printf(error::WARN, _("gethostname failed, using '%s' as hostname"), getServerHostname().c_str());
1119  pid_file= "drizzle";
1120  }
1121  else
1122  {
1123  g_hostname= ret_hostname;
1124  pid_file= getServerHostname();
1125  }
1126  pid_file.replace_extension(".pid");
1127 
1128  system_config_dir /= "drizzle";
1129 
1130  general_options.add_options()
1131  ("help,?",
1132  _("Display help and exit."))
1133  ("daemon,d", po::value<bool>(&opt_daemon)->default_value(false)->zero_tokens(),
1134  _("Run as a daemon."))
1135  ("user,u", po::value<string>(),
1136  _("Run drizzled daemon as user."))
1137  ("version,V",
1138  _("Print version information and exit."))
1139  ;
1140 
1141  config_options.add_options()
1142  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
1143  _("Configuration file defaults are not used if no-defaults is set"))
1144  ("defaults-file", po::value<vector<string> >()->composing()->notifier(&compose_defaults_file_list),
1145  _("Configuration file to use"))
1146  ("config-dir", po::value<fs::path>(&system_config_dir),
1147  _("Base location for config files"))
1148  ("plugin-dir", po::value<fs::path>(&plugin_dir)->notifier(&notify_plugin_dir),
1149  _("Directory for plugins."))
1150  ;
1151 
1152  plugin_load_options.add_options()
1153  ("plugin-add", po::value<vector<string> >()->composing()->notifier(&compose_plugin_add),
1154  _("Optional comma separated list of plugins to load at startup in addition "
1155  "to the default list of plugins. "
1156  "[for example: --plugin_add=crc32,logger_gearman]"))
1157  ("plugin-remove", po::value<vector<string> >()->composing()->notifier(&compose_plugin_remove),
1158  _("Optional comma separated list of plugins to not load at startup. Effectively "
1159  "removes a plugin from the list of plugins to be loaded. "
1160  "[for example: --plugin_remove=crc32,logger_gearman]"))
1161  ("plugin-load", po::value<string>()->notifier(&notify_plugin_load)->default_value(PANDORA_PLUGIN_LIST),
1162  _("Optional comma separated list of plugins to load at starup instead of "
1163  "the default plugin load list. "
1164  "[for example: --plugin_load=crc32,logger_gearman]"))
1165  ;
1166 
1167  long_options.add_options()
1168  ("auto-increment-increment", po::value<uint64_t>(&global_system_variables.auto_increment_increment)->default_value(1)->notifier(&check_limits_aii),
1169  _("Auto-increment columns are incremented by this"))
1170  ("auto-increment-offset", po::value<uint64_t>(&global_system_variables.auto_increment_offset)->default_value(1)->notifier(&check_limits_aio),
1171  _("Offset added to Auto-increment columns. Used when auto-increment-increment != 1"))
1172  ("basedir,b", po::value<fs::path>(&basedir),
1173  _("Path to installation directory. All paths are usually resolved "
1174  "relative to this."))
1175  ("chroot,r", po::value<string>(),
1176  _("Chroot drizzled daemon during startup."))
1177  ("collation-server", po::value<string>(),
1178  _("Set the default collation."))
1179  ("completion-type", po::value<uint32_t>(&global_system_variables.completion_type)->default_value(0)->notifier(&check_limits_completion_type),
1180  _("Default completion type."))
1181  ("core-file", _("Write core on errors."))
1182  ("datadir", po::value<fs::path>(&getMutableDataHome()),
1183  _("Path to the database root."))
1184  ("default-storage-engine", po::value<string>(),
1185  _("Set the default storage engine for tables."))
1186  ("default-time-zone", po::value<string>(),
1187  _("Set the default time zone."))
1188  ("exit-info,T", po::value<long>(),
1189  _("Used for debugging; Use at your own risk!"))
1190  ("gdb", po::value<bool>(&opt_debugging)->default_value(false)->zero_tokens(),
1191  _("Set up signals usable for debugging"))
1192  ("lc-time-name", po::value<string>(),
1193  _("Set the language used for the month names and the days of the week."))
1194  ("log-warnings,W", po::value<bool>(&global_system_variables.log_warnings)->default_value(false)->zero_tokens(),
1195  _("Log some not critical warnings to the log file."))
1196  ("pid-file", po::value<fs::path>(&pid_file),
1197  _("Pid file used by drizzled."))
1198  ("port-open-timeout", po::value<uint32_t>(&drizzled_bind_timeout)->default_value(0),
1199  _("Maximum time in seconds to wait for the port to become free. "))
1200  ("replicate-query", po::value<bool>(&global_system_variables.replicate_query)->default_value(false)->zero_tokens(),
1201  _("Include the SQL query in replicated protobuf messages."))
1202  ("secure-file-priv", po::value<fs::path>(&secure_file_priv)->notifier(expand_secure_file_priv),
1203  _("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
1204  "within specified directory"))
1205  ("server-id", po::value<uint32_t>(&server_id)->default_value(0),
1206  _("Uniquely identifies the server instance in the community of "
1207  "replication partners."))
1208  ("skip-stack-trace",
1209  _("Don't print a stack trace on failure."))
1210  ("symbolic-links,s", po::value<bool>(&internal::my_use_symdir)->default_value(IF_PURIFY(false,true))->zero_tokens(),
1211  _("Enable symbolic link support."))
1212  ("timed-mutexes", po::value<bool>(&internal::timed_mutexes)->default_value(false)->zero_tokens(),
1213  _("Specify whether to time mutexes (only InnoDB mutexes are currently "
1214  "supported)"))
1215  ("tmpdir,t", po::value<string>(),
1216  _("Path for temporary files."))
1217  ("transaction-isolation", po::value<string>(),
1218  _("Default transaction isolation level."))
1219  ("transaction-message-threshold", po::value<size_t>(&transaction_message_threshold)->default_value(1024*1024)->notifier(&check_limits_transaction_message_threshold),
1220  _("Max message size written to transaction log, valid values 131072 - 1048576 bytes."))
1221  ("back-log", po::value<back_log_constraints>(&back_log),
1222  _("The number of outstanding connection requests Drizzle can have. This "
1223  "comes into play when the main Drizzle thread gets very many connection "
1224  "requests in a very short time."))
1225  ("bulk-insert-buffer-size",
1226  po::value<uint64_t>(&global_system_variables.bulk_insert_buff_size)->default_value(8192*1024),
1227  _("Size of tree cache used in bulk insert optimization. Note that this is "
1228  "a limit per thread!"))
1229  ("div-precision-increment", po::value<uint32_t>(&global_system_variables.div_precincrement)->default_value(4)->notifier(&check_limits_dpi),
1230  _("Precision of the result of '/' operator will be increased on that "
1231  "value."))
1232  ("group-concat-max-len", po::value<uint64_t>(&global_system_variables.group_concat_max_len)->default_value(1024)->notifier(&check_limits_gcml),
1233  _("The maximum length of the result of function group_concat."))
1234  ("join-buffer-size", po::value<uint64_t>(&global_system_variables.join_buff_size)->default_value(128*1024L)->notifier(&check_limits_join_buffer_size),
1235  _("The size of the buffer that is used for full joins."))
1236  ("join-heap-threshold",
1237  po::value<uint64_t>()->default_value(0),
1238  _("A global cap on the amount of memory that can be allocated by session join buffers (0 means unlimited)"))
1239  ("max-allowed-packet", po::value<uint32_t>(&global_system_variables.max_allowed_packet)->default_value(64*1024*1024L)->notifier(&check_limits_map),
1240  _("Max packetlength to send/receive from to server."))
1241  ("max-error-count", po::value<uint64_t>(&global_system_variables.max_error_count)->default_value(DEFAULT_ERROR_COUNT)->notifier(&check_limits_max_err_cnt),
1242  _("Max number of errors/warnings to store for a statement."))
1243  ("max-heap-table-size", po::value<uint64_t>(&global_system_variables.max_heap_table_size)->default_value(16*1024*1024L)->notifier(&check_limits_mhts),
1244  _("Don't allow creation of heap tables bigger than this."))
1245  ("max-join-size", po::value<ha_rows>(&global_system_variables.max_join_size)->default_value(INT32_MAX)->notifier(&check_limits_max_join_size),
1246  _("Joins that are probably going to read more than max_join_size records "
1247  "return an error."))
1248  ("max-length-for-sort-data", po::value<uint64_t>(&global_system_variables.max_length_for_sort_data)->default_value(1024)->notifier(&check_limits_mlfsd),
1249  _("Max number of bytes in sorted records."))
1250  ("max-seeks-for-key", po::value<uint64_t>(&global_system_variables.max_seeks_for_key)->default_value(ULONG_MAX)->notifier(&check_limits_msfk),
1251  _("Limit assumed max number of seeks when looking up rows based on a key"))
1252  ("max-sort-length", po::value<size_t>(&global_system_variables.max_sort_length)->default_value(1024)->notifier(&check_limits_max_sort_length),
1253  _("The number of bytes to use when sorting BLOB or TEXT values "
1254  "(only the first max_sort_length bytes of each value are used; the "
1255  "rest are ignored)."))
1256  ("max-write-lock-count", po::value<uint64_t>(&max_write_lock_count)->default_value(UINT64_MAX),
1257  _("After this many write locks, allow some read locks to run in between."))
1258  ("min-examined-row-limit", po::value<uint64_t>(&global_system_variables.min_examined_row_limit)->default_value(0)->notifier(&check_limits_merl),
1259  _("Don't log queries which examine less than min_examined_row_limit "
1260  "rows to file."))
1261  ("disable-optimizer-prune",
1262  _("Do not apply any heuristic(s) during query optimization to prune, "
1263  "thus perform an exhaustive search from the optimizer search space."))
1264  ("optimizer-search-depth", po::value<uint32_t>(&global_system_variables.optimizer_search_depth)->default_value(0)->notifier(&check_limits_osd),
1265  _("Maximum depth of search performed by the query optimizer. Values "
1266  "larger than the number of relations in a query result in better query "
1267  "plans, but take longer to compile a query. Smaller values than the "
1268  "number of tables in a relation result in faster optimization, but may "
1269  "produce very bad query plans. If set to 0, the system will "
1270  "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
1271  "optimizer will switch to the original find_best (used for "
1272  "testing/comparison)."))
1273  ("preload-buffer-size", po::value<uint64_t>(&global_system_variables.preload_buff_size)->default_value(32*1024L)->notifier(&check_limits_pbs),
1274  _("The size of the buffer that is allocated when preloading indexes"))
1275  ("query-alloc-block-size",
1276  po::value<uint32_t>(&global_system_variables.query_alloc_block_size)->default_value(QUERY_ALLOC_BLOCK_SIZE)->notifier(&check_limits_qabs),
1277  _("Allocation block size for query parsing and execution"))
1278  ("query-prealloc-size",
1279  po::value<uint32_t>(&global_system_variables.query_prealloc_size)->default_value(QUERY_ALLOC_PREALLOC_SIZE)->notifier(&check_limits_qps),
1280  _("Persistent buffer for query parsing and execution"))
1281  ("range-alloc-block-size",
1282  po::value<size_t>(&global_system_variables.range_alloc_block_size)->default_value(RANGE_ALLOC_BLOCK_SIZE)->notifier(&check_limits_rabs),
1283  _("Allocation block size for storing ranges during optimization"))
1284  ("read-buffer-size",
1285  po::value<uint32_t>(&global_system_variables.read_buff_size)->default_value(128*1024L)->notifier(&check_limits_read_buffer_size),
1286  _("Each thread that does a sequential scan allocates a buffer of this "
1287  "size for each table it scans. If you do many sequential scans, you may "
1288  "want to increase this value."))
1289  ("read-buffer-threshold",
1290  po::value<uint64_t>()->default_value(0),
1291  _("A global cap on the size of read-buffer-size (0 means unlimited)"))
1292  ("read-rnd-buffer-size",
1293  po::value<uint32_t>(&global_system_variables.read_rnd_buff_size)->default_value(256*1024L)->notifier(&check_limits_read_rnd_buffer_size),
1294  _("When reading rows in sorted order after a sort, the rows are read "
1295  "through this buffer to avoid a disk seeks. If not set, then it's set "
1296  "to the value of record_buffer."))
1297  ("read-rnd-threshold",
1298  po::value<uint64_t>()->default_value(0),
1299  _("A global cap on the size of read-rnd-buffer-size (0 means unlimited)"))
1300  ("scheduler", po::value<string>(),
1301  _("Select scheduler to be used (by default multi-thread)."))
1302  ("sort-buffer-size",
1303  po::value<size_t>(&global_system_variables.sortbuff_size)->default_value(MAX_SORT_MEMORY)->notifier(&check_limits_sort_buffer_size),
1304  _("Each thread that needs to do a sort allocates a buffer of this size."))
1305  ("sort-heap-threshold",
1306  po::value<uint64_t>()->default_value(0),
1307  _("A global cap on the amount of memory that can be allocated by session sort buffers (0 means unlimited)"))
1308  ("table-definition-cache", po::value<size_t>(&table_def_size)->default_value(128)->notifier(&check_limits_tdc),
1309  _("The number of cached table definitions."))
1310  ("table-open-cache", po::value<uint64_t>(&table_cache_size)->default_value(TABLE_OPEN_CACHE_DEFAULT)->notifier(&check_limits_toc),
1311  _("The number of cached open tables."))
1312  ("table-lock-wait-timeout", po::value<uint64_t>(&table_lock_wait_timeout)->default_value(50)->notifier(&check_limits_tlwt),
1313  _("Timeout in seconds to wait for a table level lock before returning an "
1314  "error. Used only if the connection has active cursors."))
1315  ("thread-stack", po::value<size_t>(&my_thread_stack_size)->default_value(0)->notifier(&check_limits_thread_stack),
1316  _("The stack size for each thread."))
1317  ("tmp-table-size",
1318  po::value<uint64_t>(&global_system_variables.tmp_table_size)->default_value(16*1024*1024L)->notifier(&check_limits_tmp_table_size),
1319  _("If an internal in-memory temporary table exceeds this size, Drizzle will"
1320  " automatically convert it to an on-disk MyISAM table."))
1321  ("verbose", po::value<std::string>()->default_value(error::verbose_string())->notifier(&error::check_verbosity),
1322  _("The verbosity of messages from drizzled. Possible values are INSPECT, INFO, WARN or ERROR"))
1323  ;
1324 
1325  full_options.add(long_options);
1326  full_options.add(plugin_load_options);
1327 
1328  initial_options.add(general_options);
1329  initial_options.add(config_options);
1330  initial_options.add(plugin_load_options);
1331 
1332  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
1333 
1334  /* Get options about where config files and the like are */
1335  po::parsed_options parsed= po::command_line_parser(argc, argv).style(style).
1336  options(initial_options).allow_unregistered().run();
1337 
1338  unknown_options= po::collect_unrecognized(parsed.options, po::include_positional);
1339 
1340  try
1341  {
1342  po::store(parsed, vm);
1343  }
1344  catch (std::exception&)
1345  {
1346  unireg_abort << _("Duplicate entry for command line option");
1347  }
1348 
1349  /* TODO: here is where we should add a process_env_vars */
1350 
1351  /* We need a notify here so that plugin_init will work properly */
1352  try
1353  {
1354  po::notify(vm);
1355  }
1356  catch (po::validation_error &err)
1357  {
1358  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1359  }
1360 
1361  if (vm.count("version"))
1362  {
1363  print_version();
1364  unireg_exit();
1365  }
1366 
1367  if (!vm["no-defaults"].as<bool>())
1368  {
1369  fs::path system_config_file_drizzle(system_config_dir);
1370  system_config_file_drizzle /= "drizzled.cnf";
1371  defaults_file_list.insert(defaults_file_list.begin(), system_config_file_drizzle.file_string());
1372 
1373  fs::path config_conf_d_location(system_config_dir);
1374  config_conf_d_location /= "conf.d";
1375 
1376  CachedDirectory config_conf_d(config_conf_d_location.file_string());
1377  if (not config_conf_d.fail())
1378  {
1379  BOOST_FOREACH(CachedDirectory::Entries::const_reference iter, config_conf_d.getEntries())
1380  {
1381  string file_entry(iter->filename);
1382  if (not file_entry.empty() && file_entry != "." && file_entry != "..")
1383  defaults_file_list.push_back((config_conf_d_location / file_entry).file_string());
1384  }
1385  }
1386  }
1387 
1388  process_defaults_files();
1389 
1390  /* Process with notify a second time because a config file may contain
1391  plugin loader options */
1392 
1393  try
1394  {
1395  po::notify(vm);
1396  }
1397  catch (po::validation_error &err)
1398  {
1399  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1400  }
1401 
1402  return true;
1403 }
1404 
1405 // Return failure if we can't pass this, unireg_abort() will then be called
1406 // by the caller.
1407 bool init_variables_after_daemonizing(module::Registry &plugins)
1408 {
1409  int style = po::command_line_style::default_style & ~po::command_line_style::allow_guessing;
1410 
1411  current_pid= getpid(); /* Save for later ref */
1412 
1413  /* At this point, we've read all the options we need to read from files and
1414  collected most of them into unknown options - now let's load everything
1415  */
1416 
1417  if (plugin_init(plugins, plugin_options))
1418  {
1419  unireg_abort << _("Failed to initialize plugins");
1420  }
1421 
1422  full_options.add(plugin_options);
1423 
1424  if ( was_help_requested())
1425  {
1426  bool usage();
1427  usage();
1428  }
1429 
1430  vector<string> final_unknown_options;
1431  try
1432  {
1433  po::parsed_options final_parsed=
1434  po::command_line_parser(unknown_options).style(style).
1435  options(full_options).extra_parser(dpo::parse_size_arg).run();
1436 
1437  final_unknown_options=
1438  po::collect_unrecognized(final_parsed.options, po::include_positional);
1439 
1440  po::store(final_parsed, vm);
1441 
1442  }
1443  catch (po::validation_error &err)
1444  {
1445  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1446  }
1447  catch (po::invalid_command_line_syntax &err)
1448  {
1449  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1450  }
1451  catch (po::unknown_option &err)
1452  {
1453  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1454  }
1455 
1456  try
1457  {
1458  po::notify(vm);
1459  }
1460  catch (po::validation_error &err)
1461  {
1462  unireg_abort << err.what() << ". " << "Use --help to get a list of available options. ";
1463  }
1464 
1465  get_options();
1466 
1467  /* Inverted Booleans */
1468 
1469  global_system_variables.optimizer_prune_level= not vm.count("disable-optimizer-prune");
1470 
1471  if ((user_info= check_user(drizzled_user)))
1472  {
1473  set_user(drizzled_user, user_info);
1474  }
1475 
1476  fix_paths();
1477 
1478  /* Save pid to this process (or thread on Linux) */
1479  create_pid_file();
1480 
1481  init_time(); /* Init time-functions (read zone) */
1482 
1483  item_create_init();
1484  if (sys_var_init())
1485  {
1486  return false;
1487  }
1488 
1489  /* Creates static regex matching for temporal values */
1490  if (not init_temporal_formats())
1491  {
1492  return false;
1493  }
1494 
1495  if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)))
1496  {
1497  errmsg_printf(error::ERROR, _("Error getting default charset"));
1498  return false; // Eof of the list
1499  }
1500 
1501  if (vm.count("scheduler"))
1502  {
1503  opt_scheduler= vm["scheduler"].as<string>().c_str();
1504  }
1505 
1506  /* Set collactions that depends on the default collation */
1507  global_system_variables.collation_server= default_charset_info;
1508 
1509  if (not (character_set_filesystem= get_charset_by_csname("binary", MY_CS_PRIMARY)))
1510  {
1511  errmsg_printf(error::ERROR, _("Error setting collation"));
1512  return false;
1513  }
1514  global_system_variables.character_set_filesystem= character_set_filesystem;
1515 
1516  if ((my_default_lc_time_names= my_locale_by_name(lc_time_names_name)) == NULL)
1517  {
1518  errmsg_printf(error::ERROR, _("Unknown locale: '%s'"), lc_time_names_name);
1519  return false;
1520  }
1521  global_system_variables.lc_time_names= my_default_lc_time_names;
1522 
1523  /* Reset table_alias_charset */
1524  table_alias_charset= files_charset_info;
1525 
1526  return true;
1527 }
1528 
1529 bool was_help_requested()
1530 {
1531  return bool(vm.count("help"));
1532 }
1533 
1534 void usage();
1535 
1536 void init_server_components(module::Registry &plugins)
1537 {
1538  if (was_help_requested())
1539  {
1540  usage();
1541  }
1542 
1543  /*
1544  We need to call each of these following functions to ensure that
1545  all things are initialized so that unireg_abort() doesn't fail
1546  */
1547 
1548  // Resize the definition Cache at startup
1549  table::Cache::rehash(table_def_size);
1550  definition::Cache::rehash(table_def_size);
1551  message::Cache::singleton().rehash(table_def_size);
1552 
1553  setup_fpu();
1554 
1555  /* Allow storage engine to give real error messages */
1556  ha_init_errors();
1557 
1558  if (plugin_finalize(plugins))
1559  {
1560  unireg_abort << "plugin_finalize() failed";
1561  }
1562 
1563  if (plugin::Scheduler::setPlugin(opt_scheduler))
1564  {
1565  unireg_abort << _("No scheduler found");
1566  }
1567 
1568  /*
1569  This is entirely for legacy. We will create a new "disk based" engine and a
1570  "memory" engine which will be configurable longterm.
1571  */
1572  myisam_engine= plugin::StorageEngine::findByName("MyISAM");
1573  heap_engine= plugin::StorageEngine::findByName("MEMORY");
1574 
1575  /*
1576  Check that the default storage engine is actually available.
1577  */
1578  if (default_storage_engine_str)
1579  {
1580  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(default_storage_engine_str);
1581  if (engine == NULL)
1582  {
1583  unireg_abort << _("Unknown/unsupported storage engine: ") << default_storage_engine_str;
1584  }
1585  global_system_variables.storage_engine= engine;
1586  }
1587 
1588  if (plugin::XaResourceManager::recoverAllXids())
1589  {
1590  /* This function alredy generates error messages */
1591  unireg_abort << "plugin::XaResourceManager::recoverAllXids() failed";
1592  }
1593 
1594  init_update_queries();
1595 }
1596 
1597 
1598 /****************************************************************************
1599  Handle start options
1600 ******************************************************************************/
1601 
1602 enum options_drizzled
1603 {
1604  OPT_SOCKET=256,
1605  OPT_BIND_ADDRESS,
1606  OPT_PID_FILE,
1607  OPT_STORAGE_ENGINE,
1608  OPT_INIT_FILE,
1609  OPT_WANT_CORE,
1610  OPT_MEMLOCK,
1611  OPT_SERVER_ID,
1612  OPT_TC_HEURISTIC_RECOVER,
1613  OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
1614  OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
1615  OPT_DO_PSTACK,
1616  OPT_LOCAL_INFILE,
1617  OPT_BACK_LOG,
1618  OPT_JOIN_BUFF_SIZE,
1619  OPT_MAX_ALLOWED_PACKET,
1620  OPT_MAX_HEP_TABLE_SIZE,
1621  OPT_MAX_JOIN_SIZE,
1622  OPT_MAX_SORT_LENGTH,
1623  OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
1624  OPT_MAX_LENGTH_FOR_SORT_DATA,
1625  OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
1626  OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
1627  OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
1628  OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
1629  OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS,
1630  OPT_NET_BUFFER_LENGTH,
1631  OPT_PRELOAD_BUFFER_SIZE,
1632  OPT_RECORD_BUFFER,
1633  OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT,
1634  OPT_DEBUGGING,
1635  OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE,
1636  OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
1637  OPT_WAIT_TIMEOUT,
1638  OPT_RANGE_ALLOC_BLOCK_SIZE,
1639  OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
1640  OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
1641  OPT_OLD_ALTER_TABLE,
1642  OPT_GROUP_CONCAT_MAX_LEN,
1643  OPT_DEFAULT_COLLATION,
1644  OPT_CHARACTER_SET_FILESYSTEM,
1645  OPT_LC_TIME_NAMES,
1646  OPT_INIT_CONNECT,
1647  OPT_DEFAULT_TIME_ZONE,
1648  OPT_OPTIMIZER_SEARCH_DEPTH,
1649  OPT_SCHEDULER,
1650  OPT_PROTOCOL,
1651  OPT_OPTIMIZER_PRUNE_LEVEL,
1652  OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
1653  OPT_ENABLE_LARGE_PAGES,
1654  OPT_TIMED_MUTEXES,
1655  OPT_TABLE_LOCK_WAIT_TIMEOUT,
1656  OPT_PLUGIN_ADD,
1657  OPT_PLUGIN_REMOVE,
1658  OPT_PLUGIN_LOAD,
1659  OPT_PLUGIN_DIR,
1660  OPT_PORT_OPEN_TIMEOUT,
1661  OPT_SECURE_FILE_PRIV,
1662  OPT_MIN_EXAMINED_ROW_LIMIT,
1663  OPT_PRINT_DEFAULTS
1664 };
1665 
1666 
1667 struct option my_long_options[] =
1668 {
1669  {"auto-increment-increment", OPT_AUTO_INCREMENT,
1670  N_("Auto-increment columns are incremented by this"),
1671  (char**) &global_system_variables.auto_increment_increment,
1672  NULL, 0, GET_ULL,
1673  OPT_ARG, 1, 1, INT64_MAX, 0, 1, 0 },
1674  {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
1675  N_("Offset added to Auto-increment columns. Used when "
1676  "auto-increment-increment != 1"),
1677  (char**) &global_system_variables.auto_increment_offset,
1678  NULL, 0, GET_ULL, OPT_ARG,
1679  1, 1, INT64_MAX, 0, 1, 0 },
1680  {"basedir", 'b',
1681  N_("Path to installation directory. All paths are usually resolved "
1682  "relative to this."),
1683  NULL, NULL, 0, GET_STR, REQUIRED_ARG,
1684  0, 0, 0, 0, 0, 0},
1685  {"chroot", 'r',
1686  N_("Chroot drizzled daemon during startup."),
1687  (char**) &drizzled_chroot, NULL, 0, GET_STR, REQUIRED_ARG,
1688  0, 0, 0, 0, 0, 0},
1689  {"completion-type", OPT_COMPLETION_TYPE,
1690  N_("Default completion type."),
1691  (char**) &global_system_variables.completion_type,
1692  NULL, 0, GET_UINT,
1693  REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
1694  {"core-file", OPT_WANT_CORE,
1695  N_("Write core on errors."),
1696  0, 0, 0, GET_NO_ARG,
1697  NO_ARG, 0, 0, 0, 0, 0, 0},
1698  {"datadir", 'h',
1699  N_("Path to the database root."),
1700  NULL, NULL, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1701  /* See how it's handled in get_one_option() */
1702  {"exit-info", 'T',
1703  N_("Used for debugging; Use at your own risk!"),
1704  0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
1705  /* We must always support the next option to make scripts like mysqltest
1706  easier to do */
1707  {"gdb", OPT_DEBUGGING,
1708  N_("Set up signals usable for debugging"),
1709  (char**) &opt_debugging, NULL,
1710  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1711  {"log-warnings", 'W',
1712  N_("Log some not critical warnings to the log file."),
1713  (char**) &global_system_variables.log_warnings,
1714  NULL, 0, GET_BOOL, OPT_ARG, 1, 0, 0,
1715  0, 0, 0},
1716  {"pid-file", OPT_PID_FILE,
1717  N_("Pid file used by drizzled."),
1718  NULL, NULL, 0, GET_STR,
1719  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1720  {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
1721  N_("Maximum time in seconds to wait for the port to become free. "
1722  "(Default: no wait)"),
1723  (char**) &drizzled_bind_timeout,
1724  NULL, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1725  {"secure-file-priv", OPT_SECURE_FILE_PRIV,
1726  N_("Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
1727  "within specified directory"),
1728  NULL, NULL, 0,
1729  GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1730  {"server-id", OPT_SERVER_ID,
1731  N_("Uniquely identifies the server instance in the community of "
1732  "replication partners."),
1733  (char**) &server_id, NULL, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 0,
1734  0, 0, 0},
1735  {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
1736  N_("Don't print a stack trace on failure."),
1737  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
1738  0, 0, 0, 0},
1739  {"symbolic-links", 's',
1740  N_("Enable symbolic link support."),
1741  (char**) &internal::my_use_symdir, NULL, 0, GET_BOOL, NO_ARG,
1742  /*
1743  The system call realpath() produces warnings under valgrind and
1744  purify. These are not suppressed: instead we disable symlinks
1745  option if compiled with valgrind support.
1746  */
1747  IF_PURIFY(0,1), 0, 0, 0, 0, 0},
1748  {"timed_mutexes", OPT_TIMED_MUTEXES,
1749  N_("Specify whether to time mutexes (only InnoDB mutexes are currently "
1750  "supported)"),
1751  (char**) &internal::timed_mutexes, NULL, 0, GET_BOOL, NO_ARG, 0,
1752  0, 0, 0, 0, 0},
1753  {"transaction-isolation", OPT_TX_ISOLATION,
1754  N_("Default transaction isolation level."),
1755  0, 0, 0, GET_STR, REQUIRED_ARG, 0,
1756  0, 0, 0, 0, 0},
1757  {"user", 'u',
1758  N_("Run drizzled daemon as user."),
1759  0, 0, 0, GET_STR, REQUIRED_ARG,
1760  0, 0, 0, 0, 0, 0},
1761  {"back_log", OPT_BACK_LOG,
1762  N_("The number of outstanding connection requests Drizzle can have. This "
1763  "comes into play when the main Drizzle thread gets very many connection "
1764  "requests in a very short time."),
1765  (char**) &back_log, NULL, 0, GET_UINT,
1766  REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
1767  { "bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
1768  N_("Size of tree cache used in bulk insert optimization. Note that this is "
1769  "a limit per thread!"),
1770  (char**) &global_system_variables.bulk_insert_buff_size,
1771  NULL,
1772  0, GET_ULL, REQUIRED_ARG, 8192*1024, 0, (int64_t)ULONG_MAX, 0, 1, 0},
1773  { "div_precision_increment", OPT_DIV_PRECINCREMENT,
1774  N_("Precision of the result of '/' operator will be increased on that "
1775  "value."),
1776  (char**) &global_system_variables.div_precincrement,
1777  NULL, 0, GET_UINT,
1778  REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
1779  { "join_buffer_size", OPT_JOIN_BUFF_SIZE,
1780  N_("The size of the buffer that is used for full joins."),
1781  (char**) &global_system_variables.join_buff_size,
1782  NULL, 0, GET_UINT64,
1783  REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, (int64_t)ULONG_MAX,
1784  MALLOC_OVERHEAD, IO_SIZE, 0},
1785  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
1786  N_("Max packetlength to send/receive from to server."),
1787  (char**) &global_system_variables.max_allowed_packet,
1788  NULL, 0, GET_UINT32,
1789  REQUIRED_ARG, 64*1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
1790  {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
1791  N_("Don't allow creation of heap tables bigger than this."),
1792  (char**) &global_system_variables.max_heap_table_size,
1793  NULL, 0, GET_ULL,
1794  REQUIRED_ARG, 16*1024*1024L, 16384, (int64_t)MAX_MEM_TABLE_SIZE,
1795  MALLOC_OVERHEAD, 1024, 0},
1796  {"max_join_size", OPT_MAX_JOIN_SIZE,
1797  N_("Joins that are probably going to read more than max_join_size records "
1798  "return an error."),
1799  (char**) &global_system_variables.max_join_size,
1800  NULL, 0, GET_HA_ROWS, REQUIRED_ARG,
1801  INT32_MAX, 1, INT32_MAX, 0, 1, 0},
1802  {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
1803  N_("Max number of bytes in sorted records."),
1804  (char**) &global_system_variables.max_length_for_sort_data,
1805  NULL, 0, GET_ULL,
1806  REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
1807  { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
1808  N_("Limit assumed max number of seeks when looking up rows based on a key"),
1809  (char**) &global_system_variables.max_seeks_for_key,
1810  NULL, 0, GET_UINT64,
1811  REQUIRED_ARG, (int64_t)ULONG_MAX, 1, (int64_t)ULONG_MAX, 0, 1, 0 },
1812  {"max_sort_length", OPT_MAX_SORT_LENGTH,
1813  N_("The number of bytes to use when sorting BLOB or TEXT values "
1814  "(only the first max_sort_length bytes of each value are used; the "
1815  "rest are ignored)."),
1816  (char**) &global_system_variables.max_sort_length,
1817  NULL, 0, GET_SIZE,
1818  REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
1819  {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
1820  N_("After this many write locks, allow some read locks to run in between."),
1821  (char**) &max_write_lock_count, NULL, 0, GET_ULL,
1822  REQUIRED_ARG, (int64_t)ULONG_MAX, 1, (int64_t)ULONG_MAX, 0, 1, 0},
1823  {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT,
1824  N_("Don't log queries which examine less than min_examined_row_limit "
1825  "rows to file."),
1826  (char**) &global_system_variables.min_examined_row_limit,
1827  NULL, 0, GET_ULL,
1828  REQUIRED_ARG, 0, 0, (int64_t)ULONG_MAX, 0, 1L, 0},
1829  {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
1830  N_("Controls the heuristic(s) applied during query optimization to prune "
1831  "less-promising partial plans from the optimizer search space. Meaning: "
1832  "false - do not apply any heuristic, thus perform exhaustive search; "
1833  "true - prune plans based on number of retrieved rows."),
1834  (char**) &global_system_variables.optimizer_prune_level,
1835  NULL,
1836  0, GET_BOOL, OPT_ARG, 1, 0, 1, 0, 1, 0},
1837  {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
1838  N_("Maximum depth of search performed by the query optimizer. Values "
1839  "larger than the number of relations in a query result in better query "
1840  "plans, but take longer to compile a query. Smaller values than the "
1841  "number of tables in a relation result in faster optimization, but may "
1842  "produce very bad query plans. If set to 0, the system will "
1843  "automatically pick a reasonable value; if set to MAX_TABLES+2, the "
1844  "optimizer will switch to the original find_best (used for "
1845  "testing/comparison)."),
1846  (char**) &global_system_variables.optimizer_search_depth,
1847  NULL,
1848  0, GET_UINT, OPT_ARG, 0, 0, MAX_TABLES+2, 0, 1, 0},
1849  {"plugin_dir", OPT_PLUGIN_DIR,
1850  N_("Directory for plugins."),
1851  NULL, NULL, 0,
1852  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1853  {"plugin_add", OPT_PLUGIN_ADD,
1854  N_("Optional comma separated list of plugins to load at startup in addition "
1855  "to the default list of plugins. "
1856  "[for example: --plugin_add=crc32,logger_gearman]"),
1857  NULL, NULL, 0,
1858  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1859  {"plugin_remove", OPT_PLUGIN_ADD,
1860  N_("Optional comma separated list of plugins to not load at startup. Effectively "
1861  "removes a plugin from the list of plugins to be loaded. "
1862  "[for example: --plugin_remove=crc32,logger_gearman]"),
1863  NULL, NULL, 0,
1864  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1865  {"plugin_load", OPT_PLUGIN_LOAD,
1866  N_("Optional comma separated list of plugins to load at starup instead of "
1867  "the default plugin load list. "
1868  "[for example: --plugin_load=crc32,logger_gearman]"),
1869  NULL, NULL, 0,
1870  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1871  {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
1872  N_("The size of the buffer that is allocated when preloading indexes"),
1873  (char**) &global_system_variables.preload_buff_size,
1874  NULL, 0, GET_ULL,
1875  REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
1876  {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
1877  N_("Allocation block size for query parsing and execution"),
1878  (char**) &global_system_variables.query_alloc_block_size,
1879  NULL, 0, GET_UINT,
1880  REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, (int64_t)ULONG_MAX, 0, 1024, 0},
1881  {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
1882  N_("Persistent buffer for query parsing and execution"),
1883  (char**) &global_system_variables.query_prealloc_size,
1884  NULL, 0, GET_UINT,
1885  REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
1886  (int64_t)ULONG_MAX, 0, 1024, 0},
1887  {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
1888  N_("Allocation block size for storing ranges during optimization"),
1889  (char**) &global_system_variables.range_alloc_block_size,
1890  NULL, 0, GET_SIZE,
1891  REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, (int64_t)SIZE_MAX,
1892  0, 1024, 0},
1893  {"read_buffer_size", OPT_RECORD_BUFFER,
1894  N_("Each thread that does a sequential scan allocates a buffer of this "
1895  "size for each table it scans. If you do many sequential scans, you may "
1896  "want to increase this value."),
1897  (char**) &global_system_variables.read_buff_size,
1898  NULL,0, GET_UINT, REQUIRED_ARG,
1899  128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT32_MAX, MALLOC_OVERHEAD, IO_SIZE,
1900  0},
1901  {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
1902  N_("When reading rows in sorted order after a sort, the rows are read "
1903  "through this buffer to avoid a disk seeks. If not set, then it's set "
1904  "to the value of record_buffer."),
1905  (char**) &global_system_variables.read_rnd_buff_size,
1906  NULL, 0,
1907  GET_UINT, REQUIRED_ARG, 256*1024L, 64 /*IO_SIZE*2+MALLOC_OVERHEAD*/ ,
1908  UINT32_MAX, MALLOC_OVERHEAD, 1 /* Small lower limit to be able to test MRR */, 0},
1909  /* x8 compared to MySQL's x2. We have UTF8 to consider. */
1910  {"sort_buffer_size", OPT_SORT_BUFFER,
1911  N_("Each thread that needs to do a sort allocates a buffer of this size."),
1912  (char**) &global_system_variables.sortbuff_size,
1913  NULL, 0, GET_SIZE, REQUIRED_ARG,
1914  MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*8, (int64_t)SIZE_MAX,
1915  MALLOC_OVERHEAD, 1, 0},
1916  {"table_definition_cache", OPT_TABLE_DEF_CACHE,
1917  N_("The number of cached table definitions."),
1918  (char**) &table_def_size, NULL,
1919  0, GET_SIZE, REQUIRED_ARG, 128, 1, 512*1024L, 0, 1, 0},
1920  {"table_open_cache", OPT_TABLE_OPEN_CACHE,
1921  N_("The number of cached open tables."),
1922  (char**) &table_cache_size, NULL, 0, GET_UINT64,
1923  REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, TABLE_OPEN_CACHE_MIN, 512*1024L, 0, 1, 0},
1924  {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT,
1925  N_("Timeout in seconds to wait for a table level lock before returning an "
1926  "error. Used only if the connection has active cursors."),
1927  (char**) &table_lock_wait_timeout, NULL,
1928  0, GET_ULL, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
1929  {"thread_stack", OPT_THREAD_STACK,
1930  N_("The stack size for each thread."),
1931  (char**) &my_thread_stack_size,
1932  NULL, 0, GET_SIZE,
1933  REQUIRED_ARG,0,
1934  UINT32_C(1024*512), (int64_t)SIZE_MAX, 0, 1024, 0},
1935  {"tmp_table_size", OPT_TMP_TABLE_SIZE,
1936  N_("If an internal in-memory temporary table exceeds this size, Drizzle will"
1937  " automatically convert it to an on-disk MyISAM table."),
1938  (char**) &global_system_variables.tmp_table_size,
1939  NULL, 0, GET_ULL,
1940  REQUIRED_ARG, 16*1024*1024L, 1024, (int64_t)MAX_MEM_TABLE_SIZE, 0, 1, 0},
1941  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1942 };
1943 
1944 void usage()
1945 {
1946  if ((default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY)) == NULL)
1947  {
1948  unireg_abort << "Failed to load default_charset_info:" << default_character_set_name;
1949  }
1950 
1951  if (default_collation_name == NULL)
1952  {
1953  default_collation_name= default_charset_info->name;
1954  }
1955 
1956  print_version();
1957  puts(_("Copyright (C) 2010-2011 Drizzle Developers, Copyright (C) 2008 Sun Microsystems\n"
1958  "This software comes with ABSOLUTELY NO WARRANTY. "
1959  "This is free software,\n"
1960  "and you are welcome to modify and redistribute it under the GPL "
1961  "license\n\n"));
1962 
1963 
1964  printf(_("Usage: %s [OPTIONS]\n"), internal::my_progname);
1965 
1966  po::options_description all_options("Drizzled Options");
1967  all_options.add(general_options);
1968  all_options.add(config_options);
1969  all_options.add(plugin_load_options);
1970  all_options.add(long_options);
1971  all_options.add(plugin_options);
1972  cout << all_options << endl;
1973 
1974  unireg_exit();
1975 }
1976 
1994 {
1995  /* Things reset to zero */
1996  cleanup_done= 0;
1997  dropping_tables= ha_open_options=0;
1998  getDebug().reset();
1999  wake_thread=0;
2000  abort_loop= select_thread_in_use= false;
2001  shutdown_in_progress= 0;
2002  drizzled_user= drizzled_chroot= 0;
2003  memset(&current_global_counters, 0, sizeof(current_global_counters));
2004  key_map_full.set();
2005 
2006  /* Character sets */
2007  system_charset_info= &my_charset_utf8_general_ci;
2008  files_charset_info= &my_charset_utf8_general_ci;
2009  table_alias_charset= &my_charset_bin;
2010  character_set_filesystem= &my_charset_bin;
2011 
2012  /* Things with default values that are not zero */
2013  session_startup_options= (OPTION_AUTO_IS_NULL | OPTION_SQL_NOTES);
2014  global_thread_id= 1;
2015  session::Cache::getCache().clear();
2016 
2017  /* Set default values for some option variables */
2018  global_system_variables.storage_engine= NULL;
2019  global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
2020  global_system_variables.select_limit= (uint64_t) HA_POS_ERROR;
2021  max_system_variables.select_limit= (uint64_t) HA_POS_ERROR;
2022  global_system_variables.max_join_size= (uint64_t) HA_POS_ERROR;
2023  max_system_variables.max_join_size= (uint64_t) HA_POS_ERROR;
2024  max_system_variables.auto_increment_increment= UINT64_MAX;
2025  max_system_variables.auto_increment_offset= UINT64_MAX;
2026  max_system_variables.completion_type= 2;
2027  max_system_variables.log_warnings= true;
2028  max_system_variables.bulk_insert_buff_size= ULONG_MAX;
2029  max_system_variables.div_precincrement= DECIMAL_MAX_SCALE;
2030  max_system_variables.group_concat_max_len= ULONG_MAX;
2031  max_system_variables.join_buff_size= ULONG_MAX;
2032  max_system_variables.max_allowed_packet= 1024L*1024L*1024L;
2033  max_system_variables.max_error_count= 65535;
2034  max_system_variables.max_heap_table_size= MAX_MEM_TABLE_SIZE;
2035  max_system_variables.max_join_size= INT32_MAX;
2036  max_system_variables.max_length_for_sort_data= 8192*1024L;
2037  max_system_variables.max_seeks_for_key= ULONG_MAX;
2038  max_system_variables.max_sort_length= 8192*1024L;
2039  max_system_variables.min_examined_row_limit= ULONG_MAX;
2040  max_system_variables.optimizer_prune_level= 1;
2041  max_system_variables.optimizer_search_depth= MAX_TABLES+2;
2042  max_system_variables.preload_buff_size= 1024*1024*1024L;
2043  max_system_variables.query_alloc_block_size= UINT32_MAX;
2044  max_system_variables.query_prealloc_size= UINT32_MAX;
2045  max_system_variables.range_alloc_block_size= SIZE_MAX;
2046  max_system_variables.read_buff_size= INT32_MAX;
2047  max_system_variables.read_rnd_buff_size= UINT32_MAX;
2048  max_system_variables.sortbuff_size= SIZE_MAX;
2049  max_system_variables.tmp_table_size= MAX_MEM_TABLE_SIZE;
2050 
2051  /* Variables that depends on compile options */
2052 #ifdef HAVE_BROKEN_REALPATH
2053  have_symlink=SHOW_OPTION_NO;
2054 #else
2055  have_symlink=SHOW_OPTION_YES;
2056 #endif
2057 }
2058 
2059 
2064 static void get_options()
2065 {
2066  catalog::resetPath_for_local_identifier();
2067 
2068  if (vm.count("user"))
2069  {
2070  if (drizzled_user == NULL or strcmp(drizzled_user, vm["user"].as<string>().c_str()) == 0)
2071  {
2072  drizzled_user= (char *)vm["user"].as<string>().c_str();
2073  }
2074  else
2075  {
2076  errmsg_printf(error::WARN, _("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line"),
2077  vm["user"].as<string>().c_str(), drizzled_user);
2078  }
2079  }
2080 
2081  if (vm.count("sort-heap-threshold"))
2082  {
2083  if ((vm["sort-heap-threshold"].as<uint64_t>() > 0) and
2084  (vm["sort-heap-threshold"].as<uint64_t>() < global_system_variables.sortbuff_size))
2085  {
2086  unireg_abort << _("sort-heap-threshold cannot be less than sort-buffer-size");
2087  }
2088 
2089  global_sort_buffer.setMaxSize(vm["sort-heap-threshold"].as<uint64_t>());
2090  }
2091 
2092  if (vm.count("join-heap-threshold"))
2093  {
2094  if ((vm["join-heap-threshold"].as<uint64_t>() > 0) and
2095  (vm["join-heap-threshold"].as<uint64_t>() < global_system_variables.join_buff_size))
2096  {
2097  unireg_abort << _("join-heap-threshold cannot be less than join-buffer-size");
2098  }
2099 
2100  global_join_buffer.setMaxSize(vm["join-heap-threshold"].as<uint64_t>());
2101  }
2102 
2103  if (vm.count("read-rnd-threshold"))
2104  {
2105  if ((vm["read-rnd-threshold"].as<uint64_t>() > 0) and
2106  (vm["read-rnd-threshold"].as<uint64_t>() < global_system_variables.read_rnd_buff_size))
2107  {
2108  unireg_abort << _("read-rnd-threshold cannot be less than read-rnd-buffer-size");
2109  }
2110 
2111  global_read_rnd_buffer.setMaxSize(vm["read-rnd-threshold"].as<uint64_t>());
2112  }
2113 
2114  if (vm.count("read-buffer-threshold"))
2115  {
2116  if ((vm["read-buffer-threshold"].as<uint64_t>() > 0) and
2117  (vm["read-buffer-threshold"].as<uint64_t>() < global_system_variables.read_buff_size))
2118  {
2119  unireg_abort << _("read-buffer-threshold cannot be less than read-buffer-size");
2120  }
2121 
2122  global_read_buffer.setMaxSize(vm["read-buffer-threshold"].as<uint64_t>());
2123  }
2124 
2125  if (vm.count("exit-info"))
2126  {
2127  if (vm["exit-info"].as<long>())
2128  {
2129  getDebug().set((uint32_t) vm["exit-info"].as<long>());
2130  }
2131  }
2132 
2133  if (vm.count("want-core"))
2134  {
2135  getDebug().set(debug::CORE_ON_SIGNAL);
2136  }
2137 
2138  if (vm.count("skip-stack-trace"))
2139  {
2140  getDebug().set(debug::NO_STACKTRACE);
2141  }
2142 
2143  if (vm.count("skip-symlinks"))
2144  {
2145  internal::my_use_symdir= 0;
2146  }
2147 
2148  if (vm.count("collation-server"))
2149  {
2150  const charset_info_st * const default_collation= get_charset_by_name(vm["collation-server"].as<string>().c_str());
2151  if (not default_collation)
2152  {
2153  unireg_abort << "Unknown collation: " << default_collation_name;
2154  }
2155 
2156  if (not my_charset_same(default_charset_info, default_collation))
2157  {
2158  unireg_abort << "COLLATION '" << default_collation_name << "' is not valid for CHARACTER SET '" << default_charset_info->csname << "'";
2159  }
2160  default_charset_info= default_collation;
2161  }
2162 
2163  if (vm.count("transaction-isolation"))
2164  {
2165  int type= tx_isolation_typelib.find_type_or_exit(vm["transaction-isolation"].as<string>().c_str(), "transaction-isolation");
2166  global_system_variables.tx_isolation= type - 1;
2167  }
2168 
2169  /* @TODO Make this all strings */
2170  if (vm.count("default-storage-engine"))
2171  {
2172  default_storage_engine_str= vm["default-storage-engine"].as<string>().c_str();
2173  }
2174 
2175 
2176 #if defined(HAVE_BROKEN_REALPATH)
2177  internal::my_use_symdir=0;
2178  internal::my_disable_symlinks=1;
2179  have_symlink=SHOW_OPTION_NO;
2180 #else
2181  if (!internal::my_use_symdir)
2182  {
2183  internal::my_disable_symlinks=1;
2184  have_symlink=SHOW_OPTION_DISABLED;
2185  }
2186 #endif
2187  if (opt_debugging)
2188  {
2189  /* Allow break with SIGINT, no core or stack trace */
2190  getDebug().set(debug::ALLOW_SIGINT);
2191  getDebug().set(debug::NO_STACKTRACE);
2192  getDebug().reset(debug::CORE_ON_SIGNAL);
2193  }
2194 
2195  if (drizzled_chroot)
2196  {
2197  set_root(drizzled_chroot);
2198  }
2199 
2200  /*
2201  Set some global variables from the global_system_variables
2202  In most cases the global variables will not be used
2203  */
2204  internal::my_default_record_cache_size=global_system_variables.read_buff_size;
2205 }
2206 
2207 
2208 static void fix_paths()
2209 {
2210 
2211  {
2212  if (pid_file.string().size() and pid_file.string()[0] == '/')
2213  { } // Do nothing if the file starts with a slash
2214  else
2215  {
2216  fs::path pid_file_path(pid_file);
2217  if (pid_file_path.root_path().string() == "")
2218  {
2219  pid_file_path= getDataHome();
2220  pid_file_path /= pid_file;
2221  }
2222  pid_file= fs::system_complete(pid_file_path);
2223  }
2224  }
2225 
2226  const char *tmp_string= getenv("TMPDIR");
2227  struct stat buf;
2228  drizzle_tmpdir.clear();
2229 
2230  if (vm.count("tmpdir"))
2231  {
2232  drizzle_tmpdir.append(vm["tmpdir"].as<string>());
2233  }
2234  else if (tmp_string == NULL)
2235  {
2236  drizzle_tmpdir.append(getDataHome().file_string());
2237  drizzle_tmpdir.push_back(FN_LIBCHAR);
2238  drizzle_tmpdir.append(GLOBAL_TEMPORARY_EXT);
2239  }
2240  else
2241  {
2242  drizzle_tmpdir.append(tmp_string);
2243  }
2244 
2245  drizzle_tmpdir= fs::path(fs::system_complete(fs::path(drizzle_tmpdir))).file_string();
2246  assert(drizzle_tmpdir.size());
2247 
2248  assert(getuid() != 0 and geteuid() != 0);
2249  if (getuid() == 0 or geteuid() == 0)
2250  {
2251  unireg_abort << "Drizzle cannot be run as root, please see the Security piece of the manual for more information.";
2252  }
2253 
2254  if (mkdir(drizzle_tmpdir.c_str(), 0777) == -1)
2255  {
2256  if (errno != EEXIST)
2257  {
2258  unireg_abort << "There was an error creating the '"
2259  << fs::path(drizzle_tmpdir).leaf()
2260  << "' part of the path '"
2261  << drizzle_tmpdir
2262  << "'. Please check the path exists and is writable.";
2263  }
2264  }
2265 
2266  if (stat(drizzle_tmpdir.c_str(), &buf) || not S_ISDIR(buf.st_mode))
2267  {
2268  unireg_abort << "There was an error opening the path '" << drizzle_tmpdir << "', please check the path exists and is writable.";
2269  }
2270 }
2271 
2272 } /* namespace drizzled */
2273