mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +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.
This commit is contained in:
@ -27,7 +27,7 @@ const uint Buffer::MAX_BUFFER_SIZE= 16777216;
|
|||||||
/*
|
/*
|
||||||
Puts the given string to the buffer.
|
Puts the given string to the buffer.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
append()
|
append()
|
||||||
position start position in the buffer
|
position start position in the buffer
|
||||||
string string to be put 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
|
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.
|
"len_arg" starting from "position" and reallocs it if no.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
reserve()
|
reserve()
|
||||||
position the number starting byte on the buffer to store a buffer
|
position the number starting byte on the buffer to store a buffer
|
||||||
len_arg the length of the string.
|
len_arg the length of the string.
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
This operation incapsulates behaviour of the command.
|
This operation incapsulates behaviour of the command.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
net The network connection to the client.
|
net The network connection to the client.
|
||||||
connection_id Client connection ID
|
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.
|
Add a string to a buffer.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
put_to_buff()
|
put_to_buff()
|
||||||
buff buffer to add the string
|
buff buffer to add the string
|
||||||
str string to add
|
str string to add
|
||||||
@ -590,7 +590,7 @@ Create_instance::Create_instance(const LEX_STRING *instance_name_arg)
|
|||||||
/*
|
/*
|
||||||
This operation initializes Create_instance object.
|
This operation initializes Create_instance object.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
text [IN/OUT] a pointer to the text containing instance options.
|
text [IN/OUT] a pointer to the text containing instance options.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
@ -607,7 +607,7 @@ bool Create_instance::init(const char **text)
|
|||||||
/*
|
/*
|
||||||
This operation parses CREATE INSTANCE options.
|
This operation parses CREATE INSTANCE options.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
text [IN/OUT] a pointer to the text containing instance options.
|
text [IN/OUT] a pointer to the text containing instance options.
|
||||||
|
|
||||||
RETURN
|
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
|
Correct the option file. The "skip" option is used to remove the found
|
||||||
option.
|
option.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
Abstract_option_cmd::correct_file()
|
Abstract_option_cmd::correct_file()
|
||||||
skip Skip the option, being searched while writing the result file.
|
skip Skip the option, being searched while writing the result file.
|
||||||
That is, to delete it.
|
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.
|
This operation parses SET options.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
text [IN/OUT] a pointer to the text containing options.
|
text [IN/OUT] a pointer to the text containing options.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
@ -1569,7 +1569,7 @@ int Set_option::process_option(Instance *instance, Named_value *option)
|
|||||||
/*
|
/*
|
||||||
This operation parses UNSET options.
|
This operation parses UNSET options.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
text [IN/OUT] a pointer to the text containing options.
|
text [IN/OUT] a pointer to the text containing options.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
|
@ -32,15 +32,11 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Print all instances of this instance manager.
|
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:
|
public:
|
||||||
int execute(st_net *net, ulong connection_id);
|
int execute(st_net *net, ulong connection_id);
|
||||||
|
|
||||||
@ -57,10 +53,6 @@ private:
|
|||||||
|
|
||||||
class Flush_instances : public Command
|
class Flush_instances : public Command
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
Flush_instances()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int execute(st_net *net, ulong connection_id);
|
int execute(st_net *net, ulong connection_id);
|
||||||
};
|
};
|
||||||
@ -103,7 +95,7 @@ private:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Print status of an instance.
|
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
|
class Show_instance_status : public Abstract_instance_cmd
|
||||||
@ -319,10 +311,6 @@ private:
|
|||||||
|
|
||||||
class Set_option : public Abstract_option_cmd
|
class Set_option : public Abstract_option_cmd
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
Set_option()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool parse_args(const char **text);
|
virtual bool parse_args(const char **text);
|
||||||
virtual int process_option(Instance *instance, Named_value *option);
|
virtual int process_option(Instance *instance, Named_value *option);
|
||||||
@ -336,10 +324,6 @@ protected:
|
|||||||
|
|
||||||
class Unset_option: public Abstract_option_cmd
|
class Unset_option: public Abstract_option_cmd
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
Unset_option()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool parse_args(const char **text);
|
virtual bool parse_args(const char **text);
|
||||||
virtual int process_option(Instance *instance, Named_value *option);
|
virtual int process_option(Instance *instance, Named_value *option);
|
||||||
@ -357,10 +341,6 @@ protected:
|
|||||||
|
|
||||||
class Syntax_error : public Command
|
class Syntax_error : public Command
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
Syntax_error()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int execute(st_net *net, ulong connection_id);
|
int execute(st_net *net, ulong connection_id);
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ Guardian::~Guardian()
|
|||||||
void Guardian::request_shutdown()
|
void Guardian::request_shutdown()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_guardian);
|
pthread_mutex_lock(&LOCK_guardian);
|
||||||
/* stop instances or just clean up Guardian repository */
|
/* STOP Instances or just clean up Guardian repository */
|
||||||
stop_instances();
|
stop_instances();
|
||||||
shutdown_requested= TRUE;
|
shutdown_requested= TRUE;
|
||||||
pthread_mutex_unlock(&LOCK_guardian);
|
pthread_mutex_unlock(&LOCK_guardian);
|
||||||
@ -110,23 +110,14 @@ void Guardian::process_instance(Instance *instance,
|
|||||||
|
|
||||||
if (current_node->state == STOPPING)
|
if (current_node->state == STOPPING)
|
||||||
{
|
{
|
||||||
/* this branch is executed during shutdown */
|
waitchild= instance->options.get_shutdown_delay();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this returns TRUE if and only if an instance was stopped for sure */
|
/* this returns TRUE if and only if an instance was stopped for sure */
|
||||||
if (instance->is_crashed())
|
if (instance->is_crashed())
|
||||||
*guarded_instances= list_delete(*guarded_instances, node);
|
*guarded_instances= list_delete(*guarded_instances, node);
|
||||||
else if ( (uint) (current_time - current_node->last_checked) > waitchild)
|
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
|
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.
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance->is_running())
|
if (instance->is_mysqld_running())
|
||||||
{
|
{
|
||||||
/* The instance can be contacted on it's port */
|
/* The instance can be contacted on it's port */
|
||||||
|
|
||||||
/* If STARTING also check that pidfile has been created */
|
/* If STARTING also check that pidfile has been created */
|
||||||
if (current_node->state == STARTING &&
|
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 */
|
/* Pid file not created yet, don't go to STARTED state yet */
|
||||||
}
|
}
|
||||||
else if (current_node->state != STARTED)
|
else if (current_node->state != STARTED)
|
||||||
{
|
{
|
||||||
/* clear status fields */
|
/* 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);
|
(const char *) instance->options.instance_name.str);
|
||||||
current_node->restart_counter= 0;
|
current_node->restart_counter= 0;
|
||||||
current_node->crash_moment= 0;
|
current_node->crash_moment= 0;
|
||||||
@ -161,7 +152,7 @@ void Guardian::process_instance(Instance *instance,
|
|||||||
{
|
{
|
||||||
switch (current_node->state) {
|
switch (current_node->state) {
|
||||||
case NOT_STARTED:
|
case NOT_STARTED:
|
||||||
log_info("guardian: starting instance '%s'...",
|
log_info("Guardian: starting '%s'...",
|
||||||
(const char *) instance->options.instance_name.str);
|
(const char *) instance->options.instance_name.str);
|
||||||
|
|
||||||
/* NOTE, set state to STARTING _before_ start() is called */
|
/* NOTE, set state to STARTING _before_ start() is called */
|
||||||
@ -186,7 +177,7 @@ void Guardian::process_instance(Instance *instance,
|
|||||||
if (instance->is_crashed())
|
if (instance->is_crashed())
|
||||||
{
|
{
|
||||||
instance->start();
|
instance->start();
|
||||||
log_info("guardian: starting instance '%s'...",
|
log_info("Guardian: starting '%s'...",
|
||||||
(const char *) instance->options.instance_name.str);
|
(const char *) instance->options.instance_name.str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,14 +195,15 @@ void Guardian::process_instance(Instance *instance,
|
|||||||
instance->start();
|
instance->start();
|
||||||
current_node->last_checked= current_time;
|
current_node->last_checked= current_time;
|
||||||
current_node->restart_counter++;
|
current_node->restart_counter++;
|
||||||
log_info("guardian: restarting instance '%s'...",
|
log_info("Guardian: restarting '%s'...",
|
||||||
(const char *) instance->options.instance_name.str);
|
(const char *) instance->options.instance_name.str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_info("guardian: cannot start instance %s. Abandoning attempts "
|
log_info("Guardian: can not start '%s'. "
|
||||||
"to (re)start it", instance->options.instance_name.str);
|
"Abandoning attempts to (re)start it",
|
||||||
|
(const char *) instance->options.instance_name.str);
|
||||||
current_node->state= CRASHED_AND_ABANDONED;
|
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
|
SYNOPSIS
|
||||||
run()
|
run()
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
Check for all guarded instances and restart them if needed. If everything
|
Check for all guarded instances and restart them if needed. If everything
|
||||||
is fine go and sleep for some time.
|
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),
|
If instance is running or was running (and now probably hanging),
|
||||||
request stop.
|
request stop.
|
||||||
*/
|
*/
|
||||||
if (current_node->instance->is_running() ||
|
if (current_node->instance->is_mysqld_running() ||
|
||||||
(current_node->state == STARTED))
|
(current_node->state == STARTED))
|
||||||
{
|
{
|
||||||
current_node->state= STOPPING;
|
current_node->state= STOPPING;
|
||||||
@ -446,7 +437,7 @@ int Guardian::stop_instances()
|
|||||||
/* otherwise remove it from the list */
|
/* otherwise remove it from the list */
|
||||||
guarded_instances= list_delete(guarded_instances, node);
|
guarded_instances= list_delete(guarded_instances, node);
|
||||||
/* But try to kill it anyway. Just in case */
|
/* But try to kill it anyway. Just in case */
|
||||||
current_node->instance->kill_instance(SIGTERM);
|
current_node->instance->kill_mysqld(SIGTERM);
|
||||||
node= node->next;
|
node= node->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -499,5 +490,5 @@ bool Guardian::is_active(Instance *instance)
|
|||||||
if (guarded)
|
if (guarded)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return instance->is_running();
|
return instance->is_mysqld_running();
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
|
||||||
#include <my_global.h>
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -29,21 +28,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "guardian.h"
|
#include "guardian.h"
|
||||||
#include "instance_map.h"
|
#include "manager.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mysql_manager_error.h"
|
#include "mysql_manager_error.h"
|
||||||
#include "portability.h"
|
#include "portability.h"
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
#include "thread_registry.h"
|
#include "thread_registry.h"
|
||||||
|
#include "instance_map.h"
|
||||||
|
|
||||||
|
/* {{{ Platform-specific functions. */
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
typedef pid_t My_process_info;
|
typedef pid_t My_process_info;
|
||||||
@ -73,15 +66,16 @@ private:
|
|||||||
|
|
||||||
void Instance_monitor::run()
|
void Instance_monitor::run()
|
||||||
{
|
{
|
||||||
start_and_monitor_instance(&instance->options, instance->get_map(),
|
start_and_monitor_instance(&instance->options,
|
||||||
&instance->thread_registry);
|
Manager::get_instance_map(),
|
||||||
|
Manager::get_thread_registry());
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Wait for an instance
|
Wait for an instance
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
wait_process()
|
wait_process()
|
||||||
pi Pointer to the process information structure
|
pi Pointer to the process information structure
|
||||||
(platform-dependent).
|
(platform-dependent).
|
||||||
@ -139,11 +133,10 @@ static int wait_process(My_process_info *pi)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Launch an instance
|
Launch an instance
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
start_process()
|
start_process()
|
||||||
instance_options Pointer to the options of the instance to be
|
instance_options Pointer to the options of the instance to be
|
||||||
launched.
|
launched.
|
||||||
@ -151,13 +144,13 @@ static int wait_process(My_process_info *pi)
|
|||||||
(platform-dependent).
|
(platform-dependent).
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 - Success
|
FALSE - Success
|
||||||
1 - Cannot create an instance
|
TRUE - Cannot create an instance
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
static int start_process(Instance_options *instance_options,
|
static bool start_process(Instance_options *instance_options,
|
||||||
My_process_info *pi)
|
My_process_info *pi)
|
||||||
{
|
{
|
||||||
#ifndef __QNX__
|
#ifndef __QNX__
|
||||||
*pi= fork();
|
*pi= fork();
|
||||||
@ -177,15 +170,16 @@ static int start_process(Instance_options *instance_options,
|
|||||||
/* exec never returns */
|
/* exec never returns */
|
||||||
exit(1);
|
exit(1);
|
||||||
case -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);
|
(const char *) instance_options->instance_name.str);
|
||||||
return 1;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int start_process(Instance_options *instance_options,
|
static bool start_process(Instance_options *instance_options,
|
||||||
My_process_info *pi)
|
My_process_info *pi)
|
||||||
{
|
{
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
|
|
||||||
@ -200,7 +194,7 @@ static int start_process(Instance_options *instance_options,
|
|||||||
|
|
||||||
char *cmdline= new char[cmdlen];
|
char *cmdline= new char[cmdlen];
|
||||||
if (cmdline == NULL)
|
if (cmdline == NULL)
|
||||||
return 1;
|
return TRUE;
|
||||||
|
|
||||||
cmdline[0]= 0;
|
cmdline[0]= 0;
|
||||||
for (int i= 0; instance_options->argv[i] != 0; i++)
|
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 */
|
pi); /* Pointer to PROCESS_INFORMATION structure */
|
||||||
delete cmdline;
|
delete cmdline;
|
||||||
|
|
||||||
return (!result);
|
return !result;
|
||||||
}
|
}
|
||||||
#endif
|
#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__
|
#ifdef __WIN__
|
||||||
|
|
||||||
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
|
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
|
||||||
@ -633,42 +285,167 @@ int kill(pid_t pid, int signum)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Instance::kill_instance(int signum)
|
/* }}} */
|
||||||
{
|
|
||||||
pid_t pid;
|
/* {{{ Static constants. */
|
||||||
/* if there are no pid, everything seems to be fine */
|
|
||||||
if ((pid= options.get_pid()) != 0) /* get pid from pidfile */
|
const LEX_STRING
|
||||||
{
|
Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialize instance parameters.
|
Fork child, exec an instance and monitor it.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
Instance::init()
|
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
|
name_arg name of the instance
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
0 ok
|
FALSE - ok
|
||||||
!0 error
|
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);
|
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();
|
||||||
configured= !options.complete_initialization(mysqld_path);
|
return FALSE;
|
||||||
return 0;
|
|
||||||
/*
|
/*
|
||||||
TODO: return actual status (from
|
TODO: return actual status (from
|
||||||
Instance_options::complete_initialization()) here.
|
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);
|
static bool is_mysqld_compatible_name(const LEX_STRING *name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Instance(Thread_registry &thread_registry_arg);
|
Instance();
|
||||||
|
|
||||||
~Instance();
|
~Instance();
|
||||||
int init(const LEX_STRING *name_arg);
|
bool init(const LEX_STRING *name_arg);
|
||||||
int complete_initialization(Instance_map *instance_map_arg,
|
bool complete_initialization();
|
||||||
const char *mysqld_path);
|
|
||||||
|
|
||||||
bool is_running();
|
bool is_mysqld_running();
|
||||||
int start();
|
int start();
|
||||||
int stop();
|
int stop();
|
||||||
/* send a signal to the instance */
|
/* send a signal to the instance */
|
||||||
void kill_instance(int signo);
|
void kill_mysqld(int signo);
|
||||||
bool is_crashed();
|
bool is_crashed();
|
||||||
void set_crash_flag_n_wake_all();
|
void set_crash_flag_n_wake_all();
|
||||||
Instance_map *get_map();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The operation is intended to check if the instance is mysqld-compatible
|
The operation is intended to check if the instance is mysqld-compatible
|
||||||
@ -121,7 +119,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
|
enum { DEFAULT_SHUTDOWN_DELAY= 35 };
|
||||||
Instance_options options;
|
Instance_options options;
|
||||||
Thread_registry &thread_registry;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* This attributes is a flag, specifies if the instance has been crashed. */
|
/* This attributes is a flag, specifies if the instance has been crashed. */
|
||||||
@ -155,7 +152,6 @@ private:
|
|||||||
stop in Instance::stop()
|
stop in Instance::stop()
|
||||||
*/
|
*/
|
||||||
pthread_cond_t COND_instance_stopped;
|
pthread_cond_t COND_instance_stopped;
|
||||||
Instance_map *instance_map;
|
|
||||||
|
|
||||||
void remove_pid();
|
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.
|
The option handler to pass to the process_default_option_files finction.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
process_option()
|
process_option()
|
||||||
ctx Handler context. Here it is an instance_map structure.
|
ctx Handler context. Here it is an instance_map structure.
|
||||||
group_name The name of the group the option belongs to.
|
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,
|
if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str,
|
||||||
group->length)))
|
group->length)))
|
||||||
{
|
{
|
||||||
if (!(instance= new Instance(thread_registry)))
|
if (!(instance= new Instance()))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (instance->init(group) || add_instance(instance))
|
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,
|
Instance_map::Instance_map()
|
||||||
Thread_registry &thread_registry_arg):
|
|
||||||
mysqld_path(default_mysqld_path_arg),
|
|
||||||
thread_registry(thread_registry_arg)
|
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&LOCK_instance_map, 0);
|
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,
|
return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
||||||
get_instance_key, delete_instance, 0);
|
get_instance_key, delete_instance, 0);
|
||||||
@ -310,7 +307,7 @@ bool Instance_map::is_there_active_instance()
|
|||||||
while ((instance= iterator.next()))
|
while ((instance= iterator.next()))
|
||||||
{
|
{
|
||||||
if (guardian->find_instance_node(instance) != NULL ||
|
if (guardian->find_instance_node(instance) != NULL ||
|
||||||
instance->is_running())
|
instance->is_mysqld_running())
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -335,18 +332,18 @@ int Instance_map::remove_instance(Instance *instance)
|
|||||||
int Instance_map::create_instance(const LEX_STRING *instance_name,
|
int Instance_map::create_instance(const LEX_STRING *instance_name,
|
||||||
const Named_value_arr *options)
|
const Named_value_arr *options)
|
||||||
{
|
{
|
||||||
Instance *instance= new Instance(thread_registry);
|
Instance *instance= new Instance();
|
||||||
|
|
||||||
if (!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);
|
(const char *) instance_name->str);
|
||||||
return ER_OUT_OF_RESOURCES;
|
return ER_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance->init(instance_name))
|
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);
|
(const char *) instance_name->str);
|
||||||
delete instance;
|
delete instance;
|
||||||
return ER_OUT_OF_RESOURCES;
|
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.",
|
log_info("Warning: instance name '%s' is mysqld-compatible.",
|
||||||
(const char *) instance_name->str);
|
(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').",
|
log_error("Error: can not complete initialization of instance (name: '%s').",
|
||||||
(const char *) instance_name->str);
|
(const char *) instance_name->str);
|
||||||
@ -411,7 +408,7 @@ bool Instance_map::complete_initialization()
|
|||||||
{
|
{
|
||||||
Instance *instance= (Instance *) hash_element(&hash, i);
|
Instance *instance= (Instance *) hash_element(&hash, i);
|
||||||
|
|
||||||
if (instance->complete_initialization(this, mysqld_path))
|
if (instance->complete_initialization())
|
||||||
return TRUE;
|
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. */
|
/* 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.
|
Create a new configuration section for mysqld-instance in the config file.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
create_instance_in_file()
|
create_instance_in_file()
|
||||||
instance_name mysqld-instance name
|
instance_name mysqld-instance name
|
||||||
options options for the new mysqld-instance
|
options options for the new mysqld-instance
|
||||||
|
@ -75,7 +75,7 @@ public:
|
|||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
int init();
|
bool init();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Process a given option and assign it to appropricate instance. This is
|
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,
|
int create_instance(const LEX_STRING *instance_name,
|
||||||
const Named_value_arr *options);
|
const Named_value_arr *options);
|
||||||
|
|
||||||
Instance_map(const char *default_mysqld_path_arg,
|
Instance_map();
|
||||||
Thread_registry &thread_registry_arg);
|
|
||||||
~Instance_map();
|
~Instance_map();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,8 +131,6 @@ private:
|
|||||||
enum { START_HASH_SIZE = 16 };
|
enum { START_HASH_SIZE = 16 };
|
||||||
pthread_mutex_t LOCK_instance_map;
|
pthread_mutex_t LOCK_instance_map;
|
||||||
HASH hash;
|
HASH hash;
|
||||||
|
|
||||||
Thread_registry &thread_registry;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "options.h"
|
||||||
#include "parse_output.h"
|
#include "parse_output.h"
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
|
||||||
@ -82,8 +83,12 @@ bool Instance_options::is_option_im_specific(const char *option_name)
|
|||||||
|
|
||||||
Instance_options::Instance_options()
|
Instance_options::Instance_options()
|
||||||
:mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
|
:mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
|
||||||
mysqld_pid_file(NULL), mysqld_port(NULL), mysqld_port_val(0),
|
mysqld_pid_file(NULL),
|
||||||
nonguarded(NULL), shutdown_delay(NULL), shutdown_delay_val(0),
|
nonguarded(NULL),
|
||||||
|
mysqld_port(NULL),
|
||||||
|
mysqld_port_val(0),
|
||||||
|
shutdown_delay(NULL),
|
||||||
|
shutdown_delay_val(0),
|
||||||
filled_default_options(0)
|
filled_default_options(0)
|
||||||
{
|
{
|
||||||
mysqld_path.str= NULL;
|
mysqld_path.str= NULL;
|
||||||
@ -99,7 +104,7 @@ Instance_options::Instance_options()
|
|||||||
/*
|
/*
|
||||||
Get compiled-in value of default_option
|
Get compiled-in value of default_option
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
get_default_option()
|
get_default_option()
|
||||||
result buffer to put found value
|
result buffer to put found value
|
||||||
result_len buffer size
|
result_len buffer size
|
||||||
@ -139,7 +144,7 @@ err:
|
|||||||
/*
|
/*
|
||||||
Fill mysqld_version option (used at initialization stage)
|
Fill mysqld_version option (used at initialization stage)
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
fill_instance_version()
|
fill_instance_version()
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -182,7 +187,7 @@ int Instance_options::fill_instance_version()
|
|||||||
err:
|
err:
|
||||||
if (rc)
|
if (rc)
|
||||||
log_error("fill_instance_version: Failed to get version of '%s'",
|
log_error("fill_instance_version: Failed to get version of '%s'",
|
||||||
mysqld_path.str);
|
(const char *) mysqld_path.str);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +195,7 @@ err:
|
|||||||
/*
|
/*
|
||||||
Fill mysqld_real_path
|
Fill mysqld_real_path
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
fill_mysqld_real_path()
|
fill_mysqld_real_path()
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -242,7 +247,7 @@ err:
|
|||||||
/*
|
/*
|
||||||
Fill various log options
|
Fill various log options
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
fill_log_options()
|
fill_log_options()
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -355,7 +360,7 @@ err:
|
|||||||
/*
|
/*
|
||||||
Get the full pid file name with path
|
Get the full pid file name with path
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
get_pid_filaname()
|
get_pid_filaname()
|
||||||
result buffer to sotre the pidfile value
|
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;
|
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;
|
int arg_idx;
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
@ -423,10 +428,14 @@ int Instance_options::complete_initialization(const char *default_path)
|
|||||||
|
|
||||||
if (!mysqld_path.str)
|
if (!mysqld_path.str)
|
||||||
{
|
{
|
||||||
// Need one extra byte, as convert_dirname() adds a slash at the end.
|
/* Need one extra byte, as convert_dirname() adds a slash at the end. */
|
||||||
if (!(mysqld_path.str= alloc_root(&alloc, strlen(default_path) + 2)))
|
mysqld_path.str= alloc_root(&alloc,
|
||||||
goto err;
|
strlen(Options::Main::default_mysqld_path) + 2);
|
||||||
strcpy(mysqld_path.str, default_path);
|
|
||||||
|
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
|
// 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);
|
shutdown_delay_val= atoi(shutdown_delay);
|
||||||
|
|
||||||
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
|
if (!(tmp= strdup_root(&alloc, "--no-defaults")))
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
if (!mysqld_pid_file)
|
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))
|
if (get_pid_filename(pid_file_with_path))
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
/* we need to reserve space for the final zero + possible default options */
|
/* we need to reserve space for the final zero + possible default options */
|
||||||
if (!(argv= (char**)
|
if (!(argv= (char**)
|
||||||
alloc_root(&alloc, (get_num_options() + 1
|
alloc_root(&alloc, (get_num_options() + 1
|
||||||
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
||||||
goto err;
|
return TRUE;
|
||||||
filled_default_options= 0;
|
filled_default_options= 0;
|
||||||
|
|
||||||
/* the path must be first in the argv */
|
/* the path must be first in the argv */
|
||||||
if (add_to_argv(mysqld_path.str))
|
if (add_to_argv(mysqld_path.str))
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
if (add_to_argv(tmp))
|
if (add_to_argv(tmp))
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
arg_idx= filled_default_options;
|
arg_idx= filled_default_options;
|
||||||
for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
|
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;
|
argv[arg_idx]= 0;
|
||||||
|
|
||||||
if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
|
if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
err:
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -636,26 +642,26 @@ void Instance_options::print_argv()
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
We execute this function to initialize some options.
|
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;
|
instance_name.length= instance_name_arg->length;
|
||||||
|
|
||||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||||
|
|
||||||
if (options.init())
|
if (options.init())
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
|
if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
|
||||||
instance_name_arg->length)))
|
instance_name_arg->length)))
|
||||||
goto err;
|
return TRUE;
|
||||||
|
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
err:
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -663,3 +669,29 @@ Instance_options::~Instance_options()
|
|||||||
{
|
{
|
||||||
free_root(&alloc, MYF(0));
|
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:
|
public:
|
||||||
Instance_options();
|
Instance_options();
|
||||||
~Instance_options();
|
~Instance_options();
|
||||||
|
|
||||||
/* fills in argv */
|
/* fills in argv */
|
||||||
int complete_initialization(const char *default_path);
|
bool complete_initialization();
|
||||||
|
|
||||||
bool set_option(Named_value *option);
|
bool set_option(Named_value *option);
|
||||||
void unset_option(const char *option_name);
|
void unset_option(const char *option_name);
|
||||||
@ -55,12 +56,15 @@ public:
|
|||||||
inline Named_value get_option(int idx) const;
|
inline Named_value get_option(int idx) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int init(const LEX_STRING *instance_name_arg);
|
bool init(const LEX_STRING *instance_name_arg);
|
||||||
pid_t get_pid();
|
pid_t load_pid();
|
||||||
int get_pid_filename(char *result);
|
int get_pid_filename(char *result);
|
||||||
int unlink_pidfile();
|
int unlink_pidfile();
|
||||||
void print_argv();
|
void print_argv();
|
||||||
|
|
||||||
|
uint get_shutdown_delay() const;
|
||||||
|
int get_mysqld_port() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
We need this value to be greater or equal then FN_REFLEN found in
|
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_socket;
|
||||||
const char *mysqld_datadir;
|
const char *mysqld_datadir;
|
||||||
const char *mysqld_pid_file;
|
const char *mysqld_pid_file;
|
||||||
const char *mysqld_port;
|
|
||||||
uint mysqld_port_val;
|
|
||||||
LEX_STRING instance_name;
|
LEX_STRING instance_name;
|
||||||
LEX_STRING mysqld_path;
|
LEX_STRING mysqld_path;
|
||||||
LEX_STRING mysqld_real_path;
|
LEX_STRING mysqld_real_path;
|
||||||
const char *nonguarded;
|
const char *nonguarded;
|
||||||
const char *shutdown_delay;
|
|
||||||
uint shutdown_delay_val;
|
|
||||||
/* log enums are defined in parse.h */
|
/* log enums are defined in parse.h */
|
||||||
char *logs[3];
|
char *logs[3];
|
||||||
|
|
||||||
@ -102,6 +102,11 @@ private:
|
|||||||
int find_option(const char *option_name);
|
int find_option(const char *option_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const char *mysqld_port;
|
||||||
|
uint mysqld_port_val;
|
||||||
|
const char *shutdown_delay;
|
||||||
|
uint shutdown_delay_val;
|
||||||
|
|
||||||
uint filled_default_options;
|
uint filled_default_options;
|
||||||
MEM_ROOT alloc;
|
MEM_ROOT alloc;
|
||||||
|
|
||||||
|
@ -85,14 +85,7 @@ void Listener::run()
|
|||||||
log_info("Listener: started.");
|
log_info("Listener: started.");
|
||||||
|
|
||||||
#ifndef __WIN__
|
#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;
|
struct sockaddr_un unix_socket_address;
|
||||||
/* set global variable */
|
|
||||||
linuxthreads= (thread_pid != manager_pid);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
thread_registry->register_thread(&thread_info);
|
thread_registry->register_thread(&thread_info);
|
||||||
@ -151,10 +144,12 @@ void Listener::run()
|
|||||||
{
|
{
|
||||||
set_no_inherit(client_fd);
|
set_no_inherit(client_fd);
|
||||||
|
|
||||||
Vio *vio= vio_new(client_fd, socket_index == 0 ?
|
struct st_vio *vio=
|
||||||
VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
vio_new(client_fd,
|
||||||
socket_index == 0 ? 1 : 0);
|
socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
|
||||||
if (vio != 0)
|
socket_index == 0 ? 1 : 0);
|
||||||
|
|
||||||
|
if (vio != NULL)
|
||||||
handle_new_mysql_connection(vio);
|
handle_new_mysql_connection(vio);
|
||||||
else
|
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
|
Create new mysql connection. Created thread is responsible for deletion of
|
||||||
the Mysql_connection_thread_args and Vio instances passed to it.
|
the Mysql_connection and Vio instances passed to it.
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
handle_new_mysql_connection()
|
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=
|
Mysql_connection *mysql_connection=
|
||||||
new Mysql_connection(thread_registry, user_map,
|
new Mysql_connection(thread_registry, user_map,
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Format log entry and write it to the given stream.
|
Format log entry and write it to the given stream.
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
log()
|
log()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -93,17 +93,17 @@ int my_sigwait(const sigset_t *set, int *sig)
|
|||||||
#endif
|
#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,
|
Let guardian thread know that it should break it's processing cycle,
|
||||||
once it wakes up.
|
once it wakes up.
|
||||||
*/
|
*/
|
||||||
guardian->request_shutdown();
|
p_guardian->request_shutdown();
|
||||||
/* wake guardian */
|
/* wake guardian */
|
||||||
pthread_cond_signal(&guardian->COND_guardian);
|
pthread_cond_signal(&p_guardian->COND_guardian);
|
||||||
/* stop all threads */
|
/* 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;
|
Guardian *Manager::p_guardian;
|
||||||
Instance_map *Manager::p_instance_map;
|
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
|
manager - entry point to the main instance manager process: start
|
||||||
@ -137,8 +140,7 @@ int Manager::main()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
User_map user_map;
|
User_map user_map;
|
||||||
Instance_map instance_map(Options::Main::default_mysqld_path,
|
Instance_map instance_map;
|
||||||
thread_registry);
|
|
||||||
Guardian guardian(&thread_registry, &instance_map,
|
Guardian guardian(&thread_registry, &instance_map,
|
||||||
Options::Main::monitoring_interval);
|
Options::Main::monitoring_interval);
|
||||||
|
|
||||||
@ -147,6 +149,8 @@ int Manager::main()
|
|||||||
manager_pid= getpid();
|
manager_pid= getpid();
|
||||||
p_instance_map= &instance_map;
|
p_instance_map= &instance_map;
|
||||||
p_guardian= instance_map.guardian= &guardian;
|
p_guardian= instance_map.guardian= &guardian;
|
||||||
|
p_thread_registry= &thread_registry;
|
||||||
|
p_user_map= &user_map;
|
||||||
|
|
||||||
/* Initialize instance map. */
|
/* Initialize instance map. */
|
||||||
|
|
||||||
@ -199,14 +203,11 @@ int Manager::main()
|
|||||||
NOTE: To work nicely with LinuxThreads, the signal thread is the first
|
NOTE: To work nicely with LinuxThreads, the signal thread is the first
|
||||||
thread in the process.
|
thread in the process.
|
||||||
|
|
||||||
NOTE:
|
NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
|
||||||
After init_thr_alarm() call it's possible to call thr_alarm() (from
|
(from different threads), that results in sending ALARM signal to the
|
||||||
different threads), that results in sending ALARM signal to the alarm
|
alarm thread (which can be the main thread). That signal can interrupt
|
||||||
thread (which can be the main thread). That signal can interrupt
|
blocking calls. In other words, a blocking call can be interrupted in
|
||||||
blocking calls.
|
the main thread after init_thr_alarm().
|
||||||
|
|
||||||
In other words, a blocking call can be interrupted in the main thread
|
|
||||||
after init_thr_alarm().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
@ -230,11 +231,12 @@ int Manager::main()
|
|||||||
*/
|
*/
|
||||||
if (guardian.start_detached())
|
if (guardian.start_detached())
|
||||||
{
|
{
|
||||||
log_error("manager(): Failed to create the guardian thread");
|
log_error("Error: can not start Guardian thread.");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load instances. */
|
/* Load instances. */
|
||||||
|
|
||||||
{
|
{
|
||||||
instance_map.guardian->lock();
|
instance_map.guardian->lock();
|
||||||
instance_map.lock();
|
instance_map.lock();
|
||||||
@ -246,19 +248,18 @@ int Manager::main()
|
|||||||
|
|
||||||
if (flush_instances_status)
|
if (flush_instances_status)
|
||||||
{
|
{
|
||||||
log_error("Cannot init instances repository. This might be caused by "
|
log_error("Error: can not init instances repository.");
|
||||||
"the wrong config file options. For instance, missing mysqld "
|
stop_all_threads();
|
||||||
"binary. Aborting.");
|
|
||||||
stop_all(&guardian, &thread_registry);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start the listener */
|
/* Initialize the Listener. */
|
||||||
|
|
||||||
if (listener.start_detached())
|
if (listener.start_detached())
|
||||||
{
|
{
|
||||||
log_error("manager(): set_stacksize_n_create_thread(listener) failed");
|
log_error("Error: can not start Listener thread.");
|
||||||
stop_all(&guardian, &thread_registry);
|
stop_all_threads();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +269,9 @@ int Manager::main()
|
|||||||
*/
|
*/
|
||||||
pthread_cond_signal(&guardian.COND_guardian);
|
pthread_cond_signal(&guardian.COND_guardian);
|
||||||
|
|
||||||
log_info("Main loop: started.");
|
/* Main loop. */
|
||||||
|
|
||||||
|
log_info("Manager: started.");
|
||||||
|
|
||||||
while (!shutdown_complete)
|
while (!shutdown_complete)
|
||||||
{
|
{
|
||||||
@ -277,8 +280,8 @@ int Manager::main()
|
|||||||
|
|
||||||
if ((status= my_sigwait(&mask, &signo)) != 0)
|
if ((status= my_sigwait(&mask, &signo)) != 0)
|
||||||
{
|
{
|
||||||
log_error("sigwait() failed");
|
log_error("Error: sigwait() failed");
|
||||||
stop_all(&guardian, &thread_registry);
|
stop_all_threads();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +307,7 @@ int Manager::main()
|
|||||||
Bug #14164 IM tests fail on MacOS X (powermacg5)
|
Bug #14164 IM tests fail on MacOS X (powermacg5)
|
||||||
*/
|
*/
|
||||||
#ifdef IGNORE_SIGHUP_SIGQUIT
|
#ifdef IGNORE_SIGHUP_SIGQUIT
|
||||||
if ( SIGHUP == signo )
|
if (SIGHUP == signo)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
if (THR_SERVER_ALARM == signo)
|
if (THR_SERVER_ALARM == signo)
|
||||||
@ -312,7 +315,7 @@ int Manager::main()
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
log_info("Main loop: got shutdown signal.");
|
log_info("Manager: got shutdown signal.");
|
||||||
|
|
||||||
if (!guardian.is_stopped())
|
if (!guardian.is_stopped())
|
||||||
{
|
{
|
||||||
@ -327,7 +330,7 @@ int Manager::main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("Main loop: finished.");
|
log_info("Manager: finished.");
|
||||||
|
|
||||||
rc= 0;
|
rc= 0;
|
||||||
|
|
||||||
|
@ -19,9 +19,12 @@
|
|||||||
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
|
#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
|
||||||
#pragma interface
|
#pragma interface
|
||||||
#endif
|
#endif
|
||||||
|
#include <my_global.h>
|
||||||
|
|
||||||
class Guardian;
|
class Guardian;
|
||||||
class Instance_map;
|
class Instance_map;
|
||||||
|
class Thread_registry;
|
||||||
|
class User_map;
|
||||||
|
|
||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
@ -33,12 +36,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
static Instance_map *get_instance_map() { return p_instance_map; }
|
static Instance_map *get_instance_map() { return p_instance_map; }
|
||||||
static Guardian *get_guardian() { return p_guardian; }
|
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:
|
private:
|
||||||
static int manager_impl();
|
static void stop_all_threads();
|
||||||
private:
|
private:
|
||||||
|
static pid_t manager_pid;
|
||||||
static Guardian *p_guardian;
|
static Guardian *p_guardian;
|
||||||
static Instance_map *p_instance_map;
|
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
|
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
|
||||||
|
@ -71,6 +71,7 @@ static void daemonize(const char *log_file_name);
|
|||||||
static void angel();
|
static void angel();
|
||||||
static struct passwd *check_user(const char *user);
|
static struct passwd *check_user(const char *user);
|
||||||
static int set_user(const char *user, struct passwd *user_info);
|
static int set_user(const char *user, struct passwd *user_info);
|
||||||
|
static bool check_if_linuxthreads();
|
||||||
#endif
|
#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)
|
if (Options::Daemon::run_as_service)
|
||||||
{
|
{
|
||||||
/* forks, and returns only in child */
|
/* forks, and returns only in child */
|
||||||
@ -232,7 +236,7 @@ static void init_environment(char *progname)
|
|||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
/*
|
/*
|
||||||
Become a UNIX service
|
Become a UNIX service
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
daemonize()
|
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
|
#endif
|
||||||
|
@ -43,7 +43,7 @@ void trim_space(const char **text, uint *word_len)
|
|||||||
/*
|
/*
|
||||||
Parse output of the given command
|
Parse output of the given command
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
parse_output_and_get_value()
|
parse_output_and_get_value()
|
||||||
|
|
||||||
command the command to execue with popen.
|
command the command to execue with popen.
|
||||||
|
@ -22,14 +22,13 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
#ifndef __WIN__
|
||||||
pid_t manager_pid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This flag is set if mysqlmanager has detected that it is running on the
|
This flag is set if mysqlmanager has detected that it is running on the
|
||||||
system using LinuxThreads
|
system using LinuxThreads
|
||||||
*/
|
*/
|
||||||
bool linuxthreads;
|
bool linuxthreads;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following string must be less then 80 characters, as
|
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;
|
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__
|
#ifndef __WIN__
|
||||||
/*
|
/*
|
||||||
This flag is set if mysqlmanager has detected that it is running on the
|
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.
|
This function must not be used in user-management command implementations.
|
||||||
Use get_user_name() instead.
|
Use get_user_name() instead.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
get_user_name_impl()
|
get_user_name_impl()
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
@ -58,7 +58,7 @@ static char *get_user_name_impl()
|
|||||||
(not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
|
(not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
|
||||||
wrong.
|
wrong.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
get_user_name()
|
get_user_name()
|
||||||
user_name [OUT] on success contains 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
|
The password is retrieved from command-line options (if specified) or from
|
||||||
console.
|
console.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
get_password()
|
get_password()
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
@ -131,7 +131,7 @@ static const char *get_password()
|
|||||||
/*
|
/*
|
||||||
Load password file into user map.
|
Load password file into user map.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
load_password_file()
|
load_password_file()
|
||||||
user_map target user map
|
user_map target user map
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ static int load_password_file(User_map *user_map)
|
|||||||
/*
|
/*
|
||||||
Save user map into password file.
|
Save user map into password file.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
save_password_file()
|
save_password_file()
|
||||||
user_map user map
|
user_map user map
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
Executes user-management command.
|
Executes user-management command.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
execute()
|
execute()
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
|
@ -159,7 +159,7 @@ User_map::~User_map()
|
|||||||
/*
|
/*
|
||||||
Load password database.
|
Load password database.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSIS
|
||||||
load()
|
load()
|
||||||
password_file_name [IN] password file path
|
password_file_name [IN] password file path
|
||||||
err_msg [OUT] error message
|
err_msg [OUT] error message
|
||||||
|
Reference in New Issue
Block a user