2004-10-23 11:32:52 +04:00
|
|
|
/* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
2003-08-16 21:44:24 +04:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
2005-03-22 02:04:14 +03:00
|
|
|
#include <my_global.h>
|
2003-08-19 19:55:20 +04:00
|
|
|
#include "manager.h"
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
#include "priv.h"
|
2004-10-23 11:32:52 +04:00
|
|
|
#include "thread_registry.h"
|
2003-08-19 19:55:20 +04:00
|
|
|
#include "listener.h"
|
2004-10-23 11:32:52 +04:00
|
|
|
#include "instance_map.h"
|
|
|
|
#include "options.h"
|
|
|
|
#include "user_map.h"
|
2003-08-16 21:44:24 +04:00
|
|
|
#include "log.h"
|
2004-10-23 11:32:52 +04:00
|
|
|
#include "guardian.h"
|
2003-08-16 21:44:24 +04:00
|
|
|
|
2005-01-25 13:54:56 +03:00
|
|
|
#include <my_sys.h>
|
|
|
|
#include <m_string.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <thr_alarm.h>
|
2005-07-20 10:55:40 -05:00
|
|
|
#ifndef __WIN__
|
2005-01-25 13:54:56 +03:00
|
|
|
#include <sys/wait.h>
|
2005-07-20 10:55:40 -05:00
|
|
|
#endif
|
2005-01-25 13:54:56 +03:00
|
|
|
|
|
|
|
|
2004-10-25 14:23:31 +04:00
|
|
|
static int create_pid_file(const char *pid_file_name)
|
|
|
|
{
|
|
|
|
if (FILE *pid_file= my_fopen(pid_file_name,
|
|
|
|
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
|
|
|
|
{
|
|
|
|
fprintf(pid_file, "%d\n", (int) getpid());
|
|
|
|
my_fclose(pid_file, MYF(0));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
log_error("can't create pid file %s: errno=%d, %s",
|
|
|
|
pid_file_name, errno, strerror(errno));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-07-20 10:55:40 -05:00
|
|
|
#ifndef __WIN__
|
|
|
|
void set_signals(sigset_t *mask)
|
|
|
|
{
|
|
|
|
/* block signals */
|
|
|
|
sigemptyset(mask);
|
|
|
|
sigaddset(mask, SIGINT);
|
|
|
|
sigaddset(mask, SIGTERM);
|
|
|
|
sigaddset(mask, SIGPIPE);
|
|
|
|
sigaddset(mask, SIGHUP);
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
/*
|
|
|
|
We want this signal to be blocked in all theads but the signal
|
|
|
|
one. It is needed for the thr_alarm subsystem to work.
|
|
|
|
*/
|
|
|
|
sigaddset(mask,THR_SERVER_ALARM);
|
|
|
|
|
|
|
|
/* all new threads will inherite this signal mask */
|
|
|
|
pthread_sigmask(SIG_BLOCK, mask, NULL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
In our case the signal thread also implements functions of alarm thread.
|
|
|
|
Here we init alarm thread functionality. We suppose that we won't have
|
|
|
|
more then 10 alarms at the same time.
|
|
|
|
*/
|
|
|
|
init_thr_alarm(10);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
|
|
bool have_signal;
|
|
|
|
|
|
|
|
void onsignal(int signo)
|
|
|
|
{
|
2005-08-03 16:20:27 -05:00
|
|
|
have_signal= true;
|
2005-07-20 10:55:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_signals(sigset_t *set)
|
|
|
|
{
|
|
|
|
signal(SIGINT, onsignal);
|
|
|
|
signal(SIGTERM, onsignal);
|
2005-08-03 16:20:27 -05:00
|
|
|
have_signal= false;
|
2005-07-20 10:55:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int my_sigwait(const sigset_t *set, int *sig)
|
|
|
|
{
|
|
|
|
// MSG msg;
|
|
|
|
while (!have_signal)
|
|
|
|
{
|
|
|
|
Sleep(100);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2003-08-16 21:44:24 +04:00
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
/*
|
|
|
|
manager - entry point to the main instance manager process: start
|
|
|
|
listener thread, write pid file and enter into signal handling.
|
|
|
|
See also comments in mysqlmanager.cc to picture general Instance Manager
|
|
|
|
architecture.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void manager(const Options &options)
|
2003-08-16 21:44:24 +04:00
|
|
|
{
|
2004-10-23 11:32:52 +04:00
|
|
|
Thread_registry thread_registry;
|
|
|
|
/*
|
|
|
|
All objects created in the manager() function live as long as
|
|
|
|
thread_registry lives, and thread_registry is alive until there are
|
|
|
|
working threads.
|
|
|
|
*/
|
|
|
|
|
|
|
|
User_map user_map;
|
2005-02-18 14:58:30 +03:00
|
|
|
Instance_map instance_map(options.default_mysqld_path, options.first_option);
|
2004-10-23 11:32:52 +04:00
|
|
|
Guardian_thread guardian_thread(thread_registry,
|
|
|
|
&instance_map,
|
|
|
|
options.monitoring_interval);
|
|
|
|
|
2004-10-25 14:23:31 +04:00
|
|
|
Listener_thread_args listener_args(thread_registry, options, user_map,
|
|
|
|
instance_map);
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
manager_pid= getpid();
|
2004-10-23 11:32:52 +04:00
|
|
|
instance_map.guardian= &guardian_thread;
|
|
|
|
|
2005-02-15 04:38:33 +03:00
|
|
|
if (instance_map.init() || user_map.init())
|
|
|
|
return;
|
|
|
|
|
2005-02-27 18:41:34 +03:00
|
|
|
|
2005-02-15 04:38:33 +03:00
|
|
|
if (instance_map.load())
|
|
|
|
{
|
|
|
|
log_error("Cannot init instances repository. This might be caused by "
|
|
|
|
"the wrong config file options. For instance, missing mysqld "
|
|
|
|
"binary. Aborting.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (user_map.load(options.password_file_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
return;
|
2003-08-16 21:44:24 +04:00
|
|
|
|
2003-08-19 19:55:20 +04:00
|
|
|
/* write pid file */
|
2004-10-25 14:23:31 +04:00
|
|
|
if (create_pid_file(options.pid_file_name))
|
2004-10-23 11:32:52 +04:00
|
|
|
return;
|
2003-08-16 21:44:24 +04:00
|
|
|
|
2003-08-19 19:55:20 +04:00
|
|
|
sigset_t mask;
|
2005-07-20 10:55:40 -05:00
|
|
|
set_signals(&mask);
|
2004-10-23 11:32:52 +04:00
|
|
|
|
|
|
|
/* create the listener */
|
2003-08-16 21:44:24 +04:00
|
|
|
{
|
2003-08-19 19:55:20 +04:00
|
|
|
pthread_t listener_thd_id;
|
|
|
|
pthread_attr_t listener_thd_attr;
|
2004-10-23 11:32:52 +04:00
|
|
|
int rc;
|
2003-08-16 21:44:24 +04:00
|
|
|
|
2003-08-19 20:00:37 +04:00
|
|
|
pthread_attr_init(&listener_thd_attr);
|
|
|
|
pthread_attr_setdetachstate(&listener_thd_attr, PTHREAD_CREATE_DETACHED);
|
2004-10-23 11:32:52 +04:00
|
|
|
rc= pthread_create(&listener_thd_id, &listener_thd_attr, listener,
|
|
|
|
&listener_args);
|
|
|
|
pthread_attr_destroy(&listener_thd_attr);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error("manager(): pthread_create(listener) failed");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create guardian thread */
|
|
|
|
{
|
|
|
|
pthread_t guardian_thd_id;
|
|
|
|
pthread_attr_t guardian_thd_attr;
|
|
|
|
int rc;
|
|
|
|
|
2005-02-03 20:48:58 +03:00
|
|
|
/*
|
2005-02-11 14:21:59 +03:00
|
|
|
NOTE: Guardian should be shutdown first. Only then all other threads
|
2005-02-03 20:48:58 +03:00
|
|
|
need to be stopped. This should be done, as guardian is responsible for
|
|
|
|
shutting down the instances, and this is a long operation.
|
|
|
|
*/
|
|
|
|
|
2004-10-23 11:32:52 +04:00
|
|
|
pthread_attr_init(&guardian_thd_attr);
|
|
|
|
pthread_attr_setdetachstate(&guardian_thd_attr, PTHREAD_CREATE_DETACHED);
|
|
|
|
rc= pthread_create(&guardian_thd_id, &guardian_thd_attr, guardian,
|
|
|
|
&guardian_thread);
|
|
|
|
pthread_attr_destroy(&guardian_thd_attr);
|
|
|
|
if (rc)
|
|
|
|
{
|
|
|
|
log_error("manager(): pthread_create(guardian) failed");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2003-08-16 21:44:24 +04:00
|
|
|
}
|
2004-10-23 11:32:52 +04:00
|
|
|
|
2003-08-19 19:55:20 +04:00
|
|
|
/*
|
|
|
|
To work nicely with LinuxThreads, the signal thread is the first thread
|
|
|
|
in the process.
|
|
|
|
*/
|
|
|
|
int signo;
|
2004-10-23 11:32:52 +04:00
|
|
|
bool shutdown_complete;
|
|
|
|
|
|
|
|
shutdown_complete= FALSE;
|
2005-07-20 10:55:40 -05:00
|
|
|
|
2005-02-11 14:21:59 +03:00
|
|
|
/* init list of guarded instances */
|
2005-02-27 18:41:34 +03:00
|
|
|
guardian_thread.lock();
|
|
|
|
|
2005-02-11 14:21:59 +03:00
|
|
|
guardian_thread.init();
|
2005-02-27 18:41:34 +03:00
|
|
|
|
|
|
|
guardian_thread.unlock();
|
|
|
|
|
2005-02-03 20:48:58 +03:00
|
|
|
/*
|
|
|
|
After the list of guarded instances have been initialized,
|
|
|
|
Guardian should start them.
|
|
|
|
*/
|
|
|
|
pthread_cond_signal(&guardian_thread.COND_guardian);
|
2004-10-23 11:32:52 +04:00
|
|
|
|
|
|
|
while (!shutdown_complete)
|
|
|
|
{
|
2005-02-13 15:13:33 +03:00
|
|
|
int status= 0;
|
|
|
|
|
2005-02-15 04:38:33 +03:00
|
|
|
if ((status= my_sigwait(&mask, &signo)) != 0)
|
2005-02-13 15:13:33 +03:00
|
|
|
{
|
|
|
|
log_error("sigwait() failed");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2005-07-20 10:55:40 -05:00
|
|
|
#ifndef __WIN__
|
|
|
|
if (THR_SERVER_ALARM == signo)
|
|
|
|
process_alarm(signo);
|
|
|
|
else
|
|
|
|
#endif
|
2005-02-11 14:21:59 +03:00
|
|
|
{
|
|
|
|
if (!guardian_thread.is_stopped())
|
more fixes for IM to substitude mysqld_safe in startup scripts
BitKeeper/deleted/.del-thread_repository.cc~bba09f64f8cb4037:
Delete: server-tools/instance-manager/thread_repository.cc
BitKeeper/deleted/.del-thread_repository.h~e6a3b9cab7a6612a:
Delete: server-tools/instance-manager/thread_repository.h
server-tools/instance-manager/commands.cc:
All instances are guarded by default now, so we need to perform check on whether the instance is nonguarded,
rather then guarded when adding it to the list of guarded instnces.
server-tools/instance-manager/guardian.cc:
Guardian rewritten to start instances by default, and shut them down, when exiting. Behaviour of the guardian
in case of the instance crash has changed. Now it tries to restart an instance constantly in the first 2
seconds after the crash was noticed, and then it tries restart an instance once in the MONITORING_INTERVAL.
If it failed to restart instance for "restart_retry" (compiled-in value) times, guardian stops trying to
restart it.
server-tools/instance-manager/guardian.h:
Several new functions and variables declared.
server-tools/instance-manager/instance.cc:
now start doesn't call stop(), but rather tries to remove the pidfile itself
server-tools/instance-manager/instance.h:
cleanup
server-tools/instance-manager/instance_map.cc:
no more "admin" options
server-tools/instance-manager/instance_map.h:
User and password purged from instance_map options, as IM shouldn't know them
server-tools/instance-manager/instance_options.cc:
new option added -- shutdown_delay, guarded option now called nonguaded and has the opposite meaning
server-tools/instance-manager/instance_options.h:
appropriate changes, reflecting options addition/removal
server-tools/instance-manager/manager.cc:
shutdown process is complicated a bit -- at first signal thread should stop guardian, and only then the IM
itself
server-tools/instance-manager/messages.cc:
update error message
server-tools/instance-manager/options.cc:
admin user/password purged from mysqlmanager options
2005-01-31 23:54:08 +03:00
|
|
|
{
|
2005-02-11 14:21:59 +03:00
|
|
|
bool stop_instances= true;
|
|
|
|
guardian_thread.request_shutdown(stop_instances);
|
2005-02-03 20:48:58 +03:00
|
|
|
pthread_cond_signal(&guardian_thread.COND_guardian);
|
more fixes for IM to substitude mysqld_safe in startup scripts
BitKeeper/deleted/.del-thread_repository.cc~bba09f64f8cb4037:
Delete: server-tools/instance-manager/thread_repository.cc
BitKeeper/deleted/.del-thread_repository.h~e6a3b9cab7a6612a:
Delete: server-tools/instance-manager/thread_repository.h
server-tools/instance-manager/commands.cc:
All instances are guarded by default now, so we need to perform check on whether the instance is nonguarded,
rather then guarded when adding it to the list of guarded instnces.
server-tools/instance-manager/guardian.cc:
Guardian rewritten to start instances by default, and shut them down, when exiting. Behaviour of the guardian
in case of the instance crash has changed. Now it tries to restart an instance constantly in the first 2
seconds after the crash was noticed, and then it tries restart an instance once in the MONITORING_INTERVAL.
If it failed to restart instance for "restart_retry" (compiled-in value) times, guardian stops trying to
restart it.
server-tools/instance-manager/guardian.h:
Several new functions and variables declared.
server-tools/instance-manager/instance.cc:
now start doesn't call stop(), but rather tries to remove the pidfile itself
server-tools/instance-manager/instance.h:
cleanup
server-tools/instance-manager/instance_map.cc:
no more "admin" options
server-tools/instance-manager/instance_map.h:
User and password purged from instance_map options, as IM shouldn't know them
server-tools/instance-manager/instance_options.cc:
new option added -- shutdown_delay, guarded option now called nonguaded and has the opposite meaning
server-tools/instance-manager/instance_options.h:
appropriate changes, reflecting options addition/removal
server-tools/instance-manager/manager.cc:
shutdown process is complicated a bit -- at first signal thread should stop guardian, and only then the IM
itself
server-tools/instance-manager/messages.cc:
update error message
server-tools/instance-manager/options.cc:
admin user/password purged from mysqlmanager options
2005-01-31 23:54:08 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
thread_registry.deliver_shutdown();
|
|
|
|
shutdown_complete= TRUE;
|
|
|
|
}
|
2005-02-11 14:21:59 +03:00
|
|
|
}
|
2004-10-23 11:32:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
err:
|
|
|
|
/* delete the pid file */
|
|
|
|
my_delete(options.pid_file_name, MYF(0));
|
|
|
|
|
2005-07-20 10:55:40 -05:00
|
|
|
#ifndef __WIN__
|
2004-10-23 11:32:52 +04:00
|
|
|
/* free alarm structures */
|
|
|
|
end_thr_alarm(1);
|
2003-08-19 19:55:20 +04:00
|
|
|
/* don't pthread_exit to kill all threads who did not shut down in time */
|
2005-07-20 10:55:40 -05:00
|
|
|
#endif
|
2003-08-16 21:44:24 +04:00
|
|
|
}
|
2004-10-23 11:32:52 +04:00
|
|
|
|