~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/main.cc

Refactored the data file creation routine in BlitzData class.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include <config.h>
 
20
#include "config.h"
21
21
 
22
22
#include <pthread.h>
23
23
#include <signal.h>
24
24
#include <sys/resource.h>
25
25
#include <unistd.h>
26
 
#include <sys/stat.h>
27
 
#include <sys/types.h>
28
 
 
29
26
 
30
27
#if TIME_WITH_SYS_TIME
31
28
# include <sys/time.h>
42
39
# include <locale.h>
43
40
#endif
44
41
 
45
 
#include <boost/filesystem.hpp>
46
42
 
47
 
#include <drizzled/abort_exception.h>
48
 
#include <drizzled/catalog/local.h>
49
 
#include <drizzled/configmake.h>
50
 
#include <drizzled/data_home.h>
51
 
#include <drizzled/debug.h>
52
 
#include <drizzled/drizzled.h>
53
 
#include <drizzled/errmsg_print.h>
54
 
#include <drizzled/gettext.h>
55
 
#include <drizzled/internal/my_sys.h>
56
 
#include <drizzled/plugin.h>
57
 
#include <drizzled/plugin/client.h>
58
 
#include <drizzled/plugin/listen.h>
59
 
#include <drizzled/plugin/monitored_in_transaction.h>
60
 
#include <drizzled/pthread_globals.h>
61
 
#include <drizzled/replication_services.h>
62
 
#include <drizzled/session.h>
63
 
#include <drizzled/session/cache.h>
64
 
#include <drizzled/signal_handler.h>
65
 
#include <drizzled/transaction_services.h>
66
 
#include <drizzled/tztime.h>
67
 
#include <drizzled/unireg.h>
68
 
#include <drizzled/util/backtrace.h>
69
 
#include <drizzled/current_session.h>
70
 
#include <drizzled/daemon.h>
 
43
#include "drizzled/plugin.h"
 
44
#include "drizzled/gettext.h"
 
45
#include "drizzled/configmake.h"
 
46
#include "drizzled/session.h"
 
47
#include "drizzled/internal/my_sys.h"
 
48
#include "drizzled/unireg.h"
 
49
#include "drizzled/stacktrace.h"
 
50
#include "drizzled/drizzled.h"
 
51
#include "drizzled/errmsg_print.h"
 
52
#include "drizzled/data_home.h"
 
53
#include "drizzled/plugin/listen.h"
 
54
#include "drizzled/plugin/client.h"
 
55
#include "drizzled/pthread_globals.h"
 
56
#include "drizzled/tztime.h"
 
57
#include "drizzled/signal_handler.h"
 
58
#include "drizzled/replication_services.h"
71
59
 
72
60
using namespace drizzled;
73
61
using namespace std;
75
63
static pthread_t select_thread;
76
64
static uint32_t thr_kill_signal;
77
65
 
78
 
extern bool opt_daemon;
79
 
 
80
 
 
81
66
/**
82
67
  All global error messages are sent here where the first one is stored
83
68
  for the client.
84
69
*/
85
 
static void my_message_sql(drizzled::error_t error, const char *str, myf MyFlags)
 
70
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
86
71
{
87
72
  Session *session;
88
73
  /*
95
80
      session->is_fatal_error= 1;
96
81
 
97
82
    /*
98
 
      @TODO There are two exceptions mechanism (Session and sp_rcontext),
 
83
      TODO: There are two exceptions mechanism (Session and sp_rcontext),
99
84
      this could be improved by having a common stack of handlers.
100
85
    */
101
 
    if (session->handle_error(error, str, DRIZZLE_ERROR::WARN_LEVEL_ERROR))
102
 
      return;
 
86
    if (session->handle_error(error, str,
 
87
                          DRIZZLE_ERROR::WARN_LEVEL_ERROR))
 
88
      return;;
103
89
 
104
90
    /*
105
 
      session->getLex()->current_select == 0 if lex structure is not inited
 
91
      session->lex->current_select == 0 if lex structure is not inited
106
92
      (not query command (COM_QUERY))
107
93
    */
108
 
    if (! (session->getLex()->current_select &&
109
 
           session->getLex()->current_select->no_error && !session->is_fatal_error))
 
94
    if (! (session->lex->current_select &&
 
95
        session->lex->current_select->no_error && !session->is_fatal_error))
110
96
    {
111
97
      if (! session->main_da.is_error())            // Return only first message
112
98
      {
113
 
        if (error == EE_OK)
 
99
        if (error == 0)
114
100
          error= ER_UNKNOWN_ERROR;
115
 
 
116
101
        if (str == NULL)
117
102
          str= ER(error);
118
 
 
119
103
        session->main_da.set_error_status(error, str);
120
104
      }
121
105
    }
129
113
      session->no_warnings_for_error= true;
130
114
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
131
115
      session->no_warnings_for_error= false;
 
116
      }
132
117
    }
133
 
  }
134
 
 
135
 
  if (not session || MyFlags & ME_NOREFRESH)
136
 
  {
137
 
    errmsg_printf(error::ERROR, "%s: %s",internal::my_progname,str);
138
 
  }
 
118
    if (!session || MyFlags & ME_NOREFRESH)
 
119
        errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",internal::my_progname,str);
139
120
}
140
121
 
141
122
static void init_signals(void)
143
124
  sigset_t set;
144
125
  struct sigaction sa;
145
126
 
146
 
  if (not (getDebug().test(debug::NO_STACKTRACE) || 
147
 
        getDebug().test(debug::CORE_ON_SIGNAL)))
 
127
  if (!(test_flags.test(TEST_NO_STACKTRACE) || 
 
128
        test_flags.test(TEST_CORE_ON_SIGNAL)))
148
129
  {
149
130
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
150
131
    sigemptyset(&sa.sa_mask);
151
132
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
152
133
 
 
134
    init_stacktrace();
153
135
    sa.sa_handler= drizzled_handle_segfault;
154
136
    sigaction(SIGSEGV, &sa, NULL);
155
137
    sigaction(SIGABRT, &sa, NULL);
160
142
    sigaction(SIGFPE, &sa, NULL);
161
143
  }
162
144
 
163
 
  if (getDebug().test(debug::CORE_ON_SIGNAL))
 
145
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
164
146
  {
165
147
    /* Change limits so that we will get a core file */
166
148
    struct rlimit rl;
167
149
    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
168
150
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
169
 
        errmsg_printf(error::WARN,
 
151
        errmsg_printf(ERRMSG_LVL_WARN,
170
152
                      _("setrlimit could not change the size of core files "
171
153
                        "to 'infinity';  We may not be able to generate a "
172
154
                        "core file on signals"));
191
173
#ifdef SIGTSTP
192
174
  sigaddset(&set,SIGTSTP);
193
175
#endif
194
 
  if (getDebug().test(debug::ALLOW_SIGINT))
 
176
  if (test_flags.test(TEST_SIGINT))
195
177
  {
196
178
    sa.sa_flags= 0;
197
179
    sa.sa_handler= drizzled_end_thread_signal;
209
191
  return;
210
192
}
211
193
 
212
 
static void GoogleProtoErrorThrower(google::protobuf::LogLevel level,
213
 
                                    const char* ,
214
 
                                    int, const string& ) throw(const char *)
 
194
static void GoogleProtoErrorThrower(google::protobuf::LogLevel level, const char* filename,
 
195
                       int line, const string& message) throw(const char *)
215
196
{
 
197
  (void)filename;
 
198
  (void)line;
 
199
  (void)message;
216
200
  switch(level)
217
201
  {
218
202
  case google::protobuf::LOGLEVEL_INFO:
231
215
# if defined(HAVE_LOCALE_H)
232
216
  setlocale(LC_ALL, "");
233
217
# endif
234
 
  bindtextdomain("drizzle7", LOCALEDIR);
235
 
  textdomain("drizzle7");
 
218
  bindtextdomain("drizzle", LOCALEDIR);
 
219
  textdomain("drizzle");
236
220
#endif
237
221
 
238
222
  module::Registry &modules= module::Registry::singleton();
 
223
  plugin::Client *client;
 
224
  Session *session;
239
225
 
240
226
  MY_INIT(argv[0]);             // init my_sys library & pthreads
241
227
  /* nothing should come before this line ^^^ */
242
228
 
243
229
  /* Set signal used to kill Drizzle */
 
230
#if defined(SIGUSR2)
 
231
  thr_kill_signal= internal::thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
 
232
#else
244
233
  thr_kill_signal= SIGINT;
 
234
#endif
245
235
 
246
236
  google::protobuf::SetLogHandler(&GoogleProtoErrorThrower);
247
237
 
248
 
  /* Function generates error messages before abort */
249
 
  error_handler_hook= my_message_sql;
250
 
 
251
 
  /* init_common_variables must get basic settings such as data_home_dir
252
 
     and plugin_load_list. */
253
 
  if (init_basic_variables(argc, argv))
254
 
    unireg_abort(1);                            // Will do exit
255
 
 
256
 
  if (opt_daemon)
257
 
  {
258
 
    if (signal(SIGHUP, SIG_IGN) == SIG_ERR)
259
 
    {
260
 
      perror("Failed to ignore SIGHUP");
261
 
    }
262
 
    if (daemonize())
263
 
    {
264
 
      fprintf(stderr, "failed to daemon() in order to daemonize\n");
265
 
      exit(EXIT_FAILURE);
266
 
    }
267
 
  }
268
 
 
269
 
  if (init_remaining_variables(modules))
270
 
    unireg_abort(1);                            // Will do exit
271
 
 
272
 
  /*
273
 
    init signals & alarm
274
 
    After this we can't quit by a simple unireg_abort
275
 
  */
 
238
  if (init_common_variables(DRIZZLE_CONFIG_NAME,
 
239
                            argc, argv, load_default_groups))
 
240
    unireg_abort(1);                            // Will do exit
 
241
 
276
242
  init_signals();
277
243
 
278
244
 
279
245
  select_thread=pthread_self();
280
246
  select_thread_in_use=1;
281
247
 
282
 
  if (not opt_help)
283
 
  {
284
 
    if (chdir(getDataHome().file_string().c_str()))
285
 
    {
286
 
      errmsg_printf(error::ERROR,
287
 
                    _("Data directory %s does not exist\n"),
288
 
                    getDataHome().file_string().c_str());
289
 
      unireg_abort(1);
290
 
    }
291
 
    if (mkdir("local", 0700))
292
 
    {
293
 
      /* We don't actually care */
294
 
    }
295
 
    if (chdir("local"))
296
 
    {
297
 
      errmsg_printf(error::ERROR,
298
 
                    _("Local catalog %s/local does not exist\n"),
299
 
                    getDataHome().file_string().c_str());
300
 
      unireg_abort(1);
301
 
    }
302
 
 
303
 
    boost::filesystem::path &full_data_home= getFullDataHome();
304
 
    full_data_home= boost::filesystem::system_complete(getDataHome());
305
 
    errmsg_printf(error::INFO, "Data Home directory is : %s", full_data_home.native_file_string().c_str());
306
 
  }
307
 
 
308
 
 
 
248
  if (chdir(data_home_real) && !opt_help)
 
249
  {
 
250
    errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), data_home_real);
 
251
    unireg_abort(1);
 
252
  }
 
253
  data_home= data_home_buff;
 
254
  data_home[0]=FN_CURLIB;               // all paths are relative from here
 
255
  data_home[1]=0;
 
256
  data_home_len= 2;
 
257
 
 
258
  if ((user_info= check_user(drizzled_user)))
 
259
  {
 
260
    set_user(drizzled_user, user_info);
 
261
  }
309
262
 
310
263
  if (server_id == 0)
311
264
  {
312
265
    server_id= 1;
313
266
  }
314
267
 
315
 
  try
316
 
  {
317
 
    if (init_server_components(modules))
318
 
      DRIZZLE_ABORT;
319
 
  }
320
 
  catch (abort_exception& ex)
321
 
  {
322
 
#if defined(DEBUG)
323
 
    cout << _("Drizzle has receieved an abort event.") << endl;
324
 
    cout << _("In Function: ") << *::boost::get_error_info<boost::throw_function>(ex) << endl;
325
 
    cout << _("In File: ") << *::boost::get_error_info<boost::throw_file>(ex) << endl;
326
 
    cout << _("On Line: ") << *::boost::get_error_info<boost::throw_line>(ex) << endl;
327
 
#endif
 
268
  if (init_server_components(modules))
328
269
    unireg_abort(1);
329
 
  }
330
 
 
331
270
 
332
271
  /**
333
272
   * This check must be done after init_server_components for now
346
285
  if (plugin::Listen::setup())
347
286
    unireg_abort(1);
348
287
 
 
288
  /*
 
289
    init signals & alarm
 
290
    After this we can't quit by a simple unireg_abort
 
291
  */
 
292
  error_handler_hook= my_message_sql;
 
293
 
349
294
  assert(plugin::num_trx_monitored_objects > 0);
350
 
  if (drizzle_rm_tmp_tables())
 
295
  if (drizzle_rm_tmp_tables() ||
 
296
      my_tz_init((Session *)0, default_tz_name))
351
297
  {
352
298
    abort_loop= true;
353
299
    select_thread_in_use=0;
354
300
    (void) pthread_kill(signal_thread, SIGTERM);
355
301
 
356
 
    (void) unlink(pid_file.file_string().c_str());      // Not needed anymore
 
302
    (void) unlink(pidfile_name);        // Not needed anymore
357
303
 
358
 
    unireg_abort(1);
 
304
    exit(1);
359
305
  }
360
306
 
361
 
  errmsg_printf(error::INFO, _(ER(ER_STARTUP)), internal::my_progname,
 
307
  errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
362
308
                PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
363
309
 
364
310
 
365
 
  TransactionServices &transaction_services= TransactionServices::singleton();
366
 
 
367
 
  /* Send server startup event */
368
 
  {
369
 
    Session::shared_ptr session;
370
 
 
371
 
    if ((session= Session::make_shared(plugin::Listen::getNullClient(), catalog::local())))
372
 
    {
373
 
      currentSession().release();
374
 
      currentSession().reset(session.get());
375
 
 
376
 
 
377
 
      transaction_services.sendStartupEvent(*session);
378
 
 
379
 
      plugin_startup_window(modules, *(session.get()));
380
 
    }
381
 
  }
382
 
 
383
 
  if (opt_daemon)
384
 
    daemon_is_ready();
385
 
 
386
 
  /* 
387
 
    Listen for new connections and start new session for each connection
 
311
  /* Listen for new connections and start new session for each connection
388
312
     accepted. The listen.getClient() method will return NULL when the server
389
 
     should be shutdown.
390
 
   */
391
 
  plugin::Client *client;
 
313
     should be shutdown. */
392
314
  while ((client= plugin::Listen::getClient()) != NULL)
393
315
  {
394
 
    Session::shared_ptr session;
395
 
    session= Session::make_shared(client, client->catalog());
396
 
 
397
 
    if (not session)
 
316
    if (!(session= new Session(client)))
398
317
    {
399
318
      delete client;
400
319
      continue;
401
320
    }
402
321
 
403
322
    /* If we error on creation we drop the connection and delete the session. */
404
 
    if (Session::schedule(session))
 
323
    if (session->schedule())
405
324
      Session::unlink(session);
406
325
  }
407
326
 
408
 
  /* Send server shutdown event */
409
 
  {
410
 
    Session::shared_ptr session;
411
 
 
412
 
    if ((session= Session::make_shared(plugin::Listen::getNullClient(), catalog::local())))
413
 
    {
414
 
      currentSession().release();
415
 
      currentSession().reset(session.get());
416
 
      transaction_services.sendShutdownEvent(*session.get());
417
 
    }
418
 
  }
419
 
 
420
 
  {
421
 
    boost::mutex::scoped_lock scopedLock(session::Cache::singleton().mutex());
422
 
    select_thread_in_use= false;                        // For close_connections
423
 
  }
424
 
  COND_thread_count.notify_all();
 
327
  /* (void) pthread_attr_destroy(&connection_attrib); */
 
328
 
 
329
 
 
330
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
331
  select_thread_in_use=0;                       // For close_connections
 
332
  (void) pthread_mutex_unlock(&LOCK_thread_count);
 
333
  (void) pthread_cond_broadcast(&COND_thread_count);
425
334
 
426
335
  /* Wait until cleanup is done */
427
 
  session::Cache::singleton().shutdownSecond();
 
336
  (void) pthread_mutex_lock(&LOCK_thread_count);
 
337
  while (!ready_to_exit)
 
338
    pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
 
339
  (void) pthread_mutex_unlock(&LOCK_thread_count);
428
340
 
429
341
  clean_up(1);
430
342
  module::Registry::shutdown();
 
343
  clean_up_mutexes();
431
344
  internal::my_end();
432
 
 
433
345
  return 0;
434
346
}
435
347