Patch for IM in scope of working on BUG#24415: Instance manager test

im_daemon_life_cycle fails randomly.

1. Move IM-angel functionality into a separate file, create Angel class.
2. Be more verbose;
3. Fix typo in FLUSH INSTANCES implementation;
4. Polishing.
parent 3febb266
--------------------------------------------------------------------
server_id = 1
server_id = 2
--------------------------------------------------------------------
SHOW VARIABLES LIKE 'server_id'; SHOW VARIABLES LIKE 'server_id';
Variable_name Value Variable_name Value
server_id 1 server_id 1
SHOW INSTANCES; SHOW INSTANCES;
instance_name state instance_name state
mysqld1 starting mysqld1 XXXXX
mysqld2 offline mysqld2 offline
UNSET mysqld1.server_id; UNSET mysqld1.server_id;
ERROR HY000: The instance is active. Stop the instance first ERROR HY000: The instance is active. Stop the instance first
...@@ -86,7 +82,7 @@ UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd; ...@@ -86,7 +82,7 @@ UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
-------------------------------------------------------------------- --------------------------------------------------------------------
-------------------------------------------------------------------- --------------------------------------------------------------------
SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010; SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
ERROR HY000: Bad instance name. Check that the instance with such a name exists ERROR HY000: Unknown instance name
-------------------------------------------------------------------- --------------------------------------------------------------------
-------------------------------------------------------------------- --------------------------------------------------------------------
-------------------------------------------------------------------- --------------------------------------------------------------------
...@@ -98,7 +94,7 @@ ERROR HY000: The instance is active. Stop the instance first ...@@ -98,7 +94,7 @@ ERROR HY000: The instance is active. Stop the instance first
-------------------------------------------------------------------- --------------------------------------------------------------------
-------------------------------------------------------------------- --------------------------------------------------------------------
UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc; UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
ERROR HY000: Bad instance name. Check that the instance with such a name exists ERROR HY000: Unknown instance name
-------------------------------------------------------------------- --------------------------------------------------------------------
server_id = 1 server_id = 1
server_id=2 server_id=2
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
--echo --echo
--echo --> Printing out line for 'testuser'... --echo --> Printing out line for 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=abc | tail -1 --exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=abc | tail -2 | head -1
--echo --echo
--echo --> Listing users... --echo --> Listing users...
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
--echo --echo
--echo --> Printing out line for 'testuser'... --echo --> Printing out line for 'testuser'...
--exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=xyz | tail -1 --exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=xyz | tail -2 | head -1
--echo --echo
--echo --> Listing users... --echo --> Listing users...
......
...@@ -15,17 +15,19 @@ ...@@ -15,17 +15,19 @@
#include <windows.h> #include <windows.h>
#include <signal.h> #include <signal.h>
#include "log.h"
#include "options.h"
#include "IMService.h" #include "IMService.h"
#include "log.h"
#include "manager.h" #include "manager.h"
#include "options.h"
static const char * const IM_SVC_USERNAME= NULL;
static const char * const IM_SVC_PASSWORD= NULL;
IMService::IMService(void) IMService::IMService(void)
:WindowsService("MySqlManager", "MySQL Manager")
{ {
serviceName= "MySqlManager";
displayName= "MySQL Manager";
username= NULL;
password= NULL;
} }
IMService::~IMService(void) IMService::~IMService(void)
...@@ -60,50 +62,63 @@ void IMService::Log(const char *msg) ...@@ -60,50 +62,63 @@ void IMService::Log(const char *msg)
log_info(msg); log_info(msg);
} }
int HandleServiceOptions() int IMService::main()
{ {
int ret_val= 0;
IMService winService; IMService winService;
if (Options::Service::install_as_service) if (Options::Service::install_as_service)
{ {
if (winService.IsInstalled()) if (winService.IsInstalled())
{
log_info("Service is already installed."); log_info("Service is already installed.");
else if (winService.Install()) return 1;
}
if (winService.Install(IM_SVC_USERNAME, IM_SVC_PASSWORD))
{
log_info("Service installed successfully."); log_info("Service installed successfully.");
return 0;
}
else else
{ {
log_error("Service failed to install."); log_error("Service failed to install.");
ret_val= 1; return 1;
} }
} }
else if (Options::Service::remove_service)
if (Options::Service::remove_service)
{ {
if (! winService.IsInstalled()) if (!winService.IsInstalled())
{
log_info("Service is not installed."); log_info("Service is not installed.");
else if (winService.Remove()) return 1;
}
if (winService.Remove())
{
log_info("Service removed successfully."); log_info("Service removed successfully.");
return 0;
}
else else
{ {
log_error("Service failed to remove."); log_error("Service failed to remove.");
ret_val= 1; return 1;
} }
} }
else
log_info("Initializing Instance Manager service...");
if (!winService.Init())
{ {
log_info("Initializing Instance Manager service..."); log_error("Service failed to initialize.");
if (!winService.Init()) fprintf(stderr,
{ "The service should be started by Windows Service Manager.\n"
log_error("Service failed to initialize."); "The MySQL Manager should be started with '--standalone'\n"
fprintf(stderr, "to run from command line.");
"The service should be started by Windows Service Manager.\n"
"The MySQL Manager should be started with '--standalone'\n" return 1;
"to run from command line.");
ret_val= 1;
}
} }
return ret_val; return 0;
} }
...@@ -14,11 +14,14 @@ ...@@ -14,11 +14,14 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#pragma once #pragma once
#include "windowsservice.h" #include "WindowsService.h"
class IMService: public WindowsService class IMService: public WindowsService
{ {
public: public:
static int main();
private:
IMService(void); IMService(void);
~IMService(void); ~IMService(void);
...@@ -27,5 +30,3 @@ protected: ...@@ -27,5 +30,3 @@ protected:
void Stop(); void Stop();
void Run(DWORD argc, LPTSTR *argv); void Run(DWORD argc, LPTSTR *argv);
}; };
extern int HandleServiceOptions();
...@@ -80,7 +80,9 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \ ...@@ -80,7 +80,9 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
portability.h \ portability.h \
exit_codes.h \ exit_codes.h \
user_management_commands.h \ user_management_commands.h \
user_management_commands.cc user_management_commands.cc \
angel.h \
angel.cc
mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \ mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
liboptions.la \ liboptions.la \
......
...@@ -14,19 +14,29 @@ ...@@ -14,19 +14,29 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <windows.h> #include <windows.h>
#include <assert.h>
#include ".\windowsservice.h" #include "WindowsService.h"
static WindowsService *gService; static WindowsService *gService;
WindowsService::WindowsService(void) : WindowsService::WindowsService(const char *p_serviceName,
const char *p_displayName) :
statusCheckpoint(0), statusCheckpoint(0),
serviceName(NULL), serviceName(p_serviceName),
displayName(p_displayName),
inited(FALSE), inited(FALSE),
dwAcceptedControls(SERVICE_ACCEPT_STOP), dwAcceptedControls(SERVICE_ACCEPT_STOP),
debugging(FALSE) debugging(FALSE)
{ {
DBUG_ASSERT(serviceName != NULL);
/* TODO: shouldn't we check displayName too (can it really be NULL)? */
/* WindowsService is assumed to be singleton. Let's assure this. */
DBUG_ASSERT(gService == NULL);
gService= this; gService= this;
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS; status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
status.dwServiceSpecificExitCode= 0; status.dwServiceSpecificExitCode= 0;
} }
...@@ -35,7 +45,7 @@ WindowsService::~WindowsService(void) ...@@ -35,7 +45,7 @@ WindowsService::~WindowsService(void)
{ {
} }
BOOL WindowsService::Install() BOOL WindowsService::Install(const char *username, const char *password)
{ {
bool ret_val= FALSE; bool ret_val= FALSE;
SC_HANDLE newService; SC_HANDLE newService;
...@@ -70,7 +80,7 @@ BOOL WindowsService::Install() ...@@ -70,7 +80,7 @@ BOOL WindowsService::Install()
BOOL WindowsService::Init() BOOL WindowsService::Init()
{ {
assert(serviceName != NULL); DBUG_ASSERT(serviceName != NULL);
if (inited) if (inited)
return TRUE; return TRUE;
...@@ -207,7 +217,7 @@ void WindowsService::HandleControlCode(DWORD opcode) ...@@ -207,7 +217,7 @@ void WindowsService::HandleControlCode(DWORD opcode)
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv) void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
{ {
assert(gService != NULL); DBUG_ASSERT(gService != NULL);
// register our service control handler: // register our service control handler:
gService->RegisterAndRun(argc, argv); gService->RegisterAndRun(argc, argv);
...@@ -215,7 +225,7 @@ void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv) ...@@ -215,7 +225,7 @@ void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
void WINAPI WindowsService::ControlHandler(DWORD opcode) void WINAPI WindowsService::ControlHandler(DWORD opcode)
{ {
assert(gService != NULL); DBUG_ASSERT(gService != NULL);
return gService->HandleControlCode(opcode); return gService->HandleControlCode(opcode);
} }
...@@ -21,8 +21,6 @@ protected: ...@@ -21,8 +21,6 @@ protected:
bool inited; bool inited;
const char *serviceName; const char *serviceName;
const char *displayName; const char *displayName;
const char *username;
const char *password;
SERVICE_STATUS_HANDLE statusHandle; SERVICE_STATUS_HANDLE statusHandle;
DWORD statusCheckpoint; DWORD statusCheckpoint;
SERVICE_STATUS status; SERVICE_STATUS status;
...@@ -30,7 +28,7 @@ protected: ...@@ -30,7 +28,7 @@ protected:
bool debugging; bool debugging;
public: public:
WindowsService(void); WindowsService(const char *p_serviceName, const char *p_displayName);
~WindowsService(void); ~WindowsService(void);
BOOL Install(); BOOL Install();
......
/* Copyright (C) 2003-2006 MySQL 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; version 2 of the License.
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 */
#ifndef __WIN__
#include "angel.h"
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
/*
Include my_global.h right after system includes so that we can change
system defines if needed.
*/
#include "my_global.h"
/* Include other IM files. */
#include "log.h"
#include "manager.h"
#include "options.h"
#include "priv.h"
/************************************************************************/
enum { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL };
static int log_fd;
static volatile sig_atomic_t child_status= CHILD_OK;
static volatile sig_atomic_t shutdown_request_signo= 0;
/************************************************************************/
/**
Open log file.
@return
TRUE on error;
FALSE on success.
*************************************************************************/
static bool open_log_file()
{
log_info("Angel: opening log file '%s'...",
(const char *) Options::Daemon::log_file_name);
log_fd= open(Options::Daemon::log_file_name,
O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (log_fd < 0)
{
log_error("Can not open log file '%s': %s.",
(const char *) Options::Daemon::log_file_name,
(const char *) strerror(errno));
return TRUE;
}
return FALSE;
}
/************************************************************************/
/**
Detach the process from controlling tty.
@return
TRUE on error;
FALSE on success.
*************************************************************************/
static bool detach_process()
{
/*
Become a session leader (the goal is not to have a controlling tty).
setsid() must succeed because child is guaranteed not to be a process
group leader (it belongs to the process group of the parent).
NOTE: if we now don't have a controlling tty we will not receive
tty-related signals - no need to ignore them.
*/
if (setsid() < 0)
{
log_error("setsid() failed: %s.", (const char *) strerror(errno));
return -1;
}
/* Close STDIN. */
log_info("Angel: preparing standard streams.");
if (close(STDIN_FILENO) < 0)
{
log_error("Warning: can not close stdin (%s)."
"Trying to continue...",
(const char *) strerror(errno));
}
/* Dup STDOUT and STDERR to the log file. */
if (dup2(log_fd, STDOUT_FILENO) < 0 ||
dup2(log_fd, STDERR_FILENO) < 0)
{
log_error("Can not redirect stdout and stderr to the log file: %s.",
(const char *) strerror(errno));
return TRUE;
}
if (log_fd != STDOUT_FILENO && log_fd != STDERR_FILENO)
{
if (close(log_fd) < 0)
{
log_error("Can not close original log file handler (%d): %s. "
"Trying to continue...",
(int) log_fd,
(const char *) strerror(errno));
}
}
return FALSE;
}
/************************************************************************/
/**
Create PID file.
@return
TRUE on error;
FALSE on success.
*************************************************************************/
static bool create_pid_file()
{
if (create_pid_file(Options::Daemon::angel_pid_file_name, getpid()))
{
log_error("Angel: can not create pid file (%s).",
(const char *) Options::Daemon::angel_pid_file_name);
return TRUE;
}
log_info("Angel: pid file (%s) created.",
(const char *) Options::Daemon::angel_pid_file_name);
return FALSE;
}
/************************************************************************/
/**
SIGCHLD handler.
Reap child, analyze child exit status, and set child_status
appropriately.
*************************************************************************/
void reap_child(int __attribute__((unused)) signo)
{
/* NOTE: As we have only one child, no need to cycle waitpid(). */
int child_exit_status;
if (waitpid(0, &child_exit_status, WNOHANG) > 0)
{
child_status= WIFSIGNALED(child_exit_status) ?
CHILD_NEED_RESPAWN :
CHILD_EXIT_ANGEL;
}
}
/************************************************************************/
/**
SIGTERM, SIGHUP, SIGINT handler.
Set termination status and return.
*************************************************************************/
void terminate(int signo)
{
shutdown_request_signo= signo;
}
/************************************************************************/
/**
Angel main loop.
@return
The function returns exit status for global main():
0 -- program completed successfully;
!0 -- error occurred.
*************************************************************************/
static int angel_main_loop()
{
/*
Install signal handlers.
NOTE: Although signal handlers are needed only for parent process
(IM-angel), we should install them before fork() in order to avoid race
condition (i.e. to be sure, that IM-angel will receive SIGCHLD in any
case).
*/
sigset_t wait_for_signals_mask;
struct sigaction sa_chld;
struct sigaction sa_term;
struct sigaction sa_chld_orig;
struct sigaction sa_term_orig;
struct sigaction sa_int_orig;
struct sigaction sa_hup_orig;
log_info("Angel: setting necessary signal actions...");
sigemptyset(&wait_for_signals_mask);
sigemptyset(&sa_chld.sa_mask);
sa_chld.sa_handler= reap_child;
sa_chld.sa_flags= SA_NOCLDSTOP;
sigemptyset(&sa_term.sa_mask);
sa_term.sa_handler= terminate;
sa_term.sa_flags= 0;
/* NOTE: sigaction() fails only if arguments are wrong. */
DBUG_ASSERT(!sigaction(SIGCHLD, &sa_chld, &sa_chld_orig));
DBUG_ASSERT(!sigaction(SIGTERM, &sa_term, &sa_term_orig));
DBUG_ASSERT(!sigaction(SIGINT, &sa_term, &sa_int_orig));
DBUG_ASSERT(!sigaction(SIGHUP, &sa_term, &sa_hup_orig));
/* The main Angel loop. */
while (true)
{
/* Spawn a new Manager. */
log_info("Angel: forking Manager process...");
switch (fork()) {
case -1:
log_error("Angel: can not fork IM-main: %s.",
(const char *) strerror(errno));
return -1;
case 0:
/*
We are in child process, which will be IM-main:
- Restore default signal actions to let the IM-main work with
signals as he wishes;
- Call Manager::main();
*/
log_info("Angel: Manager process created successfully.");
/* NOTE: sigaction() fails only if arguments are wrong. */
DBUG_ASSERT(!sigaction(SIGCHLD, &sa_chld_orig, NULL));
DBUG_ASSERT(!sigaction(SIGTERM, &sa_term_orig, NULL));
DBUG_ASSERT(!sigaction(SIGINT, &sa_int_orig, NULL));
DBUG_ASSERT(!sigaction(SIGHUP, &sa_hup_orig, NULL));
log_info("Angel: executing Manager...");
return Manager::main();
}
/* Wait for signals. */
log_info("Angel: waiting for signals...");
while (child_status == CHILD_OK && shutdown_request_signo == 0)
sigsuspend(&wait_for_signals_mask);
/* Exit if one of shutdown signals has been caught. */
if (shutdown_request_signo)
{
log_info("Angel: received shutdown signal (%d). Exiting...",
(int) shutdown_request_signo);
return 0;
}
/* Manager process died. Respawn it if it was a failure. */
if (child_status == CHILD_NEED_RESPAWN)
{
child_status= CHILD_OK;
log_error("Angel: Manager exited abnormally.");
log_info("Angel: sleeping 1 second...");
sleep(1); /* don't respawn too fast */
log_info("Angel: respawning Manager...");
continue;
}
log_info("Angel: Manager exited normally. Exiting...");
return 0;
}
}
/************************************************************************/
/**
Angel main function.
@return
The function returns exit status for global main():
0 -- program completed successfully;
!0 -- error occurred.
*************************************************************************/
int Angel::main()
{
int ret_status;
log_info("Angel: started.");
/* Open log file. */
if (open_log_file())
return -1;
/* Fork a new process. */
log_info("Angel: daemonizing...");
switch (fork()) {
case -1:
/*
This is the main Instance Manager process, fork() failed.
Log an error and bail out with error code.
*/
log_error("fork() failed: %s.", (const char *) strerror(errno));
return -1;
case 0:
/* We are in child process. Continue Angel::main() execution. */
break;
default:
/*
We are in the parent process. Return 0 so that parent exits
successfully.
*/
log_info("Angel: exiting from the original process...");
return 0;
}
/* Detach child from controlling tty. */
if (detach_process())
return -1;
/* Create PID file. */
if (create_pid_file())
return -1;
/* Start Angel main loop. */
return angel_main_loop();
}
#endif // __WIN__
/* Copyright (C) 2003-2006 MySQL 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; version 2 of the License.
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 */
#ifndef INCLUDES_MYSQL_ANGEL_H
#define INCLUDES_MYSQL_ANGEL_H
#ifndef __WIN__
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
#pragma interface
#endif
#include <my_global.h>
class Angel
{
public:
static int main();
};
#endif // INCLUDES_MYSQL_ANGEL_H
#endif // __WIN__
...@@ -210,8 +210,10 @@ int Show_instances::write_data(st_net *net) ...@@ -210,8 +210,10 @@ int Show_instances::write_data(st_net *net)
int Flush_instances::execute(st_net *net, ulong connection_id) int Flush_instances::execute(st_net *net, ulong connection_id)
{ {
if (Manager::flush_instances()) int err_status= Manager::flush_instances();
return ER_OUT_OF_RESOURCES;
if (err_status)
return err_status;
return net_send_ok(net, connection_id, NULL) ? ER_OUT_OF_RESOURCES : 0; return net_send_ok(net, connection_id, NULL) ? ER_OUT_OF_RESOURCES : 0;
} }
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "guardian.h" #include "guardian.h"
#include "instance_map.h" #include "instance_map.h"
#include "listener.h" #include "listener.h"
#include "mysql_manager_error.h"
#include "mysqld_error.h"
#include "log.h" #include "log.h"
#include "options.h" #include "options.h"
#include "priv.h" #include "priv.h"
...@@ -205,14 +207,16 @@ int Manager::main() ...@@ -205,14 +207,16 @@ int Manager::main()
bool shutdown_complete= FALSE; bool shutdown_complete= FALSE;
pid_t manager_pid= getpid(); pid_t manager_pid= getpid();
log_info("Manager: initializing...");
#ifndef __WIN__ #ifndef __WIN__
if (check_if_linux_threads(&linux_threads)) if (check_if_linux_threads(&linux_threads))
{ {
log_error("Can not determine thread model."); log_error("Manager: can not determine thread model.");
return 1; return 1;
} }
log_info("Detected threads model: %s.", log_info("Manager: detected threads model: %s.",
(const char *) (linux_threads ? "LINUX threads" : "POSIX threads")); (const char *) (linux_threads ? "LINUX threads" : "POSIX threads"));
#endif // __WIN__ #endif // __WIN__
...@@ -250,7 +254,7 @@ int Manager::main() ...@@ -250,7 +254,7 @@ int Manager::main()
if (instance_map.init()) if (instance_map.init())
{ {
log_error("Can not initialize instance list: out of memory."); log_error("Manager: can not initialize instance list: out of memory.");
return 1; return 1;
} }
...@@ -258,7 +262,7 @@ int Manager::main() ...@@ -258,7 +262,7 @@ int Manager::main()
if (user_map.init()) if (user_map.init())
{ {
log_error("Can not initialize user list: out of memory."); log_error("Manager: can not initialize user list: out of memory.");
return 1; return 1;
} }
...@@ -277,20 +281,19 @@ int Manager::main() ...@@ -277,20 +281,19 @@ int Manager::main()
} }
else else
{ {
log_error("%s.", (const char *) err_msg); log_error("Manager: %s.", (const char *) err_msg);
return 1; return 1;
} }
} }
/* Write Instance Manager pid file. */ /* Write Instance Manager pid file. */
log_info("IM pid file: '%s'; PID: %d.",
(const char *) Options::Main::pid_file_name,
(int) manager_pid);
if (create_pid_file(Options::Main::pid_file_name, manager_pid)) if (create_pid_file(Options::Main::pid_file_name, manager_pid))
return 1; /* necessary logging has been already done. */ return 1; /* necessary logging has been already done. */
log_info("Manager: pid file (%s) created.",
(const char *) Options::Main::pid_file_name);
/* /*
Initialize signals and alarm-infrastructure. Initialize signals and alarm-infrastructure.
...@@ -326,7 +329,7 @@ int Manager::main() ...@@ -326,7 +329,7 @@ int Manager::main()
if (guardian.start(Thread::DETACHED)) if (guardian.start(Thread::DETACHED))
{ {
log_error("Can not start Guardian thread."); log_error("Manager: can not start Guardian thread.");
goto err; goto err;
} }
...@@ -334,7 +337,7 @@ int Manager::main() ...@@ -334,7 +337,7 @@ int Manager::main()
if (Manager::flush_instances()) if (Manager::flush_instances())
{ {
log_error("Can not init instances repository."); log_error("Manager: can not init instances repository.");
stop_all_threads(); stop_all_threads();
goto err; goto err;
} }
...@@ -343,7 +346,7 @@ int Manager::main() ...@@ -343,7 +346,7 @@ int Manager::main()
if (listener.start(Thread::DETACHED)) if (listener.start(Thread::DETACHED))
{ {
log_error("Can not start Listener thread."); log_error("Manager: can not start Listener thread.");
stop_all_threads(); stop_all_threads();
goto err; goto err;
} }
...@@ -366,7 +369,7 @@ int Manager::main() ...@@ -366,7 +369,7 @@ int Manager::main()
if ((status= my_sigwait(&mask, &signo)) != 0) if ((status= my_sigwait(&mask, &signo)) != 0)
{ {
log_error("sigwait() failed"); log_error("Manager: sigwait() failed");
stop_all_threads(); stop_all_threads();
goto err; goto err;
} }
...@@ -426,7 +429,6 @@ err: ...@@ -426,7 +429,6 @@ err:
#ifndef __WIN__ #ifndef __WIN__
/* free alarm structures */ /* free alarm structures */
end_thr_alarm(1); end_thr_alarm(1);
/* don't pthread_exit to kill all threads who did not shut down in time */
#endif #endif
return rc; return rc;
} }
...@@ -460,34 +462,41 @@ err: ...@@ -460,34 +462,41 @@ err:
In order to avoid such side effects one should never call In order to avoid such side effects one should never call
FLUSH INSTANCES without prior stop of all running instances. FLUSH INSTANCES without prior stop of all running instances.
RETURN
0 On success
ER_OUT_OF_RESOURCES Not enough resources to complete the operation
ER_THERE_IS_ACTIVE_INSTACE If there is an active instance
*/ */
bool Manager::flush_instances() int Manager::flush_instances()
{ {
p_instance_map->lock(); p_instance_map->lock();
if (p_instance_map->is_there_active_instance()) if (p_instance_map->is_there_active_instance())
{ {
p_instance_map->unlock(); p_instance_map->unlock();
return TRUE; return ER_THERE_IS_ACTIVE_INSTACE;
} }
if (p_instance_map->reset()) if (p_instance_map->reset())
{ {
p_instance_map->unlock(); p_instance_map->unlock();
return TRUE; return ER_OUT_OF_RESOURCES;
} }
if (p_instance_map->load()) if (p_instance_map->load())
{ {
p_instance_map->unlock(); p_instance_map->unlock();
return TRUE; /* Don't init guardian if we failed to load instances. */
/* Don't init guardian if we failed to load instances. */
return ER_OUT_OF_RESOURCES;
} }
get_guardian()->init(); /* TODO: check error status. */ get_guardian()->init();
get_guardian()->ping(); get_guardian()->ping();
p_instance_map->unlock(); p_instance_map->unlock();
return FALSE; return 0;
} }
...@@ -32,7 +32,7 @@ class Manager ...@@ -32,7 +32,7 @@ class Manager
public: public:
static int main(); static int main();
static bool flush_instances(); static int flush_instances();
public: public:
/** /**
......
...@@ -47,7 +47,7 @@ unsigned long open_files_limit; ...@@ -47,7 +47,7 @@ unsigned long open_files_limit;
int create_pid_file(const char *pid_file_name, int pid) bool create_pid_file(const char *pid_file_name, int pid)
{ {
FILE *pid_file; FILE *pid_file;
...@@ -58,7 +58,7 @@ int create_pid_file(const char *pid_file_name, int pid) ...@@ -58,7 +58,7 @@ int create_pid_file(const char *pid_file_name, int pid)
(const char *) pid_file_name, (const char *) pid_file_name,
(const char *) strerror(errno), (const char *) strerror(errno),
(int) errno); (int) errno);
return 1; return TRUE;
} }
if (fprintf(pid_file, "%d\n", (int) pid) <= 0) if (fprintf(pid_file, "%d\n", (int) pid) <= 0)
...@@ -67,10 +67,10 @@ int create_pid_file(const char *pid_file_name, int pid) ...@@ -67,10 +67,10 @@ int create_pid_file(const char *pid_file_name, int pid)
(const char *) pid_file_name, (const char *) pid_file_name,
(const char *) strerror(errno), (const char *) strerror(errno),
(int) errno); (int) errno);
return 1; return TRUE;
} }
my_fclose(pid_file, MYF(0)); my_fclose(pid_file, MYF(0));
return 0; return FALSE;
} }
...@@ -94,6 +94,6 @@ extern unsigned long bytes_sent, bytes_received; ...@@ -94,6 +94,6 @@ extern unsigned long bytes_sent, bytes_received;
extern unsigned long mysqld_net_retry_count; extern unsigned long mysqld_net_retry_count;
extern unsigned long open_files_limit; extern unsigned long open_files_limit;
int create_pid_file(const char *pid_file_name, int pid); bool create_pid_file(const char *pid_file_name, int pid);
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H #endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment