mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
First implementation of instance-manager carcass:
logging, options, angel process. configure.in: added support for instance-manager directory BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
This commit is contained in:
29
server-tools/instance-manager/Makefile.am
Normal file
29
server-tools/instance-manager/Makefile.am
Normal file
@ -0,0 +1,29 @@
|
||||
INCLUDES= -I$(top_srcdir)/include
|
||||
|
||||
# As all autoconf variables depend from ${prefix} and being resolved only when
|
||||
# make is run, we can't put these defines to a header file (e.g. to
|
||||
# default_options.h, generated from default_options.h.in)
|
||||
# See automake/autoconf docs for details
|
||||
|
||||
noinst_LIBRARIES= liboptions.a
|
||||
liboptions_a_CPPFLAGS= $(CPPFLAGS) \
|
||||
-DDEFAULT_PID_FILE_NAME="$(localstatedir)/mysqlmanager.pid" \
|
||||
-DDEFAULT_LOG_FILE_NAME="$(localstatedir)/mysqlmanager.log" \
|
||||
-DDEFAULT_SOCKET_FILE_NAME="$(localstatedir)/mysqlmanager.sock"
|
||||
|
||||
liboptions_a_SOURCES= otpions.h options.cc
|
||||
|
||||
bin_PROGRAMS = mysqlmanager
|
||||
|
||||
#AM_CXXFLAGS= -Wformat=2 -W -Wall -Wformat-security
|
||||
mysqlmanager_SOURCES= mysqlmanager.cc manager.h manager.cc log.h log.cc
|
||||
mysqlmanager_LDADD= liboptions.a \
|
||||
$(top_builddir)/mysys/libmysys.a \
|
||||
$(top_builddir)/strings/libmystrings.a \
|
||||
$(top_builddir)/dbug/libdbug.a
|
||||
|
||||
tags:
|
||||
ctags -R *.h *.cc
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
11
server-tools/instance-manager/README
Normal file
11
server-tools/instance-manager/README
Normal file
@ -0,0 +1,11 @@
|
||||
Instance Manager - manage MySQL instances locally and remotely.
|
||||
|
||||
File description:
|
||||
mysqlmanager.cc - entry point to the manager, main,
|
||||
options.{h,cc} - handle startup options
|
||||
manager.{h,cc} - manager process
|
||||
mysql_connection.{h,cc} - handle one connection with mysql client.
|
||||
|
||||
See also instance manager architecture description in mysqlmanager.cc.
|
||||
|
||||
|
167
server-tools/instance-manager/log.cc
Normal file
167
server-tools/instance-manager/log.cc
Normal file
@ -0,0 +1,167 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
#include "log.h"
|
||||
#include <my_global.h>
|
||||
#include <stdarg.h>
|
||||
#include <m_string.h>
|
||||
#include <my_sys.h>
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- add flexible header support
|
||||
- rewrite all fprintf with fwrite
|
||||
- think about using 'write' instead of fwrite/fprintf on POSIX systems
|
||||
*/
|
||||
|
||||
/*
|
||||
Format log entry and write it to the given stream.
|
||||
SYNOPSYS
|
||||
log()
|
||||
*/
|
||||
|
||||
static inline void log(FILE *file, const char *format, va_list args)
|
||||
{
|
||||
/*
|
||||
log() should be thread-safe; it implies that we either call fprintf()
|
||||
once per log(), or use flockfile()/funlockfile(). But flockfile() is
|
||||
POSIX, not ANSI C, so we try to vsnprintf the whole message to the
|
||||
stack, and if stack buffer is not enough, to malloced string. When
|
||||
message is formatted, it is fprintf()'ed to the file.
|
||||
*/
|
||||
|
||||
/* Format time like MYSQL_LOG does. */
|
||||
time_t now= time(0);
|
||||
struct tm bd_time; // broken-down time
|
||||
localtime_r(&now, &bd_time);
|
||||
|
||||
char buff_date[32];
|
||||
sprintf(buff_date, "%02d%02d%02d %2d:%02d:%02d\t",
|
||||
bd_time.tm_year % 100,
|
||||
bd_time.tm_mon + 1,
|
||||
bd_time.tm_mday,
|
||||
bd_time.tm_hour,
|
||||
bd_time.tm_min,
|
||||
bd_time.tm_sec);
|
||||
/* Format the message */
|
||||
char buff_stack[256];
|
||||
|
||||
int n= vsnprintf(buff_stack, sizeof(buff_stack), format, args);
|
||||
/*
|
||||
return value of vsnprintf can vary, according to various standards;
|
||||
try to check all cases.
|
||||
*/
|
||||
char *buff_msg= buff_stack;
|
||||
if (n < 0 || n == sizeof(buff_stack))
|
||||
{
|
||||
int size= sizeof(buff_stack) * 2;
|
||||
buff_msg= (char *) my_malloc(size, 0);
|
||||
while (true)
|
||||
{
|
||||
if (buff_msg == 0)
|
||||
{
|
||||
strmake(buff_stack, "log(): message is too big, my_malloc() failed",
|
||||
sizeof(buff_stack));
|
||||
buff_msg= buff_stack;
|
||||
break;
|
||||
}
|
||||
n = vsnprintf(buff_msg, size, format, args);
|
||||
if (n >= 0 && n < size)
|
||||
break;
|
||||
size*= 2;
|
||||
/* realloc() does unnecessary memcpy */
|
||||
my_free(buff_msg, 0);
|
||||
buff_msg= (char *) my_malloc(size, 0);
|
||||
}
|
||||
}
|
||||
else if ((size_t) n > sizeof(buff_stack))
|
||||
{
|
||||
buff_msg= (char *) my_malloc(n + 1, 0);
|
||||
#ifdef DBUG
|
||||
DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
|
||||
#else
|
||||
vsnprintf(buff_msg, n + 1, format, args);
|
||||
#endif
|
||||
}
|
||||
fprintf(file, "%s%s\n", buff_date, buff_msg);
|
||||
if (buff_msg != buff_stack)
|
||||
my_free(buff_msg, 0);
|
||||
|
||||
/* don't fflush() the file: buffering strategy is set in log_init() */
|
||||
}
|
||||
|
||||
|
||||
void log_error(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(stderr, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
void log_info(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
log(stdout, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/* TODO: rewrite with buffering print */
|
||||
void print_info(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stdout, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void print_error(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/*
|
||||
init_logs()
|
||||
RETURN VALUE
|
||||
0 ok
|
||||
!0 error
|
||||
*/
|
||||
|
||||
void log_init()
|
||||
{
|
||||
/*
|
||||
stderr is unbuffered by default; there is no good of line buffering,
|
||||
as all logging is performed linewise - so remove buffering from stdout
|
||||
also
|
||||
*/
|
||||
setbuf(stdout, 0);
|
||||
}
|
||||
|
||||
void die(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
fprintf(stderr,"%s: ", my_progname);
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
84
server-tools/instance-manager/log.h
Normal file
84
server-tools/instance-manager/log.h
Normal file
@ -0,0 +1,84 @@
|
||||
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
|
||||
#define INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
/*
|
||||
Logging facilities.
|
||||
|
||||
Two logging streams are supported: error log and info log. Additionally
|
||||
libdbug may be used for debug information output.
|
||||
ANSI C buffered I/O is used to perform logging.
|
||||
Logging may be performed in two modes:
|
||||
- console application mode (default), stdout/stderr is used for logging
|
||||
init_logs() must be called to initialize logging environment
|
||||
- daemon mode, without controlling terminal, call
|
||||
init_logs_in_daemon_mode() to initialize
|
||||
|
||||
Rationale:
|
||||
- no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h
|
||||
- no constructors/desctructors to make logging available all the time
|
||||
Function names are subject to change.
|
||||
*/
|
||||
|
||||
|
||||
/* Precede error message with date and time and print it to the stdout */
|
||||
void log_info(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format(printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/* Precede error message with date and time and print it to the stderr */
|
||||
void log_error(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
Now this is simple catchouts for printf (no date/time is logged), to be
|
||||
able to replace underlying streams in future.
|
||||
*/
|
||||
|
||||
void print_info(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
void print_error(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/* initialize logs */
|
||||
void log_init();
|
||||
|
||||
|
||||
/* initialize logs for daemon application */
|
||||
|
||||
void die(const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 1, 2)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
|
70
server-tools/instance-manager/manager.cc
Normal file
70
server-tools/instance-manager/manager.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
#include <my_global.h>
|
||||
#include "log.h"
|
||||
|
||||
//#include "mysql_connection.h"
|
||||
|
||||
void manager(const char *socket_file_name)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
log_info("manager is alive");
|
||||
sleep(2);
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
Dummy manager implementation: listens on a UNIX socket and
|
||||
starts echo server in a dedicated thread for each accepted connection.
|
||||
Enough to test startup/shutdown/options/logging of the instance manager.
|
||||
*/
|
||||
|
||||
int fd= socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (!fd)
|
||||
die("socket(): failed");
|
||||
|
||||
struct sockaddr_un address;
|
||||
bzero(&address, sizeof(address));
|
||||
address.sun_family= AF_UNIX;
|
||||
strcpy(address.sun_path, socket_path);
|
||||
int opt= 1;
|
||||
|
||||
if (unlink(socket_path) ||
|
||||
bind(fd, (struct sockaddr *) &address, sizeof(address)) ||
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
|
||||
die("unlink | bind | setsockopt failed");
|
||||
|
||||
if (listen(fd, 5))
|
||||
die("listen() failed");
|
||||
|
||||
int client_fd;
|
||||
while ((client_fd= accept(fd, 0, 0)) != -1);
|
||||
{
|
||||
printf("accepted\n");
|
||||
const char *message= "\n10hel";
|
||||
send(client_fd, message, strlen(message), 0);
|
||||
|
||||
int sleep_seconds= argc > 1 && atoi(argv[1]) ? atoi(argv[1]) : 1;
|
||||
printf("sleeping %d seconds\n", sleep_seconds);
|
||||
sleep(sleep_seconds);
|
||||
close(client_fd);
|
||||
}
|
||||
printf("accept(): failed\n");
|
||||
close(fd);
|
||||
#endif
|
||||
}
|
17
server-tools/instance-manager/manager.h
Normal file
17
server-tools/instance-manager/manager.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
void manager(const char *socket_file_name);
|
249
server-tools/instance-manager/mysqlmanager.cc
Normal file
249
server-tools/instance-manager/mysqlmanager.cc
Normal file
@ -0,0 +1,249 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "manager.h"
|
||||
#include "options.h"
|
||||
#include "log.h"
|
||||
|
||||
/*
|
||||
Few notes about the Instance Manager architecture:
|
||||
Instance Manager consisits of two processes: the angel process, and the
|
||||
instance manager process. Responsibilities of the angel process is to
|
||||
monitor the instance manager process, and restart it in case of
|
||||
failure/shutdown. The angel process is started only if startup option
|
||||
'--run-as-service' is provided.
|
||||
The Instance Manager process consists of several
|
||||
subsystems (thread sets):
|
||||
- the signal handling thread: it's responsibilities are to handle
|
||||
user signals and propogate them to the other threads. All other threads
|
||||
are accounted in the signal handler thread Thread Repository.
|
||||
- the listener: listens all sockets. There is a listening
|
||||
socket for each (mysql, http, snmp, rendezvous (?)) subsystem.
|
||||
- mysql subsystem: Instance Manager acts like an ordinary MySQL Server,
|
||||
but with very restricted command set. Each MySQL client connection is
|
||||
handled in a separate thread. All MySQL client connections threads
|
||||
constitute mysql subsystem.
|
||||
- http subsystem: it is also possible to talk with Instance Manager via
|
||||
http. One thread per http connection is used. Threads are pooled.
|
||||
- 'snmp' connections (FIXME: I know nothing about it yet)
|
||||
- rendezvous threads
|
||||
*/
|
||||
|
||||
static void init_environment(char *progname);
|
||||
static void daemonize(const char *log_file_name);
|
||||
static void angel(const Options &options);
|
||||
|
||||
|
||||
/*
|
||||
main, entry point
|
||||
- init environment
|
||||
- handle options
|
||||
- daemonize and run angel process (if necessary)
|
||||
- run manager process
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
init_environment(argv[0]);
|
||||
Options options;
|
||||
options.load(argc, argv);
|
||||
if (options.run_as_service)
|
||||
{
|
||||
daemonize(options.log_file_name);
|
||||
angel(options);
|
||||
}
|
||||
else
|
||||
manager(options.log_file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************* Auxilary functions implementation **********************/
|
||||
|
||||
|
||||
/*
|
||||
Init environment, common for daemon and non-daemon
|
||||
*/
|
||||
|
||||
static void init_environment(char *progname)
|
||||
{
|
||||
MY_INIT(progname);
|
||||
log_init();
|
||||
umask(0117);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Become a UNIX service
|
||||
SYNOPSYS
|
||||
daemonize()
|
||||
*/
|
||||
|
||||
static void daemonize(const char *log_file_name)
|
||||
{
|
||||
pid_t pid= fork();
|
||||
switch (pid) {
|
||||
case -1: // parent, fork error
|
||||
die("daemonize(): fork failed, %s", strerror(errno));
|
||||
case 0: // child, fork ok
|
||||
int fd;
|
||||
/*
|
||||
Become a session leader: setsid should succeed because child is
|
||||
guaranteed not to be a process group leader (it belongs to the
|
||||
process group of the parent.)
|
||||
The goal is not to have a controlling terminal.
|
||||
*/
|
||||
if (setsid() == -1)
|
||||
die("daemonize(): setsid() failed, %s", strerror(errno));
|
||||
/*
|
||||
As we now don't have a controlling terminal we will not receive
|
||||
tty-related signals - no need to ignore them.
|
||||
*/
|
||||
|
||||
close(STDIN_FILENO);
|
||||
|
||||
fd= open(log_file_name, O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
if (fd < 0)
|
||||
die("daemonize(): failed to open log file %s, %s", log_file_name,
|
||||
strerror(errno));
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
if (fd != STDOUT_FILENO && fd != STDERR_FILENO)
|
||||
close(fd);
|
||||
|
||||
/* TODO: chroot() and/or chdir() here */
|
||||
break;
|
||||
default:
|
||||
/* successfully exit from parent */
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL };
|
||||
|
||||
static volatile sig_atomic_t child_status= CHILD_OK;
|
||||
|
||||
/*
|
||||
Signal handler for SIGCHLD: reap child, analyze child exit status, and set
|
||||
child_status appropriately.
|
||||
*/
|
||||
|
||||
void reap_child(int __attribute__((unused)) signo)
|
||||
{
|
||||
int child_exit_status;
|
||||
/* As we have only one child, no need to cycle waitpid */
|
||||
if (waitpid(0, &child_exit_status, WNOHANG) > 0)
|
||||
{
|
||||
if (WIFSIGNALED(child_exit_status))
|
||||
child_status= CHILD_NEED_RESPAWN;
|
||||
else
|
||||
/*
|
||||
As we reap_child is not called for SIGSTOP, we should be here only
|
||||
if the child exited normally.
|
||||
*/
|
||||
child_status= CHILD_EXIT_ANGEL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not static to reuse it in childs */
|
||||
|
||||
volatile sig_atomic_t is_terminated= 0;
|
||||
|
||||
/*
|
||||
Signal handler for terminate signals - SIGTERM, SIGHUP, SIGINT.
|
||||
Set termination status and return.
|
||||
(q) do we need to handle SIGQUIT?
|
||||
*/
|
||||
|
||||
void terminate(int signo)
|
||||
{
|
||||
is_terminated= signo;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Fork a child and monitor it.
|
||||
User can explicitly kill the angel process with SIGTERM/SIGHUP/SIGINT.
|
||||
Angel process will exit silently if mysqlmanager exits normally.
|
||||
*/
|
||||
|
||||
static void angel(const Options &options)
|
||||
{
|
||||
/* install signal handlers */
|
||||
sigset_t zeromask; // to sigsuspend in parent
|
||||
struct sigaction sa_chld, sa_term;
|
||||
struct sigaction sa_chld_out, sa_term_out, sa_int_out, sa_hup_out;
|
||||
if (sigemptyset(&zeromask) ||
|
||||
sigemptyset(&sa_chld.sa_mask) ||
|
||||
sigemptyset(&sa_term.sa_mask)) // how can it fail?
|
||||
die("angel(): sigemptyset() failed, %s", strerror(errno));
|
||||
sa_chld.sa_handler= reap_child;
|
||||
sa_chld.sa_flags= SA_NOCLDSTOP;
|
||||
sa_term.sa_handler= terminate;
|
||||
sa_term.sa_flags= 0;
|
||||
if (sigaction(SIGCHLD, &sa_chld, &sa_chld_out) == -1 ||
|
||||
sigaction(SIGTERM, &sa_term, &sa_term_out) == -1 ||
|
||||
sigaction(SIGINT, &sa_term, &sa_int_out) == -1 ||
|
||||
sigaction(SIGHUP, &sa_term, &sa_hup_out) == -1)
|
||||
die("angel(): sigaction() failed, %s", strerror(errno));
|
||||
|
||||
/* spawn a child */
|
||||
spawn:
|
||||
pid_t pid= fork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
die("angel(): fork failed, %s", strerror(errno));
|
||||
case 0: // child, success
|
||||
/*
|
||||
restore default actions for signals to let the manager work with
|
||||
signals as he wishes
|
||||
*/
|
||||
if (sigaction(SIGCHLD, &sa_chld_out, 0) == -1 ||
|
||||
sigaction(SIGTERM, &sa_term_out, 0) == -1 ||
|
||||
sigaction(SIGINT, &sa_int_out, 0) == -1 ||
|
||||
sigaction(SIGHUP, &sa_hup_out, 0) == -1)
|
||||
die("angel(): child failed to restore old signal actions, %s",
|
||||
strerror(errno));
|
||||
|
||||
manager(options.socket_file_name);
|
||||
default: // parent, success
|
||||
while (child_status == CHILD_OK && is_terminated == 0)
|
||||
{
|
||||
errno= 0;
|
||||
sigsuspend(&zeromask);
|
||||
if (errno != EINTR)
|
||||
die("angel(): sigsuspend failed, %s", strerror(errno));
|
||||
}
|
||||
if (is_terminated)
|
||||
log_info("angel got signal %d (%s), exiting",
|
||||
is_terminated, sys_siglist[is_terminated]);
|
||||
else if (child_status == CHILD_NEED_RESPAWN)
|
||||
{
|
||||
child_status= CHILD_OK;
|
||||
log_error("angel(): mysqlmanager exited abnormally: respawning...");
|
||||
sleep(1); /* don't respawn too fast */
|
||||
goto spawn;
|
||||
}
|
||||
/* mysqlmanager successfully exited, let's silently evaporate */
|
||||
}
|
||||
}
|
127
server-tools/instance-manager/options.cc
Normal file
127
server-tools/instance-manager/options.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
#include "options.h"
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include <my_getopt.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
|
||||
#define QUOTE2(x) #x
|
||||
#define QUOTE(x) QUOTE2(x)
|
||||
|
||||
char Options::run_as_service;
|
||||
const char *Options::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
|
||||
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
|
||||
const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
|
||||
|
||||
/*
|
||||
List of options, accepted by the instance manager.
|
||||
List must be closed with empty option.
|
||||
*/
|
||||
|
||||
enum options {
|
||||
OPT_LOG= 256,
|
||||
OPT_PID_FILE,
|
||||
OPT_SOCKET,
|
||||
OPT_RUN_AS_SERVICE
|
||||
};
|
||||
|
||||
static struct my_option my_long_options[] =
|
||||
{
|
||||
{ "help", '?', "Display this help and exit.",
|
||||
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ "log", OPT_LOG, "Path to log file. Used only with --run-as-service.",
|
||||
(gptr *) &Options::log_file_name, (gptr *) &Options::log_file_name,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ "pid-file", OPT_PID_FILE, "Pid file to use.",
|
||||
(gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ "socket", OPT_SOCKET, "Socket file to use for connection.",
|
||||
(gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
|
||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ "run-as-service", OPT_RUN_AS_SERVICE,
|
||||
"Daemonize and start angel process.", (gptr *) &Options::run_as_service,
|
||||
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
|
||||
|
||||
{ "version", 'V', "Output version information and exit.", 0, 0, 0,
|
||||
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void version()
|
||||
{
|
||||
static const char mysqlmanager_version[] = "0.1-alpha";
|
||||
printf("%s Ver %s for %s on %s\n", my_progname, mysqlmanager_version,
|
||||
SYSTEM_TYPE, MACHINE_TYPE);
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
version();
|
||||
my_print_help(my_long_options);
|
||||
}
|
||||
|
||||
C_MODE_START
|
||||
|
||||
static my_bool
|
||||
get_one_option(int optid,
|
||||
const struct my_option *opt __attribute__((unused)),
|
||||
char *argument __attribute__((unused)))
|
||||
{
|
||||
switch(optid) {
|
||||
case 'V':
|
||||
version();
|
||||
exit(0);
|
||||
case 'I':
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
C_MODE_END
|
||||
|
||||
|
||||
/*
|
||||
- call load_defaults to load configuration file section
|
||||
- call handle_options to assign defaults and command-line arguments
|
||||
to the class members
|
||||
if either of these function fail, exit the program
|
||||
May not return.
|
||||
*/
|
||||
|
||||
void Options::load(int argc, char **argv)
|
||||
{
|
||||
if (int rc= handle_options(&argc, &argv, my_long_options, get_one_option))
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
void init_mysys_library(const char *progname)
|
||||
{
|
||||
MY_INIT((char *) progname);
|
||||
}
|
40
server-tools/instance-manager/options.h
Normal file
40
server-tools/instance-manager/options.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
|
||||
#define INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
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 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
/*
|
||||
Options - all possible options for the instance manager grouped in one
|
||||
struct.
|
||||
*/
|
||||
|
||||
struct Options
|
||||
{
|
||||
static char run_as_service; /* handle_options doesn't support bool */
|
||||
static const char *log_file_name;
|
||||
static const char *pid_file_name;
|
||||
static const char *socket_file_name;
|
||||
|
||||
static void load(int argc, char **argv);
|
||||
};
|
||||
|
||||
void init_mysys_library(const char *progname);
|
||||
|
||||
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
|
Reference in New Issue
Block a user