~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/main.cc

  • Committer: Monty Taylor
  • Date: 2008-08-05 19:01:20 UTC
  • mto: (266.1.1 codestyle)
  • mto: This revision was merged to the branch mainline in revision 266.
  • Revision ID: monty@inaugust.com-20080805190120-tsuziqz2mfqcw7pe
Removed libmysyslt.la, made mysys a noinst_ and made everything use it. It's
not a standalone lib, there's no reason to pretend otherwise.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
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 <pthread.h>
23
 
#include <signal.h>
24
 
#include <sys/resource.h>
25
 
#include <unistd.h>
26
 
#include <sys/stat.h>
27
 
#include <sys/types.h>
28
 
 
29
 
 
30
 
#if TIME_WITH_SYS_TIME
31
 
# include <sys/time.h>
32
 
# include <time.h>
33
 
#else
34
 
# if HAVE_SYS_TIME_H
35
 
#  include <sys/time.h>
36
 
# else
37
 
#  include <time.h>
38
 
# endif
39
 
#endif
40
 
 
41
 
#if defined(HAVE_LOCALE_H)
42
 
# include <locale.h>
43
 
#endif
44
 
 
45
 
#include <boost/filesystem.hpp>
46
 
 
47
 
#include "drizzled/plugin.h"
48
 
#include "drizzled/gettext.h"
49
 
#include "drizzled/configmake.h"
50
 
#include "drizzled/session.h"
51
 
#include "drizzled/internal/my_sys.h"
52
 
#include "drizzled/unireg.h"
53
 
#include "drizzled/drizzled.h"
54
 
#include "drizzled/errmsg_print.h"
55
 
#include "drizzled/data_home.h"
56
 
#include "drizzled/plugin/listen.h"
57
 
#include "drizzled/plugin/client.h"
58
 
#include "drizzled/pthread_globals.h"
59
 
#include "drizzled/tztime.h"
60
 
#include "drizzled/signal_handler.h"
61
 
#include "drizzled/replication_services.h"
62
 
 
63
 
using namespace drizzled;
64
 
using namespace std;
65
 
namespace fs=boost::filesystem;
66
 
 
67
 
static pthread_t select_thread;
68
 
static uint32_t thr_kill_signal;
69
 
 
70
 
 
71
 
/**
72
 
  All global error messages are sent here where the first one is stored
73
 
  for the client.
74
 
*/
75
 
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
76
 
{
77
 
  Session *session;
78
 
  /*
79
 
    Put here following assertion when situation with EE_* error codes
80
 
    will be fixed
81
 
  */
82
 
  if ((session= current_session))
83
 
  {
84
 
    if (MyFlags & ME_FATALERROR)
85
 
      session->is_fatal_error= 1;
86
 
 
87
 
    /*
88
 
      TODO: There are two exceptions mechanism (Session and sp_rcontext),
89
 
      this could be improved by having a common stack of handlers.
90
 
    */
91
 
    if (session->handle_error(error, str,
92
 
                          DRIZZLE_ERROR::WARN_LEVEL_ERROR))
93
 
      return;;
94
 
 
95
 
    /*
96
 
      session->lex->current_select == 0 if lex structure is not inited
97
 
      (not query command (COM_QUERY))
98
 
    */
99
 
    if (! (session->lex->current_select &&
100
 
        session->lex->current_select->no_error && !session->is_fatal_error))
101
 
    {
102
 
      if (! session->main_da.is_error())            // Return only first message
103
 
      {
104
 
        if (error == 0)
105
 
          error= ER_UNKNOWN_ERROR;
106
 
        if (str == NULL)
107
 
          str= ER(error);
108
 
        session->main_da.set_error_status(error, str);
109
 
      }
110
 
    }
111
 
 
112
 
    if (!session->no_warnings_for_error && !session->is_fatal_error)
113
 
    {
114
 
      /*
115
 
        Suppress infinite recursion if there a memory allocation error
116
 
        inside push_warning.
117
 
      */
118
 
      session->no_warnings_for_error= true;
119
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
120
 
      session->no_warnings_for_error= false;
121
 
      }
122
 
    }
123
 
    if (!session || MyFlags & ME_NOREFRESH)
124
 
        errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",internal::my_progname,str);
125
 
}
126
 
 
127
 
static void init_signals(void)
128
 
{
129
 
  sigset_t set;
130
 
  struct sigaction sa;
131
 
 
132
 
  if (!(test_flags.test(TEST_NO_STACKTRACE) || 
133
 
        test_flags.test(TEST_CORE_ON_SIGNAL)))
134
 
  {
135
 
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
136
 
    sigemptyset(&sa.sa_mask);
137
 
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
138
 
 
139
 
    sa.sa_handler= drizzled_handle_segfault;
140
 
    sigaction(SIGSEGV, &sa, NULL);
141
 
    sigaction(SIGABRT, &sa, NULL);
142
 
#ifdef SIGBUS
143
 
    sigaction(SIGBUS, &sa, NULL);
144
 
#endif
145
 
    sigaction(SIGILL, &sa, NULL);
146
 
    sigaction(SIGFPE, &sa, NULL);
147
 
  }
148
 
 
149
 
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
150
 
  {
151
 
    /* Change limits so that we will get a core file */
152
 
    struct rlimit rl;
153
 
    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
154
 
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
155
 
        errmsg_printf(ERRMSG_LVL_WARN,
156
 
                      _("setrlimit could not change the size of core files "
157
 
                        "to 'infinity';  We may not be able to generate a "
158
 
                        "core file on signals"));
159
 
  }
160
 
  (void) sigemptyset(&set);
161
 
  ignore_signal(SIGPIPE);
162
 
  sigaddset(&set,SIGPIPE);
163
 
#ifndef IGNORE_SIGHUP_SIGQUIT
164
 
  sigaddset(&set,SIGQUIT);
165
 
  sigaddset(&set,SIGHUP);
166
 
#endif
167
 
  sigaddset(&set,SIGTERM);
168
 
 
169
 
  /* Fix signals if blocked by parents (can happen on Mac OS X) */
170
 
  sigemptyset(&sa.sa_mask);
171
 
  sa.sa_flags = 0;
172
 
  sa.sa_handler = drizzled_print_signal_warning;
173
 
  sigaction(SIGTERM, &sa, NULL);
174
 
  sa.sa_flags = 0;
175
 
  sa.sa_handler = drizzled_print_signal_warning;
176
 
  sigaction(SIGHUP, &sa, NULL);
177
 
#ifdef SIGTSTP
178
 
  sigaddset(&set,SIGTSTP);
179
 
#endif
180
 
  if (test_flags.test(TEST_SIGINT))
181
 
  {
182
 
    sa.sa_flags= 0;
183
 
    sa.sa_handler= drizzled_end_thread_signal;
184
 
    sigaction(thr_kill_signal, &sa, NULL);
185
 
 
186
 
    // May be SIGINT
187
 
    sigdelset(&set, thr_kill_signal);
188
 
  }
189
 
  else
190
 
  {
191
 
    sigaddset(&set,SIGINT);
192
 
  }
193
 
  sigprocmask(SIG_SETMASK,&set,NULL);
194
 
  pthread_sigmask(SIG_SETMASK,&set,NULL);
195
 
  return;
196
 
}
197
 
 
198
 
static void GoogleProtoErrorThrower(google::protobuf::LogLevel level, const char* filename,
199
 
                       int line, const string& message) throw(const char *)
200
 
{
201
 
  (void)filename;
202
 
  (void)line;
203
 
  (void)message;
204
 
  switch(level)
205
 
  {
206
 
  case google::protobuf::LOGLEVEL_INFO:
207
 
    break;
208
 
  case google::protobuf::LOGLEVEL_WARNING:
209
 
  case google::protobuf::LOGLEVEL_ERROR:
210
 
  case google::protobuf::LOGLEVEL_FATAL:
211
 
  default:
212
 
    throw("error in google protocol buffer parsing");
213
 
  }
214
 
}
215
 
 
216
 
int main(int argc, char **argv)
217
 
{
218
 
#if defined(ENABLE_NLS)
219
 
# if defined(HAVE_LOCALE_H)
220
 
  setlocale(LC_ALL, "");
221
 
# endif
222
 
  bindtextdomain("drizzle", LOCALEDIR);
223
 
  textdomain("drizzle");
224
 
#endif
225
 
 
226
 
  module::Registry &modules= module::Registry::singleton();
227
 
  plugin::Client *client;
228
 
  Session *session;
229
 
 
230
 
  MY_INIT(argv[0]);             // init my_sys library & pthreads
231
 
  /* nothing should come before this line ^^^ */
232
 
 
233
 
  /* Set signal used to kill Drizzle */
234
 
  thr_kill_signal= SIGINT;
235
 
 
236
 
  google::protobuf::SetLogHandler(&GoogleProtoErrorThrower);
237
 
 
238
 
  /* Function generates error messages before abort */
239
 
  /* init_common_variables must get basic settings such as data_home_dir
240
 
     and plugin_load_list. */
241
 
  if (init_common_variables(argc, argv))
242
 
    unireg_abort(1);                            // Will do exit
243
 
 
244
 
  init_signals();
245
 
 
246
 
 
247
 
  select_thread=pthread_self();
248
 
  select_thread_in_use=1;
249
 
 
250
 
  if (not opt_help)
251
 
  {
252
 
    if (chdir(getDataHome().c_str()))
253
 
    {
254
 
      errmsg_printf(ERRMSG_LVL_ERROR,
255
 
                    _("Data directory %s does not exist\n"),
256
 
                    getDataHome().c_str());
257
 
      unireg_abort(1);
258
 
    }
259
 
    if (mkdir("local", 0700))
260
 
    {
261
 
      /* We don't actually care */
262
 
    }
263
 
    if (chdir("local"))
264
 
    {
265
 
      errmsg_printf(ERRMSG_LVL_ERROR,
266
 
                    _("Local catalog %s/local does not exist\n"),
267
 
                    getDataHome().c_str());
268
 
      unireg_abort(1);
269
 
    }
270
 
    /* TODO: This is a hack until we can properly support std::string in sys_var*/
271
 
    char **data_home_ptr= getDatadirPtr();
272
 
    *data_home_ptr= new char[getDataHome().size()+1] ();
273
 
    fs::path full_data_home_path(fs::system_complete(fs::path(getDataHome())));
274
 
    std::string full_data_home(full_data_home_path.file_string());
275
 
    memcpy(*data_home_ptr, full_data_home.c_str(), full_data_home.size());
276
 
    getDataHomeCatalog()= "./";
277
 
    getDataHome()= "../";
278
 
  }
279
 
 
280
 
 
281
 
 
282
 
  if (server_id == 0)
283
 
  {
284
 
    server_id= 1;
285
 
  }
286
 
 
287
 
  if (init_server_components(modules))
288
 
    unireg_abort(1);
289
 
 
290
 
  /**
291
 
   * This check must be done after init_server_components for now
292
 
   * because we don't yet have plugin dependency tracking...
293
 
   *
294
 
   * ReplicationServices::evaluateRegisteredPlugins() will print error messages to stderr
295
 
   * via errmsg_printf().
296
 
   *
297
 
   * @todo
298
 
   *
299
 
   * not checking return since unireg_abort() hangs
300
 
   */
301
 
  ReplicationServices &replication_services= ReplicationServices::singleton();
302
 
    (void) replication_services.evaluateRegisteredPlugins();
303
 
 
304
 
  if (plugin::Listen::setup())
305
 
    unireg_abort(1);
306
 
 
307
 
  /*
308
 
    init signals & alarm
309
 
    After this we can't quit by a simple unireg_abort
310
 
  */
311
 
  error_handler_hook= my_message_sql;
312
 
 
313
 
  assert(plugin::num_trx_monitored_objects > 0);
314
 
  if (drizzle_rm_tmp_tables() ||
315
 
      my_tz_init((Session *)0, default_tz_name))
316
 
  {
317
 
    abort_loop= true;
318
 
    select_thread_in_use=0;
319
 
    (void) pthread_kill(signal_thread, SIGTERM);
320
 
 
321
 
    (void) unlink(pidfile_name);        // Not needed anymore
322
 
 
323
 
    exit(1);
324
 
  }
325
 
 
326
 
  errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
327
 
                PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
328
 
 
329
 
 
330
 
  /* Listen for new connections and start new session for each connection
331
 
     accepted. The listen.getClient() method will return NULL when the server
332
 
     should be shutdown. */
333
 
  while ((client= plugin::Listen::getClient()) != NULL)
334
 
  {
335
 
    if (!(session= new Session(client)))
336
 
    {
337
 
      delete client;
338
 
      continue;
339
 
    }
340
 
 
341
 
    /* If we error on creation we drop the connection and delete the session. */
342
 
    if (session->schedule())
343
 
      Session::unlink(session);
344
 
  }
345
 
 
346
 
  LOCK_thread_count.lock();
347
 
  select_thread_in_use=0;                       // For close_connections
348
 
  LOCK_thread_count.unlock();
349
 
  COND_thread_count.notify_all();
350
 
 
351
 
  /* Wait until cleanup is done */
352
 
  LOCK_thread_count.lock();
353
 
  while (!ready_to_exit)
354
 
    pthread_cond_wait(COND_server_end.native_handle(), LOCK_thread_count.native_handle());
355
 
  LOCK_thread_count.unlock();
356
 
 
357
 
  clean_up(1);
358
 
  module::Registry::shutdown();
359
 
  internal::my_end();
360
 
  return 0;
361
 
}
362