1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
24
#include <sys/resource.h>
27
#include <sys/types.h>
30
#if TIME_WITH_SYS_TIME
31
# include <sys/time.h>
35
# include <sys/time.h>
41
#if defined(HAVE_LOCALE_H)
45
#include <boost/filesystem.hpp>
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
#include "drizzled/transaction_services.h"
64
#include "drizzled/util/backtrace.h"
66
using namespace drizzled;
68
namespace fs=boost::filesystem;
70
static pthread_t select_thread;
71
static uint32_t thr_kill_signal;
75
All global error messages are sent here where the first one is stored
78
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
82
Put here following assertion when situation with EE_* error codes
85
if ((session= current_session))
87
if (MyFlags & ME_FATALERROR)
88
session->is_fatal_error= 1;
91
TODO: There are two exceptions mechanism (Session and sp_rcontext),
92
this could be improved by having a common stack of handlers.
94
if (session->handle_error(error, str,
95
DRIZZLE_ERROR::WARN_LEVEL_ERROR))
99
session->lex->current_select == 0 if lex structure is not inited
100
(not query command (COM_QUERY))
102
if (! (session->lex->current_select &&
103
session->lex->current_select->no_error && !session->is_fatal_error))
105
if (! session->main_da.is_error()) // Return only first message
108
error= ER_UNKNOWN_ERROR;
111
session->main_da.set_error_status(error, str);
115
if (!session->no_warnings_for_error && !session->is_fatal_error)
118
Suppress infinite recursion if there a memory allocation error
121
session->no_warnings_for_error= true;
122
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
123
session->no_warnings_for_error= false;
126
if (!session || MyFlags & ME_NOREFRESH)
127
errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",internal::my_progname,str);
130
static void init_signals(void)
135
if (!(test_flags.test(TEST_NO_STACKTRACE) ||
136
test_flags.test(TEST_CORE_ON_SIGNAL)))
138
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
139
sigemptyset(&sa.sa_mask);
140
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
142
sa.sa_handler= drizzled_handle_segfault;
143
sigaction(SIGSEGV, &sa, NULL);
144
sigaction(SIGABRT, &sa, NULL);
146
sigaction(SIGBUS, &sa, NULL);
148
sigaction(SIGILL, &sa, NULL);
149
sigaction(SIGFPE, &sa, NULL);
152
if (test_flags.test(TEST_CORE_ON_SIGNAL))
154
/* Change limits so that we will get a core file */
156
rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
157
if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
158
errmsg_printf(ERRMSG_LVL_WARN,
159
_("setrlimit could not change the size of core files "
160
"to 'infinity'; We may not be able to generate a "
161
"core file on signals"));
163
(void) sigemptyset(&set);
164
ignore_signal(SIGPIPE);
165
sigaddset(&set,SIGPIPE);
166
#ifndef IGNORE_SIGHUP_SIGQUIT
167
sigaddset(&set,SIGQUIT);
168
sigaddset(&set,SIGHUP);
170
sigaddset(&set,SIGTERM);
172
/* Fix signals if blocked by parents (can happen on Mac OS X) */
173
sigemptyset(&sa.sa_mask);
175
sa.sa_handler = drizzled_print_signal_warning;
176
sigaction(SIGTERM, &sa, NULL);
178
sa.sa_handler = drizzled_print_signal_warning;
179
sigaction(SIGHUP, &sa, NULL);
181
sigaddset(&set,SIGTSTP);
183
if (test_flags.test(TEST_SIGINT))
186
sa.sa_handler= drizzled_end_thread_signal;
187
sigaction(thr_kill_signal, &sa, NULL);
190
sigdelset(&set, thr_kill_signal);
194
sigaddset(&set,SIGINT);
196
sigprocmask(SIG_SETMASK,&set,NULL);
197
pthread_sigmask(SIG_SETMASK,&set,NULL);
201
static void GoogleProtoErrorThrower(google::protobuf::LogLevel level, const char* filename,
202
int line, const string& message) throw(const char *)
208
drizzled::util::custom_backtrace();
212
case google::protobuf::LOGLEVEL_INFO:
214
case google::protobuf::LOGLEVEL_WARNING:
215
case google::protobuf::LOGLEVEL_ERROR:
216
case google::protobuf::LOGLEVEL_FATAL:
218
std::cerr << "GoogleProtoErrorThrower(" << filename << ", " << line << ", " << message << ")";
219
throw("error in google protocol buffer parsing");
223
int main(int argc, char **argv)
225
#if defined(ENABLE_NLS)
226
# if defined(HAVE_LOCALE_H)
227
setlocale(LC_ALL, "");
229
bindtextdomain("drizzle", LOCALEDIR);
230
textdomain("drizzle");
233
module::Registry &modules= module::Registry::singleton();
234
plugin::Client *client;
237
MY_INIT(argv[0]); // init my_sys library & pthreads
238
/* nothing should come before this line ^^^ */
240
/* Set signal used to kill Drizzle */
241
thr_kill_signal= SIGINT;
243
google::protobuf::SetLogHandler(&GoogleProtoErrorThrower);
245
/* Function generates error messages before abort */
246
error_handler_hook= my_message_sql;
247
/* init_common_variables must get basic settings such as data_home_dir
248
and plugin_load_list. */
249
if (init_common_variables(argc, argv, modules))
250
unireg_abort(1); // Will do exit
254
After this we can't quit by a simple unireg_abort
259
select_thread=pthread_self();
260
select_thread_in_use=1;
264
if (chdir(getDataHome().file_string().c_str()))
266
errmsg_printf(ERRMSG_LVL_ERROR,
267
_("Data directory %s does not exist\n"),
268
getDataHome().file_string().c_str());
271
if (mkdir("local", 0700))
273
/* We don't actually care */
277
errmsg_printf(ERRMSG_LVL_ERROR,
278
_("Local catalog %s/local does not exist\n"),
279
getDataHome().file_string().c_str());
283
full_data_home= fs::system_complete(getDataHome());
284
getDataHomeCatalog()= "./";
285
getDataHome()= "../";
295
if (init_server_components(modules))
299
* This check must be done after init_server_components for now
300
* because we don't yet have plugin dependency tracking...
302
* ReplicationServices::evaluateRegisteredPlugins() will print error messages to stderr
303
* via errmsg_printf().
307
* not checking return since unireg_abort() hangs
309
ReplicationServices &replication_services= ReplicationServices::singleton();
310
(void) replication_services.evaluateRegisteredPlugins();
312
if (plugin::Listen::setup())
316
assert(plugin::num_trx_monitored_objects > 0);
317
if (drizzle_rm_tmp_tables() ||
318
my_tz_init((Session *)0, default_tz_name))
321
select_thread_in_use=0;
322
(void) pthread_kill(signal_thread, SIGTERM);
324
(void) unlink(pid_file.file_string().c_str()); // Not needed anymore
329
errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
330
PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
333
TransactionServices &transaction_services= TransactionServices::singleton();
335
/* Send server startup event */
336
if ((session= new Session(plugin::Listen::getNullClient())))
338
currentSession().release();
339
currentSession().reset(session);
340
transaction_services.sendStartupEvent(session);
341
session->lockForDelete();
346
/* Listen for new connections and start new session for each connection
347
accepted. The listen.getClient() method will return NULL when the server
348
should be shutdown. */
349
while ((client= plugin::Listen::getClient()) != NULL)
351
if (!(session= new Session(client)))
357
/* If we error on creation we drop the connection and delete the session. */
358
if (session->schedule())
359
Session::unlink(session);
362
/* Send server shutdown event */
363
if ((session= new Session(plugin::Listen::getNullClient())))
365
currentSession().release();
366
currentSession().reset(session);
367
transaction_services.sendShutdownEvent(session);
368
session->lockForDelete();
372
LOCK_thread_count.lock();
373
select_thread_in_use=0; // For close_connections
374
LOCK_thread_count.unlock();
375
COND_thread_count.notify_all();
377
/* Wait until cleanup is done */
379
boost::mutex::scoped_lock scopedLock(LOCK_thread_count);
380
while (!ready_to_exit)
381
COND_server_end.wait(scopedLock);
385
module::Registry::shutdown();