mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Port cleanups, trivial refactoring and code rearrangements from
Alik's patch for BUG#22306: STOP INSTANCE can not be applied for instances in Crashed, Failed and Abandoned" to ease review process. Evaluate global variable linuxthreads before starting threads to avoid a race. server-tools/instance-manager/buffer.cc: Fix spelling. server-tools/instance-manager/command.h: Fix spelling. server-tools/instance-manager/commands.cc: Fix spelling. server-tools/instance-manager/commands.h: Fix spelling, tidy up. server-tools/instance-manager/guardian.cc: Cleanup logging, options.get_shutdown_delay() is a method, tidy up. server-tools/instance-manager/instance.cc: Rearrange methods to be the same as in Alik's patch, fix spelling errors, clean up logging texts, port comments from Alik's patch, implement some basic renames from his patch. No real changes. server-tools/instance-manager/instance.h: Tidy up, renames. server-tools/instance-manager/instance_map.cc: Fix spellings, port some refactoring from Alik's patch. server-tools/instance-manager/instance_map.h: Cleanup. server-tools/instance-manager/instance_options.cc: Cleanup. Implement Instance_options::get_shutdown_delay() and Instance_options::get_mysqld_port(). server-tools/instance-manager/instance_options.h: Cleanup. server-tools/instance-manager/listener.cc: Cleanup. server-tools/instance-manager/log.cc: Fix spelling. server-tools/instance-manager/manager.cc: Cleanup. server-tools/instance-manager/manager.h: Add getters for Manager members. server-tools/instance-manager/mysqlmanager.cc: Evaluate linuxthreads before starting threads to avoid a race. server-tools/instance-manager/parse_output.cc: Fix spelling. server-tools/instance-manager/priv.cc: Cleanup. server-tools/instance-manager/priv.h: Cleanup. server-tools/instance-manager/user_management_commands.cc: Fix spelling. server-tools/instance-manager/user_management_commands.h: Fix spelling. server-tools/instance-manager/user_map.cc: Fix spelling.
This commit is contained in:
@ -27,7 +27,7 @@ const uint Buffer::MAX_BUFFER_SIZE= 16777216;
|
||||
/*
|
||||
Puts the given string to the buffer.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
append()
|
||||
position start position in the buffer
|
||||
string string to be put in the buffer
|
||||
@ -59,7 +59,7 @@ int Buffer::append(uint position, const char *string, uint len_arg)
|
||||
Checks whether the current buffer size is ok to put a string of the length
|
||||
"len_arg" starting from "position" and reallocs it if no.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
reserve()
|
||||
position the number starting byte on the buffer to store a buffer
|
||||
len_arg the length of the string.
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
/*
|
||||
This operation incapsulates behaviour of the command.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
net The network connection to the client.
|
||||
connection_id Client connection ID
|
||||
|
||||
|
@ -49,7 +49,7 @@ static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
|
||||
/*
|
||||
Add a string to a buffer.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
put_to_buff()
|
||||
buff buffer to add the string
|
||||
str string to add
|
||||
@ -590,7 +590,7 @@ Create_instance::Create_instance(const LEX_STRING *instance_name_arg)
|
||||
/*
|
||||
This operation initializes Create_instance object.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing instance options.
|
||||
|
||||
RETURN
|
||||
@ -607,7 +607,7 @@ bool Create_instance::init(const char **text)
|
||||
/*
|
||||
This operation parses CREATE INSTANCE options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing instance options.
|
||||
|
||||
RETURN
|
||||
@ -1255,7 +1255,7 @@ bool Abstract_option_cmd::init(const char **text)
|
||||
Correct the option file. The "skip" option is used to remove the found
|
||||
option.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
Abstract_option_cmd::correct_file()
|
||||
skip Skip the option, being searched while writing the result file.
|
||||
That is, to delete it.
|
||||
@ -1395,7 +1395,7 @@ int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id)
|
||||
/*
|
||||
This operation parses SET options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing options.
|
||||
|
||||
RETURN
|
||||
@ -1569,7 +1569,7 @@ int Set_option::process_option(Instance *instance, Named_value *option)
|
||||
/*
|
||||
This operation parses UNSET options.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
text [IN/OUT] a pointer to the text containing options.
|
||||
|
||||
RETURN
|
||||
|
@ -32,15 +32,11 @@
|
||||
|
||||
/*
|
||||
Print all instances of this instance manager.
|
||||
Grammar: SHOW ISTANCES
|
||||
Grammar: SHOW INSTANCES
|
||||
*/
|
||||
|
||||
class Show_instances : public Command
|
||||
class Show_instances: public Command
|
||||
{
|
||||
public:
|
||||
Show_instances()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
|
||||
@ -57,10 +53,6 @@ private:
|
||||
|
||||
class Flush_instances : public Command
|
||||
{
|
||||
public:
|
||||
Flush_instances()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
};
|
||||
@ -103,7 +95,7 @@ private:
|
||||
|
||||
/*
|
||||
Print status of an instance.
|
||||
Grammar: SHOW ISTANCE STATUS <instance_name>
|
||||
Grammar: SHOW INSTANCE STATUS <instance_name>
|
||||
*/
|
||||
|
||||
class Show_instance_status : public Abstract_instance_cmd
|
||||
@ -319,10 +311,6 @@ private:
|
||||
|
||||
class Set_option : public Abstract_option_cmd
|
||||
{
|
||||
public:
|
||||
Set_option()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual bool parse_args(const char **text);
|
||||
virtual int process_option(Instance *instance, Named_value *option);
|
||||
@ -336,10 +324,6 @@ protected:
|
||||
|
||||
class Unset_option: public Abstract_option_cmd
|
||||
{
|
||||
public:
|
||||
Unset_option()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual bool parse_args(const char **text);
|
||||
virtual int process_option(Instance *instance, Named_value *option);
|
||||
@ -357,10 +341,6 @@ protected:
|
||||
|
||||
class Syntax_error : public Command
|
||||
{
|
||||
public:
|
||||
Syntax_error()
|
||||
{ }
|
||||
|
||||
public:
|
||||
int execute(st_net *net, ulong connection_id);
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ Guardian::~Guardian()
|
||||
void Guardian::request_shutdown()
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_guardian);
|
||||
/* stop instances or just clean up Guardian repository */
|
||||
/* STOP Instances or just clean up Guardian repository */
|
||||
stop_instances();
|
||||
shutdown_requested= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_guardian);
|
||||
@ -110,23 +110,14 @@ void Guardian::process_instance(Instance *instance,
|
||||
|
||||
if (current_node->state == STOPPING)
|
||||
{
|
||||
/* this branch is executed during shutdown */
|
||||
if (instance->options.shutdown_delay)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
waitchild= instance->options.shutdown_delay_val;
|
||||
}
|
||||
waitchild= instance->options.get_shutdown_delay();
|
||||
|
||||
/* this returns TRUE if and only if an instance was stopped for sure */
|
||||
if (instance->is_crashed())
|
||||
*guarded_instances= list_delete(*guarded_instances, node);
|
||||
else if ( (uint) (current_time - current_node->last_checked) > waitchild)
|
||||
{
|
||||
instance->kill_instance(SIGKILL);
|
||||
instance->kill_mysqld(SIGKILL);
|
||||
/*
|
||||
Later we do node= node->next. This is ok, as we are only removing
|
||||
the node from the list. The pointer to the next one is still valid.
|
||||
@ -137,20 +128,20 @@ void Guardian::process_instance(Instance *instance,
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->is_running())
|
||||
if (instance->is_mysqld_running())
|
||||
{
|
||||
/* The instance can be contacted on it's port */
|
||||
|
||||
/* If STARTING also check that pidfile has been created */
|
||||
if (current_node->state == STARTING &&
|
||||
current_node->instance->options.get_pid() == 0)
|
||||
current_node->instance->options.load_pid() == 0)
|
||||
{
|
||||
/* Pid file not created yet, don't go to STARTED state yet */
|
||||
}
|
||||
else if (current_node->state != STARTED)
|
||||
{
|
||||
/* clear status fields */
|
||||
log_info("guardian: instance '%s' is running, set state to STARTED.",
|
||||
log_info("Guardian: '%s' is running, set state to STARTED.",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
current_node->restart_counter= 0;
|
||||
current_node->crash_moment= 0;
|
||||
@ -161,7 +152,7 @@ void Guardian::process_instance(Instance *instance,
|
||||
{
|
||||
switch (current_node->state) {
|
||||
case NOT_STARTED:
|
||||
log_info("guardian: starting instance '%s'...",
|
||||
log_info("Guardian: starting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
|
||||
/* NOTE, set state to STARTING _before_ start() is called */
|
||||
@ -186,7 +177,7 @@ void Guardian::process_instance(Instance *instance,
|
||||
if (instance->is_crashed())
|
||||
{
|
||||
instance->start();
|
||||
log_info("guardian: starting instance '%s'...",
|
||||
log_info("Guardian: starting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
}
|
||||
}
|
||||
@ -204,14 +195,15 @@ void Guardian::process_instance(Instance *instance,
|
||||
instance->start();
|
||||
current_node->last_checked= current_time;
|
||||
current_node->restart_counter++;
|
||||
log_info("guardian: restarting instance '%s'...",
|
||||
log_info("Guardian: restarting '%s'...",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info("guardian: cannot start instance %s. Abandoning attempts "
|
||||
"to (re)start it", instance->options.instance_name.str);
|
||||
log_info("Guardian: can not start '%s'. "
|
||||
"Abandoning attempts to (re)start it",
|
||||
(const char *) instance->options.instance_name.str);
|
||||
current_node->state= CRASHED_AND_ABANDONED;
|
||||
}
|
||||
}
|
||||
@ -226,13 +218,12 @@ void Guardian::process_instance(Instance *instance,
|
||||
|
||||
|
||||
/*
|
||||
Run guardian thread
|
||||
Main function of Guardian thread.
|
||||
|
||||
SYNOPSIS
|
||||
run()
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Check for all guarded instances and restart them if needed. If everything
|
||||
is fine go and sleep for some time.
|
||||
*/
|
||||
@ -436,7 +427,7 @@ int Guardian::stop_instances()
|
||||
If instance is running or was running (and now probably hanging),
|
||||
request stop.
|
||||
*/
|
||||
if (current_node->instance->is_running() ||
|
||||
if (current_node->instance->is_mysqld_running() ||
|
||||
(current_node->state == STARTED))
|
||||
{
|
||||
current_node->state= STOPPING;
|
||||
@ -446,7 +437,7 @@ int Guardian::stop_instances()
|
||||
/* otherwise remove it from the list */
|
||||
guarded_instances= list_delete(guarded_instances, node);
|
||||
/* But try to kill it anyway. Just in case */
|
||||
current_node->instance->kill_instance(SIGTERM);
|
||||
current_node->instance->kill_mysqld(SIGTERM);
|
||||
node= node->next;
|
||||
}
|
||||
return 0;
|
||||
@ -499,5 +490,5 @@ bool Guardian::is_active(Instance *instance)
|
||||
if (guarded)
|
||||
return true;
|
||||
|
||||
return instance->is_running();
|
||||
return instance->is_mysqld_running();
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "instance.h"
|
||||
|
||||
#include <my_global.h>
|
||||
#include <mysql.h>
|
||||
|
||||
#include <signal.h>
|
||||
@ -29,21 +28,15 @@
|
||||
#endif
|
||||
|
||||
#include "guardian.h"
|
||||
#include "instance_map.h"
|
||||
#include "manager.h"
|
||||
#include "log.h"
|
||||
#include "mysql_manager_error.h"
|
||||
#include "portability.h"
|
||||
#include "priv.h"
|
||||
#include "thread_registry.h"
|
||||
#include "instance_map.h"
|
||||
|
||||
|
||||
const LEX_STRING
|
||||
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
|
||||
|
||||
static const char * const INSTANCE_NAME_PREFIX= Instance::DFLT_INSTANCE_NAME.str;
|
||||
static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length;
|
||||
|
||||
|
||||
/* {{{ Platform-specific functions. */
|
||||
|
||||
#ifndef __WIN__
|
||||
typedef pid_t My_process_info;
|
||||
@ -73,15 +66,16 @@ private:
|
||||
|
||||
void Instance_monitor::run()
|
||||
{
|
||||
start_and_monitor_instance(&instance->options, instance->get_map(),
|
||||
&instance->thread_registry);
|
||||
start_and_monitor_instance(&instance->options,
|
||||
Manager::get_instance_map(),
|
||||
Manager::get_thread_registry());
|
||||
delete this;
|
||||
}
|
||||
|
||||
/*
|
||||
Wait for an instance
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
wait_process()
|
||||
pi Pointer to the process information structure
|
||||
(platform-dependent).
|
||||
@ -139,11 +133,10 @@ static int wait_process(My_process_info *pi)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Launch an instance
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
start_process()
|
||||
instance_options Pointer to the options of the instance to be
|
||||
launched.
|
||||
@ -151,13 +144,13 @@ static int wait_process(My_process_info *pi)
|
||||
(platform-dependent).
|
||||
|
||||
RETURN
|
||||
0 - Success
|
||||
1 - Cannot create an instance
|
||||
FALSE - Success
|
||||
TRUE - Cannot create an instance
|
||||
*/
|
||||
|
||||
#ifndef __WIN__
|
||||
static int start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
static bool start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
{
|
||||
#ifndef __QNX__
|
||||
*pi= fork();
|
||||
@ -177,15 +170,16 @@ static int start_process(Instance_options *instance_options,
|
||||
/* exec never returns */
|
||||
exit(1);
|
||||
case -1:
|
||||
log_info("cannot create a new process to start instance '%s'.",
|
||||
log_info("Instance '%s': can not start mysqld: fork() failed.",
|
||||
(const char *) instance_options->instance_name.str);
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
static int start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
static bool start_process(Instance_options *instance_options,
|
||||
My_process_info *pi)
|
||||
{
|
||||
STARTUPINFO si;
|
||||
|
||||
@ -200,7 +194,7 @@ static int start_process(Instance_options *instance_options,
|
||||
|
||||
char *cmdline= new char[cmdlen];
|
||||
if (cmdline == NULL)
|
||||
return 1;
|
||||
return TRUE;
|
||||
|
||||
cmdline[0]= 0;
|
||||
for (int i= 0; instance_options->argv[i] != 0; i++)
|
||||
@ -224,352 +218,10 @@ static int start_process(Instance_options *instance_options,
|
||||
pi); /* Pointer to PROCESS_INFORMATION structure */
|
||||
delete cmdline;
|
||||
|
||||
return (!result);
|
||||
return !result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Fork child, exec an instance and monitor it.
|
||||
|
||||
SYNOPSYS
|
||||
start_and_monitor_instance()
|
||||
old_instance_options Pointer to the options of the instance to be
|
||||
launched. This info is likely to become obsolete
|
||||
when function returns from wait_process()
|
||||
instance_map Pointer to the instance_map. We use it to protect
|
||||
the instance from deletion, while we are working
|
||||
with it.
|
||||
|
||||
DESCRIPTION
|
||||
Fork a child, then exec and monitor it. When the child is dead,
|
||||
find appropriate instance (for this purpose we save its name),
|
||||
set appropriate flags and wake all threads waiting for instance
|
||||
to stop.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void
|
||||
Instance_monitor::
|
||||
start_and_monitor_instance(Instance_options *old_instance_options,
|
||||
Instance_map *instance_map,
|
||||
Thread_registry *thread_registry)
|
||||
{
|
||||
Instance_name instance_name(&old_instance_options->instance_name);
|
||||
Instance *current_instance;
|
||||
My_process_info process_info;
|
||||
Thread_info thread_info;
|
||||
|
||||
log_info("Monitoring thread (instance: '%s'): started.",
|
||||
(const char *) instance_name.get_c_str());
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
{
|
||||
/*
|
||||
Register thread in Thread_registry to wait for it to stop on shutdown
|
||||
only if instance is guarded. If instance is guarded, the thread will not
|
||||
finish, because nonguarded instances are not stopped on shutdown.
|
||||
*/
|
||||
thread_registry->register_thread(&thread_info, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
Lock instance map to guarantee that no instances are deleted during
|
||||
strmake() and execv() calls.
|
||||
*/
|
||||
instance_map->lock();
|
||||
|
||||
/*
|
||||
Save the instance name in the case if Instance object we
|
||||
are using is destroyed. (E.g. by "FLUSH INSTANCES")
|
||||
*/
|
||||
|
||||
log_info("starting instance %s...",
|
||||
(const char *) instance_name.get_c_str());
|
||||
|
||||
if (start_process(old_instance_options, &process_info))
|
||||
{
|
||||
instance_map->unlock();
|
||||
return; /* error is logged */
|
||||
}
|
||||
|
||||
/* allow users to delete instances */
|
||||
instance_map->unlock();
|
||||
|
||||
/* don't check for return value */
|
||||
wait_process(&process_info);
|
||||
|
||||
instance_map->lock();
|
||||
|
||||
current_instance= instance_map->find(instance_name.get_str());
|
||||
|
||||
if (current_instance)
|
||||
current_instance->set_crash_flag_n_wake_all();
|
||||
|
||||
instance_map->unlock();
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
thread_registry->unregister_thread(&thread_info);
|
||||
|
||||
log_info("Monitoring thread (instance: '%s'): finished.",
|
||||
(const char *) instance_name.get_c_str());
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_name_valid(const LEX_STRING *name)
|
||||
{
|
||||
const char *name_suffix= name->str + INSTANCE_NAME_PREFIX_LEN;
|
||||
|
||||
if (strncmp(name->str, INSTANCE_NAME_PREFIX, INSTANCE_NAME_PREFIX_LEN) != 0)
|
||||
return FALSE;
|
||||
|
||||
return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
|
||||
{
|
||||
return strcmp(name->str, INSTANCE_NAME_PREFIX) == 0;
|
||||
}
|
||||
|
||||
|
||||
Instance_map *Instance::get_map()
|
||||
{
|
||||
return instance_map;
|
||||
}
|
||||
|
||||
|
||||
void Instance::remove_pid()
|
||||
{
|
||||
int pid;
|
||||
if ((pid= options.get_pid()) != 0) /* check the pidfile */
|
||||
if (options.unlink_pidfile()) /* remove stalled pidfile */
|
||||
log_error("cannot remove pidfile for instance '%s', this might be "
|
||||
"since IM lacks permmissions or hasn't found the pidifle",
|
||||
(const char *) options.instance_name.str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The method starts an instance.
|
||||
|
||||
SYNOPSYS
|
||||
start()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
ER_CANNOT_START_INSTANCE Cannot start instance
|
||||
ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket
|
||||
is already started
|
||||
*/
|
||||
|
||||
int Instance::start()
|
||||
{
|
||||
/* clear crash flag */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
|
||||
if (configured && !is_running())
|
||||
{
|
||||
Instance_monitor *instance_monitor;
|
||||
remove_pid();
|
||||
|
||||
instance_monitor= new Instance_monitor(this);
|
||||
|
||||
if (instance_monitor == NULL || instance_monitor->start_detached())
|
||||
{
|
||||
delete instance_monitor;
|
||||
log_error("Instance::start(): failed to create the monitoring thread"
|
||||
" to start an instance");
|
||||
return ER_CANNOT_START_INSTANCE;
|
||||
}
|
||||
/* The monitoring thread will delete itself when it's finished. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The instance is started already or misconfigured. */
|
||||
return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
|
||||
}
|
||||
|
||||
/*
|
||||
The method sets the crash flag and wakes all waiters on
|
||||
COND_instance_stopped and COND_guardian
|
||||
|
||||
SYNOPSYS
|
||||
set_crash_flag_n_wake_all()
|
||||
|
||||
DESCRIPTION
|
||||
The method is called when an instance is crashed or terminated.
|
||||
In the former case it might indicate that guardian probably should
|
||||
restart it.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void Instance::set_crash_flag_n_wake_all()
|
||||
{
|
||||
/* set instance state to crashed */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
/*
|
||||
Wake connection threads waiting for an instance to stop. This
|
||||
is needed if a user issued command to stop an instance via
|
||||
mysql connection. This is not the case if Guardian stop the thread.
|
||||
*/
|
||||
pthread_cond_signal(&COND_instance_stopped);
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&instance_map->guardian->COND_guardian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Instance::Instance(Thread_registry &thread_registry_arg):
|
||||
thread_registry(thread_registry_arg), crashed(FALSE), configured(FALSE)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance, 0);
|
||||
pthread_cond_init(&COND_instance_stopped, 0);
|
||||
}
|
||||
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
pthread_cond_destroy(&COND_instance_stopped);
|
||||
pthread_mutex_destroy(&LOCK_instance);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_crashed()
|
||||
{
|
||||
bool val;
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
val= crashed;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_running()
|
||||
{
|
||||
MYSQL mysql;
|
||||
uint port= 0;
|
||||
const char *socket= NULL;
|
||||
static const char *password= "check_connection";
|
||||
static const char *username= "MySQL_Instance_Manager";
|
||||
static const char *access_denied_message= "Access denied for user";
|
||||
bool return_val;
|
||||
|
||||
if (options.mysqld_port)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check mysqld_port here, but use
|
||||
mysqld_port_val. The idea is that if the option is unset, mysqld_port
|
||||
will be NULL, but mysqld_port_val will not be reset.
|
||||
*/
|
||||
port= options.mysqld_port_val;
|
||||
}
|
||||
|
||||
if (options.mysqld_socket)
|
||||
socket= options.mysqld_socket;
|
||||
|
||||
/* no port was specified => instance falled back to default value */
|
||||
if (!options.mysqld_port && !options.mysqld_socket)
|
||||
port= SERVER_DEFAULT_PORT;
|
||||
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
|
||||
mysql_init(&mysql);
|
||||
/* try to connect to a server with a fake username/password pair */
|
||||
if (mysql_real_connect(&mysql, LOCAL_HOST, username,
|
||||
password,
|
||||
NullS, port,
|
||||
socket, 0))
|
||||
{
|
||||
/*
|
||||
We have successfully connected to the server using fake
|
||||
username/password. Write a warning to the logfile.
|
||||
*/
|
||||
log_info("The Instance Manager was able to log into you server "
|
||||
"with faked compiled-in password while checking server status. "
|
||||
"Looks like something is wrong.");
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return_val= TRUE; /* server is alive */
|
||||
}
|
||||
else
|
||||
return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
|
||||
sizeof(access_denied_message) - 1));
|
||||
|
||||
mysql_close(&mysql);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stop an instance.
|
||||
|
||||
SYNOPSYS
|
||||
stop()
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started
|
||||
ER_STOP_INSTANCE mysql_shutdown reported an error
|
||||
*/
|
||||
|
||||
int Instance::stop()
|
||||
{
|
||||
struct timespec timeout;
|
||||
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
||||
|
||||
if (is_running())
|
||||
{
|
||||
if (options.shutdown_delay)
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
waitchild= options.shutdown_delay_val;
|
||||
}
|
||||
|
||||
kill_instance(SIGTERM);
|
||||
/* sleep on condition to wait for SIGCHLD */
|
||||
|
||||
timeout.tv_sec= time(NULL) + waitchild;
|
||||
timeout.tv_nsec= 0;
|
||||
if (pthread_mutex_lock(&LOCK_instance))
|
||||
return ER_STOP_INSTANCE;
|
||||
|
||||
while (options.get_pid() != 0) /* while server isn't stopped */
|
||||
{
|
||||
int status;
|
||||
|
||||
status= pthread_cond_timedwait(&COND_instance_stopped,
|
||||
&LOCK_instance,
|
||||
&timeout);
|
||||
if (status == ETIMEDOUT || status == ETIME)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
kill_instance(SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ER_INSTANCE_IS_NOT_STARTED;
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
|
||||
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
|
||||
@ -633,42 +285,167 @@ int kill(pid_t pid, int signum)
|
||||
}
|
||||
#endif
|
||||
|
||||
void Instance::kill_instance(int signum)
|
||||
{
|
||||
pid_t pid;
|
||||
/* if there are no pid, everything seems to be fine */
|
||||
if ((pid= options.get_pid()) != 0) /* get pid from pidfile */
|
||||
{
|
||||
if (kill(pid, signum) == 0)
|
||||
{
|
||||
/* Kill suceeded */
|
||||
if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
||||
{
|
||||
log_error("The instance '%s' is being stopped forcibly. Normally"
|
||||
"it should not happen. Probably the instance has been"
|
||||
"hanging. You should also check your IM setup",
|
||||
(const char *) options.instance_name.str);
|
||||
/* After sucessful hard kill the pidfile need to be removed */
|
||||
options.unlink_pidfile();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Static constants. */
|
||||
|
||||
const LEX_STRING
|
||||
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
|
||||
|
||||
/* }}} */
|
||||
|
||||
|
||||
/*
|
||||
Initialize instance parameters.
|
||||
Fork child, exec an instance and monitor it.
|
||||
|
||||
SYNOPSYS
|
||||
Instance::init()
|
||||
SYNOPSIS
|
||||
start_and_monitor_instance()
|
||||
old_instance_options Pointer to the options of the instance to be
|
||||
launched. This info is likely to become obsolete
|
||||
when function returns from wait_process()
|
||||
instance_map Pointer to the instance_map. We use it to protect
|
||||
the instance from deletion, while we are working
|
||||
with it.
|
||||
|
||||
DESCRIPTION
|
||||
Fork a child, then exec and monitor it. When the child is dead,
|
||||
find appropriate instance (for this purpose we save its name),
|
||||
set appropriate flags and wake all threads waiting for instance
|
||||
to stop.
|
||||
|
||||
NOTE
|
||||
A separate thread for starting/monitoring instance is a simple way
|
||||
to avoid all pitfalls of the threads implementation in the OS (e.g.
|
||||
LinuxThreads). For one, with such a thread we don't have to process
|
||||
SIGCHLD, which is a tricky business if we want to do it in a
|
||||
portable way.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void
|
||||
Instance_monitor::
|
||||
start_and_monitor_instance(Instance_options *old_instance_options,
|
||||
Instance_map *instance_map,
|
||||
Thread_registry *thread_registry)
|
||||
{
|
||||
Instance_name instance_name(&old_instance_options->instance_name);
|
||||
Instance *current_instance;
|
||||
My_process_info process_info;
|
||||
Thread_info thread_info;
|
||||
|
||||
log_info("Instance '%s': Monitor: started.",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
{
|
||||
/*
|
||||
Register thread in Thread_registry to wait for it to stop on shutdown
|
||||
only if instance is guarded. If instance is guarded, the thread will not
|
||||
finish, because nonguarded instances are not stopped on shutdown.
|
||||
*/
|
||||
thread_registry->register_thread(&thread_info, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
Lock instance map to guarantee that no instances are deleted during
|
||||
strmake() and execv() calls.
|
||||
*/
|
||||
instance_map->lock();
|
||||
|
||||
/*
|
||||
Save the instance name in the case if Instance object we
|
||||
are using is destroyed. (E.g. by "FLUSH INSTANCES")
|
||||
*/
|
||||
|
||||
log_info("Instance '%s': Monitor: starting mysqld...",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
if (start_process(old_instance_options, &process_info))
|
||||
{
|
||||
instance_map->unlock();
|
||||
return; /* error is logged */
|
||||
}
|
||||
|
||||
/* allow users to delete instances */
|
||||
instance_map->unlock();
|
||||
|
||||
log_info("Instance '%s': Monitor: waiting for mysqld to stop...",
|
||||
(const char *) instance->get_name()->str);
|
||||
|
||||
wait_process(&process_info); /* Don't check for return value. */
|
||||
|
||||
instance_map->lock();
|
||||
|
||||
current_instance= instance_map->find(instance_name.get_str());
|
||||
|
||||
if (current_instance)
|
||||
current_instance->set_crash_flag_n_wake_all();
|
||||
|
||||
instance_map->unlock();
|
||||
|
||||
if (!old_instance_options->nonguarded)
|
||||
thread_registry->unregister_thread(&thread_info);
|
||||
|
||||
log_info("Instance '%s': Monitor: finished.",
|
||||
(const char *) instance->get_name()->str);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_name_valid(const LEX_STRING *name)
|
||||
{
|
||||
const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length;
|
||||
|
||||
if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str,
|
||||
Instance::DFLT_INSTANCE_NAME.length) != 0)
|
||||
return FALSE;
|
||||
|
||||
return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
|
||||
}
|
||||
|
||||
|
||||
bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
|
||||
{
|
||||
return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* {{{ Constructor & destructor */
|
||||
|
||||
Instance::Instance()
|
||||
:crashed(FALSE),
|
||||
configured(FALSE)
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance, 0);
|
||||
pthread_cond_init(&COND_instance_stopped, 0);
|
||||
}
|
||||
|
||||
|
||||
Instance::~Instance()
|
||||
{
|
||||
log_info("Instance '%s': destroying...", (const char *) get_name()->str);
|
||||
|
||||
pthread_cond_destroy(&COND_instance_stopped);
|
||||
pthread_mutex_destroy(&LOCK_instance);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
Initialize instance options.
|
||||
|
||||
SYNOPSIS
|
||||
init()
|
||||
name_arg name of the instance
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
!0 error
|
||||
FALSE - ok
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
int Instance::init(const LEX_STRING *name_arg)
|
||||
bool Instance::init(const LEX_STRING *name_arg)
|
||||
{
|
||||
mysqld_compatible= is_mysqld_compatible_name(name_arg);
|
||||
|
||||
@ -676,14 +453,295 @@ int Instance::init(const LEX_STRING *name_arg)
|
||||
}
|
||||
|
||||
|
||||
int Instance::complete_initialization(Instance_map *instance_map_arg,
|
||||
const char *mysqld_path)
|
||||
/*
|
||||
Complete instance options initialization.
|
||||
|
||||
SYNOPSIS
|
||||
complete_initialization()
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
TRUE - error
|
||||
*/
|
||||
|
||||
bool Instance::complete_initialization()
|
||||
{
|
||||
instance_map= instance_map_arg;
|
||||
configured= !options.complete_initialization(mysqld_path);
|
||||
return 0;
|
||||
configured= ! options.complete_initialization();
|
||||
return FALSE;
|
||||
/*
|
||||
TODO: return actual status (from
|
||||
Instance_options::complete_initialization()) here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Determine if mysqld is accepting connections.
|
||||
|
||||
SYNOPSIS
|
||||
is_mysqld_running()
|
||||
|
||||
DESCRIPTION
|
||||
Try to connect to mysqld with fake login/password to check whether it is
|
||||
accepting connections or not.
|
||||
|
||||
MT-NOTE: this operation must be called under acquired LOCK_instance.
|
||||
|
||||
RETURN
|
||||
TRUE - mysqld is alive and accept connections
|
||||
FALSE - otherwise.
|
||||
*/
|
||||
|
||||
bool Instance::is_mysqld_running()
|
||||
{
|
||||
MYSQL mysql;
|
||||
uint port= options.get_mysqld_port(); /* 0 if not specified. */
|
||||
const char *socket= NULL;
|
||||
static const char *password= "check_connection";
|
||||
static const char *username= "MySQL_Instance_Manager";
|
||||
static const char *access_denied_message= "Access denied for user";
|
||||
bool return_val;
|
||||
|
||||
if (options.mysqld_socket)
|
||||
socket= options.mysqld_socket;
|
||||
|
||||
/* no port was specified => instance falled back to default value */
|
||||
if (!port && !options.mysqld_socket)
|
||||
port= SERVER_DEFAULT_PORT;
|
||||
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
|
||||
mysql_init(&mysql);
|
||||
/* try to connect to a server with a fake username/password pair */
|
||||
if (mysql_real_connect(&mysql, LOCAL_HOST, username,
|
||||
password,
|
||||
NullS, port,
|
||||
socket, 0))
|
||||
{
|
||||
/*
|
||||
We have successfully connected to the server using fake
|
||||
username/password. Write a warning to the logfile.
|
||||
*/
|
||||
log_error("Instance '%s': was able to log into mysqld.",
|
||||
(const char *) get_name()->str);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return_val= TRUE; /* server is alive */
|
||||
}
|
||||
else
|
||||
return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
|
||||
sizeof(access_denied_message) - 1));
|
||||
|
||||
mysql_close(&mysql);
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/*
|
||||
The method starts an instance.
|
||||
|
||||
SYNOPSIS
|
||||
start()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
ER_CANNOT_START_INSTANCE Cannot start instance
|
||||
ER_INSTANCE_ALREADY_STARTED The instance on the specified port/socket
|
||||
is already started
|
||||
*/
|
||||
|
||||
int Instance::start()
|
||||
{
|
||||
/* clear crash flag */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= FALSE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
|
||||
if (configured && !is_mysqld_running())
|
||||
{
|
||||
Instance_monitor *instance_monitor;
|
||||
remove_pid();
|
||||
|
||||
instance_monitor= new Instance_monitor(this);
|
||||
|
||||
if (instance_monitor == NULL || instance_monitor->start_detached())
|
||||
{
|
||||
delete instance_monitor;
|
||||
log_error("Instance::start(): failed to create the monitoring thread"
|
||||
" to start an instance");
|
||||
return ER_CANNOT_START_INSTANCE;
|
||||
}
|
||||
/* The monitoring thread will delete itself when it's finished. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The instance is started already or misconfigured. */
|
||||
return configured ? ER_INSTANCE_ALREADY_STARTED : ER_INSTANCE_MISCONFIGURED;
|
||||
}
|
||||
|
||||
/*
|
||||
The method sets the crash flag and wakes all waiters on
|
||||
COND_instance_stopped and COND_guardian
|
||||
|
||||
SYNOPSIS
|
||||
set_crash_flag_n_wake_all()
|
||||
|
||||
DESCRIPTION
|
||||
The method is called when an instance is crashed or terminated.
|
||||
In the former case it might indicate that guardian probably should
|
||||
restart it.
|
||||
|
||||
RETURN
|
||||
Function returns no value
|
||||
*/
|
||||
|
||||
void Instance::set_crash_flag_n_wake_all()
|
||||
{
|
||||
/* set instance state to crashed */
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
crashed= TRUE;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
/*
|
||||
Wake connection threads waiting for an instance to stop. This
|
||||
is needed if a user issued command to stop an instance via
|
||||
mysql connection. This is not the case if Guardian stop the thread.
|
||||
*/
|
||||
pthread_cond_signal(&COND_instance_stopped);
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&Manager::get_guardian()->COND_guardian);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stop an instance.
|
||||
|
||||
SYNOPSIS
|
||||
stop()
|
||||
|
||||
RETURN:
|
||||
0 ok
|
||||
ER_INSTANCE_IS_NOT_STARTED Looks like the instance it is not started
|
||||
ER_STOP_INSTANCE mysql_shutdown reported an error
|
||||
*/
|
||||
|
||||
int Instance::stop()
|
||||
{
|
||||
struct timespec timeout;
|
||||
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
||||
|
||||
if (is_mysqld_running())
|
||||
{
|
||||
waitchild= options.get_shutdown_delay();
|
||||
|
||||
kill_mysqld(SIGTERM);
|
||||
/* sleep on condition to wait for SIGCHLD */
|
||||
|
||||
timeout.tv_sec= time(NULL) + waitchild;
|
||||
timeout.tv_nsec= 0;
|
||||
if (pthread_mutex_lock(&LOCK_instance))
|
||||
return ER_STOP_INSTANCE;
|
||||
|
||||
while (options.load_pid() != 0) /* while server isn't stopped */
|
||||
{
|
||||
int status;
|
||||
|
||||
status= pthread_cond_timedwait(&COND_instance_stopped,
|
||||
&LOCK_instance,
|
||||
&timeout);
|
||||
if (status == ETIMEDOUT || status == ETIME)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
|
||||
kill_mysqld(SIGKILL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ER_INSTANCE_IS_NOT_STARTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send signal to mysqld.
|
||||
|
||||
SYNOPSIS
|
||||
kill_mysqld()
|
||||
*/
|
||||
|
||||
void Instance::kill_mysqld(int signum)
|
||||
{
|
||||
pid_t mysqld_pid= options.load_pid();
|
||||
|
||||
if (mysqld_pid == 0)
|
||||
{
|
||||
log_info("Instance '%s': no pid file to send a signal (%d).",
|
||||
(const char *) get_name()->str,
|
||||
(int) signum);
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("Instance '%s': sending %d to %d...",
|
||||
(const char *) get_name()->str,
|
||||
(int) signum,
|
||||
(int) mysqld_pid);
|
||||
|
||||
if (kill(mysqld_pid, signum))
|
||||
{
|
||||
log_info("Instance '%s': kill() failed.",
|
||||
(const char *) get_name()->str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kill suceeded */
|
||||
if (signum == SIGKILL) /* really killed instance with SIGKILL */
|
||||
{
|
||||
log_error("The instance '%s' is being stopped forcibly. Normally"
|
||||
"it should not happen. Probably the instance has been"
|
||||
"hanging. You should also check your IM setup",
|
||||
(const char *) options.instance_name.str);
|
||||
/* After sucessful hard kill the pidfile need to be removed */
|
||||
options.unlink_pidfile();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return crashed flag.
|
||||
|
||||
SYNOPSIS
|
||||
is_crashed()
|
||||
|
||||
RETURN
|
||||
TRUE - mysqld crashed
|
||||
FALSE - mysqld hasn't crashed yet
|
||||
*/
|
||||
|
||||
bool Instance::is_crashed()
|
||||
{
|
||||
bool val;
|
||||
pthread_mutex_lock(&LOCK_instance);
|
||||
val= crashed;
|
||||
pthread_mutex_unlock(&LOCK_instance);
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove pid file.
|
||||
*/
|
||||
|
||||
void Instance::remove_pid()
|
||||
{
|
||||
int mysqld_pid= options.load_pid();
|
||||
|
||||
if (mysqld_pid == 0)
|
||||
return;
|
||||
|
||||
if (options.unlink_pidfile())
|
||||
{
|
||||
log_error("Instance '%s': can not unlink pid file.",
|
||||
(const char *) options.instance_name.str);
|
||||
}
|
||||
}
|
||||
|
@ -88,21 +88,19 @@ public:
|
||||
static bool is_mysqld_compatible_name(const LEX_STRING *name);
|
||||
|
||||
public:
|
||||
Instance(Thread_registry &thread_registry_arg);
|
||||
Instance();
|
||||
|
||||
~Instance();
|
||||
int init(const LEX_STRING *name_arg);
|
||||
int complete_initialization(Instance_map *instance_map_arg,
|
||||
const char *mysqld_path);
|
||||
bool init(const LEX_STRING *name_arg);
|
||||
bool complete_initialization();
|
||||
|
||||
bool is_running();
|
||||
bool is_mysqld_running();
|
||||
int start();
|
||||
int stop();
|
||||
/* send a signal to the instance */
|
||||
void kill_instance(int signo);
|
||||
void kill_mysqld(int signo);
|
||||
bool is_crashed();
|
||||
void set_crash_flag_n_wake_all();
|
||||
Instance_map *get_map();
|
||||
|
||||
/*
|
||||
The operation is intended to check if the instance is mysqld-compatible
|
||||
@ -121,7 +119,6 @@ public:
|
||||
public:
|
||||
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
|
||||
Instance_options options;
|
||||
Thread_registry &thread_registry;
|
||||
|
||||
private:
|
||||
/* This attributes is a flag, specifies if the instance has been crashed. */
|
||||
@ -155,7 +152,6 @@ private:
|
||||
stop in Instance::stop()
|
||||
*/
|
||||
pthread_cond_t COND_instance_stopped;
|
||||
Instance_map *instance_map;
|
||||
|
||||
void remove_pid();
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ static void delete_instance(void *u)
|
||||
/*
|
||||
The option handler to pass to the process_default_option_files finction.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
process_option()
|
||||
ctx Handler context. Here it is an instance_map structure.
|
||||
group_name The name of the group the option belongs to.
|
||||
@ -169,7 +169,7 @@ int Instance_map::process_one_option(const LEX_STRING *group,
|
||||
if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str,
|
||||
group->length)))
|
||||
{
|
||||
if (!(instance= new Instance(thread_registry)))
|
||||
if (!(instance= new Instance()))
|
||||
return 1;
|
||||
|
||||
if (instance->init(group) || add_instance(instance))
|
||||
@ -213,16 +213,13 @@ int Instance_map::process_one_option(const LEX_STRING *group,
|
||||
}
|
||||
|
||||
|
||||
Instance_map::Instance_map(const char *default_mysqld_path_arg,
|
||||
Thread_registry &thread_registry_arg):
|
||||
mysqld_path(default_mysqld_path_arg),
|
||||
thread_registry(thread_registry_arg)
|
||||
Instance_map::Instance_map()
|
||||
{
|
||||
pthread_mutex_init(&LOCK_instance_map, 0);
|
||||
}
|
||||
|
||||
|
||||
int Instance_map::init()
|
||||
bool Instance_map::init()
|
||||
{
|
||||
return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
||||
get_instance_key, delete_instance, 0);
|
||||
@ -310,7 +307,7 @@ bool Instance_map::is_there_active_instance()
|
||||
while ((instance= iterator.next()))
|
||||
{
|
||||
if (guardian->find_instance_node(instance) != NULL ||
|
||||
instance->is_running())
|
||||
instance->is_mysqld_running())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@ -335,18 +332,18 @@ int Instance_map::remove_instance(Instance *instance)
|
||||
int Instance_map::create_instance(const LEX_STRING *instance_name,
|
||||
const Named_value_arr *options)
|
||||
{
|
||||
Instance *instance= new Instance(thread_registry);
|
||||
Instance *instance= new Instance();
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
log_error("Error: can not initialize (name: '%s').",
|
||||
log_error("Error: can not allocate instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
return ER_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (instance->init(instance_name))
|
||||
{
|
||||
log_error("Error: can not initialize (name: '%s').",
|
||||
log_error("Error: can not initialize instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
delete instance;
|
||||
return ER_OUT_OF_RESOURCES;
|
||||
@ -374,7 +371,7 @@ int Instance_map::create_instance(const LEX_STRING *instance_name,
|
||||
log_info("Warning: instance name '%s' is mysqld-compatible.",
|
||||
(const char *) instance_name->str);
|
||||
|
||||
if (instance->complete_initialization(this, mysqld_path))
|
||||
if (instance->complete_initialization())
|
||||
{
|
||||
log_error("Error: can not complete initialization of instance (name: '%s').",
|
||||
(const char *) instance_name->str);
|
||||
@ -411,7 +408,7 @@ bool Instance_map::complete_initialization()
|
||||
{
|
||||
Instance *instance= (Instance *) hash_element(&hash, i);
|
||||
|
||||
if (instance->complete_initialization(this, mysqld_path))
|
||||
if (instance->complete_initialization())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -543,14 +540,14 @@ const char *Instance_map::get_instance_state_name(Instance *instance)
|
||||
|
||||
/* The instance is not managed by Guardian: we can report status only. */
|
||||
|
||||
return instance->is_running() ? "online" : "offline";
|
||||
return instance->is_mysqld_running() ? "online" : "offline";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a new configuration section for mysqld-instance in the config file.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
create_instance_in_file()
|
||||
instance_name mysqld-instance name
|
||||
options options for the new mysqld-instance
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
int init();
|
||||
bool init();
|
||||
|
||||
/*
|
||||
Process a given option and assign it to appropricate instance. This is
|
||||
@ -105,8 +105,7 @@ public:
|
||||
int create_instance(const LEX_STRING *instance_name,
|
||||
const Named_value_arr *options);
|
||||
|
||||
Instance_map(const char *default_mysqld_path_arg,
|
||||
Thread_registry &thread_registry_arg);
|
||||
Instance_map();
|
||||
~Instance_map();
|
||||
|
||||
/*
|
||||
@ -132,8 +131,6 @@ private:
|
||||
enum { START_HASH_SIZE = 16 };
|
||||
pthread_mutex_t LOCK_instance_map;
|
||||
HASH hash;
|
||||
|
||||
Thread_registry &thread_registry;
|
||||
};
|
||||
|
||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "buffer.h"
|
||||
#include "instance.h"
|
||||
#include "log.h"
|
||||
#include "options.h"
|
||||
#include "parse_output.h"
|
||||
#include "priv.h"
|
||||
|
||||
@ -82,8 +83,12 @@ bool Instance_options::is_option_im_specific(const char *option_name)
|
||||
|
||||
Instance_options::Instance_options()
|
||||
:mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
|
||||
mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0),
|
||||
nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0),
|
||||
mysqld_pid_file(NULL),
|
||||
nonguarded(NULL),
|
||||
mysqld_port(NULL),
|
||||
mysqld_port_val(0),
|
||||
shutdown_delay(NULL),
|
||||
shutdown_delay_val(0),
|
||||
filled_default_options(0)
|
||||
{
|
||||
mysqld_path.str= NULL;
|
||||
@ -99,7 +104,7 @@ Instance_options::Instance_options()
|
||||
/*
|
||||
Get compiled-in value of default_option
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_default_option()
|
||||
result buffer to put found value
|
||||
result_len buffer size
|
||||
@ -139,7 +144,7 @@ err:
|
||||
/*
|
||||
Fill mysqld_version option (used at initialization stage)
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_instance_version()
|
||||
|
||||
DESCRIPTION
|
||||
@ -182,7 +187,7 @@ int Instance_options::fill_instance_version()
|
||||
err:
|
||||
if (rc)
|
||||
log_error("fill_instance_version: Failed to get version of '%s'",
|
||||
mysqld_path.str);
|
||||
(const char *) mysqld_path.str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -190,7 +195,7 @@ err:
|
||||
/*
|
||||
Fill mysqld_real_path
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_mysqld_real_path()
|
||||
|
||||
DESCRIPTION
|
||||
@ -242,7 +247,7 @@ err:
|
||||
/*
|
||||
Fill various log options
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
fill_log_options()
|
||||
|
||||
DESCRIPTION
|
||||
@ -355,7 +360,7 @@ err:
|
||||
/*
|
||||
Get the full pid file name with path
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_pid_filaname()
|
||||
result buffer to sotre the pidfile value
|
||||
|
||||
@ -396,7 +401,7 @@ int Instance_options::unlink_pidfile()
|
||||
}
|
||||
|
||||
|
||||
pid_t Instance_options::get_pid()
|
||||
pid_t Instance_options::load_pid()
|
||||
{
|
||||
FILE *pid_file_stream;
|
||||
|
||||
@ -415,7 +420,7 @@ pid_t Instance_options::get_pid()
|
||||
}
|
||||
|
||||
|
||||
int Instance_options::complete_initialization(const char *default_path)
|
||||
bool Instance_options::complete_initialization()
|
||||
{
|
||||
int arg_idx;
|
||||
const char *tmp;
|
||||
@ -423,10 +428,14 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
|
||||
if (!mysqld_path.str)
|
||||
{
|
||||
// Need one extra byte, as convert_dirname() adds a slash at the end.
|
||||
if (!(mysqld_path.str= alloc_root(&alloc, strlen(default_path) + 2)))
|
||||
goto err;
|
||||
strcpy(mysqld_path.str, default_path);
|
||||
/* Need one extra byte, as convert_dirname() adds a slash at the end. */
|
||||
mysqld_path.str= alloc_root(&alloc,
|
||||
strlen(Options::Main::default_mysqld_path) + 2);
|
||||
|
||||
if (! mysqld_path.str)
|
||||
return TRUE;
|
||||
|
||||
strcpy(mysqld_path.str, Options::Main::default_mysqld_path);
|
||||
}
|
||||
|
||||
// it's safe to cast this to char* since this is a buffer we are allocating
|
||||
@ -442,7 +451,7 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
shutdown_delay_val= atoi(shutdown_delay);
|
||||
|
||||
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (!mysqld_pid_file)
|
||||
{
|
||||
@ -477,21 +486,21 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
}
|
||||
|
||||
if (get_pid_filename(pid_file_with_path))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
/* we need to reserve space for the final zero + possible default options */
|
||||
if (!(argv= (char**)
|
||||
alloc_root(&alloc, (get_num_options() + 1
|
||||
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
||||
goto err;
|
||||
return TRUE;
|
||||
filled_default_options= 0;
|
||||
|
||||
/* the path must be first in the argv */
|
||||
if (add_to_argv(mysqld_path.str))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (add_to_argv(tmp))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
arg_idx= filled_default_options;
|
||||
for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
|
||||
@ -514,12 +523,9 @@ int Instance_options::complete_initialization(const char *default_path)
|
||||
argv[arg_idx]= 0;
|
||||
|
||||
if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -636,26 +642,26 @@ void Instance_options::print_argv()
|
||||
|
||||
/*
|
||||
We execute this function to initialize some options.
|
||||
Return value: 0 - ok. 1 - unable to allocate memory.
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
TRUE - memory allocation error
|
||||
*/
|
||||
|
||||
int Instance_options::init(const LEX_STRING *instance_name_arg)
|
||||
bool Instance_options::init(const LEX_STRING *instance_name_arg)
|
||||
{
|
||||
instance_name.length= instance_name_arg->length;
|
||||
|
||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||
|
||||
if (options.init())
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
|
||||
instance_name_arg->length)))
|
||||
goto err;
|
||||
return TRUE;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -663,3 +669,29 @@ Instance_options::~Instance_options()
|
||||
{
|
||||
free_root(&alloc, MYF(0));
|
||||
}
|
||||
|
||||
|
||||
uint Instance_options::get_shutdown_delay() const
|
||||
{
|
||||
static const uint DEFAULT_SHUTDOWN_DELAY= 35;
|
||||
|
||||
/*
|
||||
NOTE: it is important to check shutdown_delay here, but use
|
||||
shutdown_delay_val. The idea is that if the option is unset,
|
||||
shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
|
||||
*/
|
||||
|
||||
return shutdown_delay ? shutdown_delay_val : DEFAULT_SHUTDOWN_DELAY;
|
||||
}
|
||||
|
||||
int Instance_options::get_mysqld_port() const
|
||||
{
|
||||
/*
|
||||
NOTE: it is important to check mysqld_port here, but use mysqld_port_val.
|
||||
The idea is that if the option is unset, mysqld_port will be NULL, but
|
||||
mysqld_port_val will not be reset.
|
||||
*/
|
||||
|
||||
return mysqld_port ? mysqld_port_val : 0;
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,9 @@ public:
|
||||
public:
|
||||
Instance_options();
|
||||
~Instance_options();
|
||||
|
||||
/* fills in argv */
|
||||
int complete_initialization(const char *default_path);
|
||||
bool complete_initialization();
|
||||
|
||||
bool set_option(Named_value *option);
|
||||
void unset_option(const char *option_name);
|
||||
@ -55,12 +56,15 @@ public:
|
||||
inline Named_value get_option(int idx) const;
|
||||
|
||||
public:
|
||||
int init(const LEX_STRING *instance_name_arg);
|
||||
pid_t get_pid();
|
||||
bool init(const LEX_STRING *instance_name_arg);
|
||||
pid_t load_pid();
|
||||
int get_pid_filename(char *result);
|
||||
int unlink_pidfile();
|
||||
void print_argv();
|
||||
|
||||
uint get_shutdown_delay() const;
|
||||
int get_mysqld_port() const;
|
||||
|
||||
public:
|
||||
/*
|
||||
We need this value to be greater or equal then FN_REFLEN found in
|
||||
@ -79,14 +83,10 @@ public:
|
||||
const char *mysqld_socket;
|
||||
const char *mysqld_datadir;
|
||||
const char *mysqld_pid_file;
|
||||
const char *mysqld_port;
|
||||
uint mysqld_port_val;
|
||||
LEX_STRING instance_name;
|
||||
LEX_STRING mysqld_path;
|
||||
LEX_STRING mysqld_real_path;
|
||||
const char *nonguarded;
|
||||
const char *shutdown_delay;
|
||||
uint shutdown_delay_val;
|
||||
/* log enums are defined in parse.h */
|
||||
char *logs[3];
|
||||
|
||||
@ -102,6 +102,11 @@ private:
|
||||
int find_option(const char *option_name);
|
||||
|
||||
private:
|
||||
const char *mysqld_port;
|
||||
uint mysqld_port_val;
|
||||
const char *shutdown_delay;
|
||||
uint shutdown_delay_val;
|
||||
|
||||
uint filled_default_options;
|
||||
MEM_ROOT alloc;
|
||||
|
||||
|
@ -85,14 +85,7 @@ void Listener::run()
|
||||
log_info("Listener: started.");
|
||||
|
||||
#ifndef __WIN__
|
||||
/* we use this var to check whether we are running on LinuxThreads */
|
||||
pid_t thread_pid;
|
||||
|
||||
thread_pid= getpid();
|
||||
|
||||
struct sockaddr_un unix_socket_address;
|
||||
/* set global variable */
|
||||
linuxthreads= (thread_pid != manager_pid);
|
||||
#endif
|
||||
|
||||
thread_registry->register_thread(&thread_info);
|
||||
@ -151,10 +144,12 @@ void Listener::run()
|
||||
{
|
||||
set_no_inherit(client_fd);
|
||||
|
||||
Vio *vio= vio_new(client_fd, socket_index == 0 ?
|
||||
VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
||||
socket_index == 0 ? 1 : 0);
|
||||
if (vio != 0)
|
||||
struct st_vio *vio=
|
||||
vio_new(client_fd,
|
||||
socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
||||
socket_index == 0 ? 1 : 0);
|
||||
|
||||
if (vio != NULL)
|
||||
handle_new_mysql_connection(vio);
|
||||
else
|
||||
{
|
||||
@ -318,12 +313,12 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
|
||||
|
||||
/*
|
||||
Create new mysql connection. Created thread is responsible for deletion of
|
||||
the Mysql_connection_thread_args and Vio instances passed to it.
|
||||
SYNOPSYS
|
||||
the Mysql_connection and Vio instances passed to it.
|
||||
SYNOPSIS
|
||||
handle_new_mysql_connection()
|
||||
*/
|
||||
|
||||
void Listener::handle_new_mysql_connection(Vio *vio)
|
||||
void Listener::handle_new_mysql_connection(struct st_vio *vio)
|
||||
{
|
||||
Mysql_connection *mysql_connection=
|
||||
new Mysql_connection(thread_registry, user_map,
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
/*
|
||||
Format log entry and write it to the given stream.
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
log()
|
||||
*/
|
||||
|
||||
|
@ -93,17 +93,17 @@ int my_sigwait(const sigset_t *set, int *sig)
|
||||
#endif
|
||||
|
||||
|
||||
void stop_all(Guardian *guardian, Thread_registry *registry)
|
||||
void Manager::stop_all_threads()
|
||||
{
|
||||
/*
|
||||
Let guardian thread know that it should break it's processing cycle,
|
||||
once it wakes up.
|
||||
*/
|
||||
guardian->request_shutdown();
|
||||
p_guardian->request_shutdown();
|
||||
/* wake guardian */
|
||||
pthread_cond_signal(&guardian->COND_guardian);
|
||||
pthread_cond_signal(&p_guardian->COND_guardian);
|
||||
/* stop all threads */
|
||||
registry->deliver_shutdown();
|
||||
p_thread_registry->deliver_shutdown();
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
@ -112,6 +112,9 @@ void stop_all(Guardian *guardian, Thread_registry *registry)
|
||||
|
||||
Guardian *Manager::p_guardian;
|
||||
Instance_map *Manager::p_instance_map;
|
||||
Thread_registry *Manager::p_thread_registry;
|
||||
User_map *Manager::p_user_map;
|
||||
pid_t Manager::manager_pid;
|
||||
|
||||
/*
|
||||
manager - entry point to the main instance manager process: start
|
||||
@ -137,8 +140,7 @@ int Manager::main()
|
||||
*/
|
||||
|
||||
User_map user_map;
|
||||
Instance_map instance_map(Options::Main::default_mysqld_path,
|
||||
thread_registry);
|
||||
Instance_map instance_map;
|
||||
Guardian guardian(&thread_registry, &instance_map,
|
||||
Options::Main::monitoring_interval);
|
||||
|
||||
@ -147,6 +149,8 @@ int Manager::main()
|
||||
manager_pid= getpid();
|
||||
p_instance_map= &instance_map;
|
||||
p_guardian= instance_map.guardian= &guardian;
|
||||
p_thread_registry= &thread_registry;
|
||||
p_user_map= &user_map;
|
||||
|
||||
/* Initialize instance map. */
|
||||
|
||||
@ -199,14 +203,11 @@ int Manager::main()
|
||||
NOTE: To work nicely with LinuxThreads, the signal thread is the first
|
||||
thread in the process.
|
||||
|
||||
NOTE:
|
||||
After init_thr_alarm() call it's possible to call thr_alarm() (from
|
||||
different threads), that results in sending ALARM signal to the alarm
|
||||
thread (which can be the main thread). That signal can interrupt
|
||||
blocking calls.
|
||||
|
||||
In other words, a blocking call can be interrupted in the main thread
|
||||
after init_thr_alarm().
|
||||
NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
|
||||
(from different threads), that results in sending ALARM signal to the
|
||||
alarm thread (which can be the main thread). That signal can interrupt
|
||||
blocking calls. In other words, a blocking call can be interrupted in
|
||||
the main thread after init_thr_alarm().
|
||||
*/
|
||||
|
||||
sigset_t mask;
|
||||
@ -230,11 +231,12 @@ int Manager::main()
|
||||
*/
|
||||
if (guardian.start_detached())
|
||||
{
|
||||
log_error("manager(): Failed to create the guardian thread");
|
||||
log_error("Error: can not start Guardian thread.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Load instances. */
|
||||
|
||||
{
|
||||
instance_map.guardian->lock();
|
||||
instance_map.lock();
|
||||
@ -246,19 +248,18 @@ int Manager::main()
|
||||
|
||||
if (flush_instances_status)
|
||||
{
|
||||
log_error("Cannot init instances repository. This might be caused by "
|
||||
"the wrong config file options. For instance, missing mysqld "
|
||||
"binary. Aborting.");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: can not init instances repository.");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* start the listener */
|
||||
/* Initialize the Listener. */
|
||||
|
||||
if (listener.start_detached())
|
||||
{
|
||||
log_error("manager(): set_stacksize_n_create_thread(listener) failed");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: can not start Listener thread.");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -268,7 +269,9 @@ int Manager::main()
|
||||
*/
|
||||
pthread_cond_signal(&guardian.COND_guardian);
|
||||
|
||||
log_info("Main loop: started.");
|
||||
/* Main loop. */
|
||||
|
||||
log_info("Manager: started.");
|
||||
|
||||
while (!shutdown_complete)
|
||||
{
|
||||
@ -277,8 +280,8 @@ int Manager::main()
|
||||
|
||||
if ((status= my_sigwait(&mask, &signo)) != 0)
|
||||
{
|
||||
log_error("sigwait() failed");
|
||||
stop_all(&guardian, &thread_registry);
|
||||
log_error("Error: sigwait() failed");
|
||||
stop_all_threads();
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -304,7 +307,7 @@ int Manager::main()
|
||||
Bug #14164 IM tests fail on MacOS X (powermacg5)
|
||||
*/
|
||||
#ifdef IGNORE_SIGHUP_SIGQUIT
|
||||
if ( SIGHUP == signo )
|
||||
if (SIGHUP == signo)
|
||||
continue;
|
||||
#endif
|
||||
if (THR_SERVER_ALARM == signo)
|
||||
@ -312,7 +315,7 @@ int Manager::main()
|
||||
else
|
||||
#endif
|
||||
{
|
||||
log_info("Main loop: got shutdown signal.");
|
||||
log_info("Manager: got shutdown signal.");
|
||||
|
||||
if (!guardian.is_stopped())
|
||||
{
|
||||
@ -327,7 +330,7 @@ int Manager::main()
|
||||
}
|
||||
}
|
||||
|
||||
log_info("Main loop: finished.");
|
||||
log_info("Manager: finished.");
|
||||
|
||||
rc= 0;
|
||||
|
||||
|
@ -19,9 +19,12 @@
|
||||
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
|
||||
#pragma interface
|
||||
#endif
|
||||
#include <my_global.h>
|
||||
|
||||
class Guardian;
|
||||
class Instance_map;
|
||||
class Thread_registry;
|
||||
class User_map;
|
||||
|
||||
class Manager
|
||||
{
|
||||
@ -33,12 +36,18 @@ public:
|
||||
*/
|
||||
static Instance_map *get_instance_map() { return p_instance_map; }
|
||||
static Guardian *get_guardian() { return p_guardian; }
|
||||
static Thread_registry *get_thread_registry() { return p_thread_registry; }
|
||||
static User_map *get_user_map() { return p_user_map; }
|
||||
static pid_t get_manager_pid() { return manager_pid; }
|
||||
|
||||
private:
|
||||
static int manager_impl();
|
||||
static void stop_all_threads();
|
||||
private:
|
||||
static pid_t manager_pid;
|
||||
static Guardian *p_guardian;
|
||||
static Instance_map *p_instance_map;
|
||||
static Thread_registry *p_thread_registry;
|
||||
static User_map *p_user_map;
|
||||
};
|
||||
|
||||
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
|
||||
|
@ -71,6 +71,7 @@ static void daemonize(const char *log_file_name);
|
||||
static void angel();
|
||||
static struct passwd *check_user(const char *user);
|
||||
static int set_user(const char *user, struct passwd *user_info);
|
||||
static bool check_if_linuxthreads();
|
||||
#endif
|
||||
|
||||
|
||||
@ -110,6 +111,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (check_if_linuxthreads())
|
||||
goto main_end; /* out of resources */
|
||||
|
||||
if (Options::Daemon::run_as_service)
|
||||
{
|
||||
/* forks, and returns only in child */
|
||||
@ -232,7 +236,7 @@ static void init_environment(char *progname)
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
Become a UNIX service
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
daemonize()
|
||||
*/
|
||||
|
||||
@ -392,4 +396,27 @@ spawn:
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void *check_if_linuxthreads_thread_func(void *arg)
|
||||
{
|
||||
pid_t main_pid= *(pid_t*) arg;
|
||||
linuxthreads= getpid() != main_pid;
|
||||
return NULL;
|
||||
}
|
||||
} /* extern "C" */
|
||||
|
||||
|
||||
static bool check_if_linuxthreads()
|
||||
{
|
||||
pid_t pid= getpid();
|
||||
pthread_t thread_id;
|
||||
int rc;
|
||||
|
||||
rc= pthread_create(&thread_id, NULL, check_if_linuxthreads_thread_func,
|
||||
(void*) &pid);
|
||||
if (rc == 0)
|
||||
rc= pthread_join(thread_id, NULL);
|
||||
|
||||
return test(rc);
|
||||
}
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ void trim_space(const char **text, uint *word_len)
|
||||
/*
|
||||
Parse output of the given command
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
parse_output_and_get_value()
|
||||
|
||||
command the command to execue with popen.
|
||||
|
@ -22,14 +22,13 @@
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||
pid_t manager_pid;
|
||||
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
This flag is set if mysqlmanager has detected that it is running on the
|
||||
system using LinuxThreads
|
||||
*/
|
||||
bool linuxthreads;
|
||||
#endif
|
||||
|
||||
/*
|
||||
The following string must be less then 80 characters, as
|
||||
|
@ -50,9 +50,6 @@ const int MAX_VERSION_LENGTH= 160;
|
||||
|
||||
const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN;
|
||||
|
||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||
extern pid_t manager_pid;
|
||||
|
||||
#ifndef __WIN__
|
||||
/*
|
||||
This flag is set if mysqlmanager has detected that it is running on the
|
||||
|
@ -20,7 +20,7 @@
|
||||
This function must not be used in user-management command implementations.
|
||||
Use get_user_name() instead.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_user_name_impl()
|
||||
|
||||
RETURN
|
||||
@ -58,7 +58,7 @@ static char *get_user_name_impl()
|
||||
(not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
|
||||
wrong.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_user_name()
|
||||
user_name [OUT] on success contains user name
|
||||
|
||||
@ -102,7 +102,7 @@ static bool get_user_name(LEX_STRING *user_name)
|
||||
The password is retrieved from command-line options (if specified) or from
|
||||
console.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
get_password()
|
||||
|
||||
RETURN
|
||||
@ -131,7 +131,7 @@ static const char *get_password()
|
||||
/*
|
||||
Load password file into user map.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
load_password_file()
|
||||
user_map target user map
|
||||
|
||||
@ -160,7 +160,7 @@ static int load_password_file(User_map *user_map)
|
||||
/*
|
||||
Save user map into password file.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
save_password_file()
|
||||
user_map user map
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
/*
|
||||
Executes user-management command.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
execute()
|
||||
|
||||
RETURN
|
||||
|
@ -159,7 +159,7 @@ User_map::~User_map()
|
||||
/*
|
||||
Load password database.
|
||||
|
||||
SYNOPSYS
|
||||
SYNOPSIS
|
||||
load()
|
||||
password_file_name [IN] password file path
|
||||
err_msg [OUT] error message
|
||||
|
Reference in New Issue
Block a user