mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
initial import of Windows port of IM.
This commit is contained in:
73
server-tools/instance-manager/IMService.cpp
Executable file
73
server-tools/instance-manager/IMService.cpp
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "IMService.h"
|
||||||
|
|
||||||
|
IMService::IMService(void)
|
||||||
|
{
|
||||||
|
serviceName = "MySqlManager";
|
||||||
|
displayName = "MySQL Manager";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMService::~IMService(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMService::Stop()
|
||||||
|
{
|
||||||
|
ReportStatus(SERVICE_STOP_PENDING);
|
||||||
|
// stop the IM work
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMService::Run()
|
||||||
|
{
|
||||||
|
// report to the SCM that we're about to start
|
||||||
|
ReportStatus((DWORD)SERVICE_START_PENDING);
|
||||||
|
|
||||||
|
// init goes here
|
||||||
|
|
||||||
|
ReportStatus((DWORD)SERVICE_RUNNING);
|
||||||
|
|
||||||
|
// wait for main loop to terminate
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMService::Log(const char *msg)
|
||||||
|
{
|
||||||
|
log_info(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int HandleServiceOptions(Options options)
|
||||||
|
{
|
||||||
|
int ret_val = 0;
|
||||||
|
|
||||||
|
IMService winService;
|
||||||
|
|
||||||
|
if (options.install_as_service)
|
||||||
|
{
|
||||||
|
if (winService.IsInstalled())
|
||||||
|
log_info("Service is already installed\n");
|
||||||
|
else if (winService.Install())
|
||||||
|
log_info("Service installed successfully\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_info("Service failed to install\n");
|
||||||
|
ret_val = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (options.remove_service)
|
||||||
|
{
|
||||||
|
if (! winService.IsInstalled())
|
||||||
|
log_info("Service is not installed\n");
|
||||||
|
else if (winService.Remove())
|
||||||
|
log_info("Service removed successfully\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_info("Service failed to remove\n");
|
||||||
|
ret_val = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (int)winService.Init();
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
14
server-tools/instance-manager/IMService.h
Executable file
14
server-tools/instance-manager/IMService.h
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "windowsservice.h"
|
||||||
|
|
||||||
|
class IMService : public WindowsService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMService(void);
|
||||||
|
~IMService(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Log(const char *msg);
|
||||||
|
void Stop();
|
||||||
|
void Run();
|
||||||
|
};
|
200
server-tools/instance-manager/WindowsService.cpp
Executable file
200
server-tools/instance-manager/WindowsService.cpp
Executable file
@ -0,0 +1,200 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include ".\windowsservice.h"
|
||||||
|
|
||||||
|
static WindowsService *gService;
|
||||||
|
|
||||||
|
WindowsService::WindowsService(void)
|
||||||
|
: statusCheckpoint(0), serviceName(NULL), inited(false),
|
||||||
|
dwAcceptedControls(SERVICE_ACCEPT_STOP)
|
||||||
|
{
|
||||||
|
gService = this;
|
||||||
|
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
status.dwServiceSpecificExitCode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsService::~WindowsService(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Install()
|
||||||
|
{
|
||||||
|
bool ret_val=false;
|
||||||
|
SC_HANDLE newService;
|
||||||
|
SC_HANDLE scm;
|
||||||
|
|
||||||
|
if (IsInstalled()) return true;
|
||||||
|
|
||||||
|
// determine the name of the currently executing file
|
||||||
|
char szFilePath[_MAX_PATH];
|
||||||
|
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
|
||||||
|
|
||||||
|
// open a connection to the SCM
|
||||||
|
if (!(scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newService = CreateService(scm, serviceName, displayName,
|
||||||
|
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
|
||||||
|
SERVICE_ERROR_NORMAL, szFilePath,
|
||||||
|
NULL, NULL, NULL, username, password);
|
||||||
|
|
||||||
|
if (newService)
|
||||||
|
{
|
||||||
|
CloseServiceHandle(newService);
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Init()
|
||||||
|
{
|
||||||
|
assert(serviceName != NULL);
|
||||||
|
|
||||||
|
if (inited) return true;
|
||||||
|
|
||||||
|
SERVICE_TABLE_ENTRY stb[] =
|
||||||
|
{
|
||||||
|
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
inited = true;
|
||||||
|
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Remove()
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
|
||||||
|
if (! IsInstalled())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// open a connection to the SCM
|
||||||
|
SC_HANDLE scm = OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
|
||||||
|
if (! scm)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SC_HANDLE service = OpenService(scm, serviceName, DELETE);
|
||||||
|
if (service)
|
||||||
|
{
|
||||||
|
if (DeleteService(service))
|
||||||
|
ret_val = true;
|
||||||
|
DWORD dw = ::GetLastError();
|
||||||
|
CloseServiceHandle(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::IsInstalled()
|
||||||
|
{
|
||||||
|
BOOL ret_val = FALSE;
|
||||||
|
|
||||||
|
SC_HANDLE scm = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||||
|
SC_HANDLE serv_handle = ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
|
||||||
|
|
||||||
|
ret_val = serv_handle != NULL;
|
||||||
|
|
||||||
|
::CloseServiceHandle(serv_handle);
|
||||||
|
::CloseServiceHandle(scm);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::SetAcceptedControls(DWORD acceptedControls)
|
||||||
|
{
|
||||||
|
dwAcceptedControls = acceptedControls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint, DWORD dwError)
|
||||||
|
{
|
||||||
|
if(debugging) return TRUE;
|
||||||
|
|
||||||
|
if(currentState == SERVICE_START_PENDING)
|
||||||
|
status.dwControlsAccepted = 0;
|
||||||
|
else
|
||||||
|
status.dwControlsAccepted = dwAcceptedControls;
|
||||||
|
|
||||||
|
status.dwCurrentState = currentState;
|
||||||
|
status.dwWin32ExitCode = dwError != 0 ? ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
|
||||||
|
status.dwWaitHint = waitHint;
|
||||||
|
status.dwServiceSpecificExitCode = dwError;
|
||||||
|
|
||||||
|
if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
|
||||||
|
{
|
||||||
|
status.dwCheckPoint = 0;
|
||||||
|
statusCheckpoint = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status.dwCheckPoint = ++statusCheckpoint;
|
||||||
|
|
||||||
|
// Report the status of the service to the service control manager.
|
||||||
|
BOOL result = SetServiceStatus(statusHandle, &status);
|
||||||
|
if (!result)
|
||||||
|
Log("ReportStatus failed");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
|
||||||
|
{
|
||||||
|
statusHandle = ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
|
||||||
|
if (statusHandle && ReportStatus(SERVICE_START_PENDING))
|
||||||
|
Run();
|
||||||
|
ReportStatus(SERVICE_STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::HandleControlCode(DWORD opcode)
|
||||||
|
{
|
||||||
|
// Handle the requested control code.
|
||||||
|
switch(opcode)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
// Stop the service.
|
||||||
|
status.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
|
Stop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_PAUSE:
|
||||||
|
status.dwCurrentState = SERVICE_PAUSE_PENDING;
|
||||||
|
Pause();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_CONTINUE:
|
||||||
|
status.dwCurrentState = SERVICE_CONTINUE_PENDING;
|
||||||
|
Continue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
Shutdown();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_INTERROGATE:
|
||||||
|
ReportStatus(status.dwCurrentState);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// invalid control code
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
|
||||||
|
{
|
||||||
|
assert(gService != NULL);
|
||||||
|
|
||||||
|
// register our service control handler:
|
||||||
|
gService->RegisterAndRun(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI WindowsService::ControlHandler(DWORD opcode)
|
||||||
|
{
|
||||||
|
assert(gService != NULL);
|
||||||
|
|
||||||
|
return gService->HandleControlCode(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
44
server-tools/instance-manager/WindowsService.h
Executable file
44
server-tools/instance-manager/WindowsService.h
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class WindowsService
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool inited;
|
||||||
|
const char *serviceName;
|
||||||
|
const char *displayName;
|
||||||
|
const char *username;
|
||||||
|
const char *password;
|
||||||
|
SERVICE_STATUS_HANDLE statusHandle;
|
||||||
|
DWORD statusCheckpoint;
|
||||||
|
SERVICE_STATUS status;
|
||||||
|
DWORD dwAcceptedControls;
|
||||||
|
bool debugging;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WindowsService(void);
|
||||||
|
~WindowsService(void);
|
||||||
|
|
||||||
|
BOOL Install();
|
||||||
|
BOOL Remove();
|
||||||
|
BOOL Init();
|
||||||
|
BOOL IsInstalled();
|
||||||
|
void SetAcceptedControls(DWORD acceptedControls);
|
||||||
|
void Debug(bool debugFlag) { debugging = debugFlag; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void WINAPI ServiceMain(DWORD argc, LPTSTR * argv);
|
||||||
|
static void WINAPI ControlHandler(DWORD CtrlType);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void Run() = 0;
|
||||||
|
virtual void Stop() {}
|
||||||
|
virtual void Shutdown() {}
|
||||||
|
virtual void Pause() {}
|
||||||
|
virtual void Continue() {}
|
||||||
|
virtual void Log(const char *msg) {}
|
||||||
|
|
||||||
|
BOOL ReportStatus(DWORD currentStatus, DWORD waitHint=3000, DWORD dwError=0);
|
||||||
|
void HandleControlCode(DWORD opcode);
|
||||||
|
void RegisterAndRun(DWORD argc, LPTSTR *argv);
|
||||||
|
};
|
||||||
|
|
@ -22,6 +22,7 @@
|
|||||||
#include "mysql_manager_error.h"
|
#include "mysql_manager_error.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
@ -469,7 +470,7 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
|
|||||||
size_t buff_size;
|
size_t buff_size;
|
||||||
int read_len;
|
int read_len;
|
||||||
/* calculate buffer size */
|
/* calculate buffer size */
|
||||||
struct stat file_stat;
|
MY_STAT file_stat;
|
||||||
|
|
||||||
/* my_fstat doesn't use the flag parameter */
|
/* my_fstat doesn't use the flag parameter */
|
||||||
if (my_fstat(fd, &file_stat, MYF(0)))
|
if (my_fstat(fd, &file_stat, MYF(0)))
|
||||||
@ -481,7 +482,7 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
|
|||||||
read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
|
read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
|
||||||
|
|
||||||
char *bf= (char*) malloc(sizeof(char)*buff_size);
|
char *bf= (char*) malloc(sizeof(char)*buff_size);
|
||||||
if ((read_len= my_read(fd, bf, buff_size, MYF(0))) < 0)
|
if ((read_len= my_read(fd, (byte*)bf, buff_size, MYF(0))) < 0)
|
||||||
return ER_READ_FILE;
|
return ER_READ_FILE;
|
||||||
store_to_protocol_packet(&send_buff, (char*) bf, &position, read_len);
|
store_to_protocol_packet(&send_buff, (char*) bf, &position, read_len);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -604,7 +605,7 @@ int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
|
|||||||
store_to_protocol_packet(&send_buff, "", &position);
|
store_to_protocol_packet(&send_buff, "", &position);
|
||||||
store_to_protocol_packet(&send_buff, (char*) "0", &position);
|
store_to_protocol_packet(&send_buff, (char*) "0", &position);
|
||||||
}
|
}
|
||||||
else if (S_ISREG(file_stat.st_mode))
|
else if (MY_S_ISREG(file_stat.st_mode))
|
||||||
{
|
{
|
||||||
store_to_protocol_packet(&send_buff,
|
store_to_protocol_packet(&send_buff,
|
||||||
(char*) log_files->value,
|
(char*) log_files->value,
|
||||||
@ -689,7 +690,7 @@ int Set_option::correct_file(int skip)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error= modify_defaults_file("/etc/my.cnf", option,
|
error= modify_defaults_file(Options::config_file, option,
|
||||||
option_value, instance_name, skip);
|
option_value, instance_name, skip);
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
return ER_OUT_OF_RESOURCES;
|
return ER_OUT_OF_RESOURCES;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
#include "mysql_manager_error.h"
|
#include "mysql_manager_error.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -32,7 +33,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
|
|
||||||
pthread_handler_decl(guardian, arg)
|
pthread_handler_decl(guardian, arg)
|
||||||
@ -426,11 +426,21 @@ int Guardian_thread::stop_instances(bool stop_instances_arg)
|
|||||||
|
|
||||||
int Guardian_thread::lock()
|
int Guardian_thread::lock()
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
pthread_mutex_lock(&LOCK_guardian);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
return pthread_mutex_lock(&LOCK_guardian);
|
return pthread_mutex_lock(&LOCK_guardian);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Guardian_thread::unlock()
|
int Guardian_thread::unlock()
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
pthread_mutex_unlock(&LOCK_guardian);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
return pthread_mutex_unlock(&LOCK_guardian);
|
return pthread_mutex_unlock(&LOCK_guardian);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,19 @@
|
|||||||
#pragma implementation
|
#pragma implementation
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
#include <process.h>
|
||||||
|
#endif
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
|
||||||
#include "mysql_manager_error.h"
|
#include "mysql_manager_error.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "instance_map.h"
|
#include "instance_map.h"
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
#include "port.h"
|
||||||
|
#ifndef __WIN__
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
@ -50,6 +55,16 @@ pthread_handler_decl(proxy, arg)
|
|||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
|
|
||||||
|
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 %i, this might be \
|
||||||
|
since IM lacks permmissions or hasn't found the pidifle",
|
||||||
|
options.instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The method starts an instance.
|
The method starts an instance.
|
||||||
|
|
||||||
@ -65,8 +80,6 @@ C_MODE_END
|
|||||||
|
|
||||||
int Instance::start()
|
int Instance::start()
|
||||||
{
|
{
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
/* clear crash flag */
|
/* clear crash flag */
|
||||||
pthread_mutex_lock(&LOCK_instance);
|
pthread_mutex_lock(&LOCK_instance);
|
||||||
crashed= 0;
|
crashed= 0;
|
||||||
@ -75,11 +88,7 @@ int Instance::start()
|
|||||||
|
|
||||||
if (!is_running())
|
if (!is_running())
|
||||||
{
|
{
|
||||||
if ((pid= options.get_pid()) != 0) /* check the pidfile */
|
remove_pid();
|
||||||
if (options.unlink_pidfile()) /* remove stalled pidfile */
|
|
||||||
log_error("cannot remove pidfile for instance %i, this might be \
|
|
||||||
since IM lacks permmissions or hasn't found the pidifle",
|
|
||||||
options.instance_name);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
No need to monitor this thread in the Thread_registry, as all
|
No need to monitor this thread in the Thread_registry, as all
|
||||||
@ -107,20 +116,21 @@ int Instance::start()
|
|||||||
return ER_INSTANCE_ALREADY_STARTED;
|
return ER_INSTANCE_ALREADY_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
void Instance::fork_and_monitor()
|
int Instance::launch_and_wait()
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid = fork();
|
||||||
log_info("starting instance %s", options.instance_name);
|
|
||||||
switch (pid= fork()) {
|
switch (pid)
|
||||||
case 0:
|
{
|
||||||
execv(options.mysqld_path, options.argv);
|
case 0:
|
||||||
/* exec never returns */
|
execv(options.mysqld_path, options.argv);
|
||||||
exit(1);
|
/* exec never returns */
|
||||||
case -1:
|
exit(1);
|
||||||
log_info("cannot fork() to start instance %s", options.instance_name);
|
case -1:
|
||||||
return;
|
log_info("cannot fork() to start instance %s", options.instance_name);
|
||||||
default:
|
return -1;
|
||||||
|
default:
|
||||||
/*
|
/*
|
||||||
Here we wait for the child created. This process differs for systems
|
Here we wait for the child created. This process differs for systems
|
||||||
running LinuxThreads and POSIX Threads compliant systems. This is because
|
running LinuxThreads and POSIX Threads compliant systems. This is because
|
||||||
@ -141,22 +151,89 @@ void Instance::fork_and_monitor()
|
|||||||
wait(NULL); /* LinuxThreads were detected */
|
wait(NULL); /* LinuxThreads were detected */
|
||||||
else
|
else
|
||||||
waitpid(pid, NULL, 0);
|
waitpid(pid, NULL, 0);
|
||||||
/* set instance state to crashed */
|
|
||||||
pthread_mutex_lock(&LOCK_instance);
|
|
||||||
crashed= 1;
|
|
||||||
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);
|
|
||||||
/* thread exits */
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int Instance::launch_and_wait()
|
||||||
|
{
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
ZeroMemory( &si, sizeof(si) );
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
ZeroMemory( &pi, sizeof(pi) );
|
||||||
|
|
||||||
|
int cmdlen = 0;
|
||||||
|
for (int i=1; options.argv[i] != 0; i++)
|
||||||
|
cmdlen += strlen(options.argv[i]) + 1;
|
||||||
|
cmdlen++; // we have to add a single space for CreateProcess (read the docs)
|
||||||
|
|
||||||
|
char *cmdline = NULL;
|
||||||
|
if (cmdlen > 0)
|
||||||
|
{
|
||||||
|
cmdline = new char[cmdlen];
|
||||||
|
cmdline[0] = 0;
|
||||||
|
for (int i=1; options.argv[i] != 0; i++)
|
||||||
|
{
|
||||||
|
strcat(cmdline, " ");
|
||||||
|
strcat(cmdline, options.argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the child process.
|
||||||
|
BOOL result = CreateProcess(options.mysqld_path, // file to execute
|
||||||
|
cmdline, // Command line.
|
||||||
|
NULL, // Process handle not inheritable.
|
||||||
|
NULL, // Thread handle not inheritable.
|
||||||
|
FALSE, // Set handle inheritance to FALSE.
|
||||||
|
0, // No creation flags.
|
||||||
|
NULL, // Use parent's environment block.
|
||||||
|
NULL, // Use parent's starting directory.
|
||||||
|
&si, // Pointer to STARTUPINFO structure.
|
||||||
|
&pi ); // Pointer to PROCESS_INFORMATION structure.
|
||||||
|
delete cmdline;
|
||||||
|
if (! result)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Wait until child process exits.
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
DWORD exitcode;
|
||||||
|
::GetExitCodeProcess(pi.hProcess, &exitcode);
|
||||||
|
|
||||||
|
// Close process and thread handles.
|
||||||
|
CloseHandle( pi.hProcess );
|
||||||
|
CloseHandle( pi.hThread );
|
||||||
|
|
||||||
|
return exitcode;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void Instance::fork_and_monitor()
|
||||||
|
{
|
||||||
|
log_info("starting instance %s", options.instance_name);
|
||||||
|
|
||||||
|
int result = launch_and_wait();
|
||||||
|
if (result == -1) return;
|
||||||
|
|
||||||
|
/* set instance state to crashed */
|
||||||
|
pthread_mutex_lock(&LOCK_instance);
|
||||||
|
crashed= 1;
|
||||||
|
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);
|
||||||
|
/* thread exits */
|
||||||
|
return;
|
||||||
|
|
||||||
/* we should never end up here */
|
/* we should never end up here */
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
@ -253,7 +330,6 @@ bool Instance::is_running()
|
|||||||
|
|
||||||
int Instance::stop()
|
int Instance::stop()
|
||||||
{
|
{
|
||||||
pid_t pid;
|
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
uint waitchild= (uint) DEFAULT_SHUTDOWN_DELAY;
|
||||||
|
|
||||||
@ -290,6 +366,68 @@ err:
|
|||||||
return ER_STOP_INSTANCE;
|
return ER_STOP_INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
|
||||||
|
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
|
||||||
|
{
|
||||||
|
DWORD dwTID, dwCode, dwErr = 0;
|
||||||
|
HANDLE hProcessDup = INVALID_HANDLE_VALUE;
|
||||||
|
HANDLE hRT = NULL;
|
||||||
|
HINSTANCE hKernel = GetModuleHandle("Kernel32");
|
||||||
|
BOOL bSuccess = FALSE;
|
||||||
|
|
||||||
|
BOOL bDup = DuplicateHandle(GetCurrentProcess(),
|
||||||
|
hProcess, GetCurrentProcess(), &hProcessDup, PROCESS_ALL_ACCESS, FALSE, 0);
|
||||||
|
|
||||||
|
// Detect the special case where the process is
|
||||||
|
// already dead...
|
||||||
|
if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) &&
|
||||||
|
(dwCode == STILL_ACTIVE) )
|
||||||
|
{
|
||||||
|
FARPROC pfnExitProc;
|
||||||
|
|
||||||
|
pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
|
||||||
|
|
||||||
|
hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
|
||||||
|
(LPTHREAD_START_ROUTINE)pfnExitProc, (PVOID)uExitCode, 0, &dwTID);
|
||||||
|
|
||||||
|
if ( hRT == NULL )
|
||||||
|
dwErr = GetLastError();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwErr = ERROR_PROCESS_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( hRT )
|
||||||
|
{
|
||||||
|
// Must wait process to terminate to
|
||||||
|
// guarantee that it has exited...
|
||||||
|
WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(hRT);
|
||||||
|
bSuccess = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bDup )
|
||||||
|
CloseHandle(hProcessDup);
|
||||||
|
|
||||||
|
if ( !bSuccess )
|
||||||
|
SetLastError(dwErr);
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kill(pid_t pid, int signum)
|
||||||
|
{
|
||||||
|
HANDLE processhandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
|
if (signum == SIGTERM)
|
||||||
|
::SafeTerminateProcess(processhandle, 0);
|
||||||
|
else
|
||||||
|
::TerminateProcess(processhandle, -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Instance::kill_instance(int signum)
|
void Instance::kill_instance(int signum)
|
||||||
{
|
{
|
||||||
|
@ -61,6 +61,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
pthread_cond_t COND_instance_stopped;
|
pthread_cond_t COND_instance_stopped;
|
||||||
Instance_map *instance_map;
|
Instance_map *instance_map;
|
||||||
|
|
||||||
|
void remove_pid();
|
||||||
|
int launch_and_wait();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
#include "options.h"
|
||||||
|
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
#include <mysql_com.h>
|
#include <mysql_com.h>
|
||||||
@ -138,13 +139,23 @@ Instance_map::~Instance_map()
|
|||||||
|
|
||||||
int Instance_map::lock()
|
int Instance_map::lock()
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
pthread_mutex_lock(&LOCK_instance_map);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
return pthread_mutex_lock(&LOCK_instance_map);
|
return pthread_mutex_lock(&LOCK_instance_map);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Instance_map::unlock()
|
int Instance_map::unlock()
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
pthread_mutex_unlock(&LOCK_instance_map);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
return pthread_mutex_unlock(&LOCK_instance_map);
|
return pthread_mutex_unlock(&LOCK_instance_map);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -245,7 +256,7 @@ int Instance_map::load()
|
|||||||
else
|
else
|
||||||
argv_options[1]= '\0';
|
argv_options[1]= '\0';
|
||||||
|
|
||||||
if (my_search_option_files("my", &argc, (char ***) &argv, &args_used,
|
if (my_search_option_files(Options::config_file, &argc, (char ***) &argv, &args_used,
|
||||||
process_option, (void*) this) ||
|
process_option, (void*) this) ||
|
||||||
complete_initialization())
|
complete_initialization())
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma interface
|
#pragma interface
|
||||||
|
@ -19,11 +19,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "listener.h"
|
#include "listener.h"
|
||||||
|
#include "priv.h"
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
#include <violite.h>
|
#include <violite.h>
|
||||||
|
#ifndef __WIN__
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#endif
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "thread_registry.h"
|
#include "thread_registry.h"
|
||||||
@ -31,7 +33,7 @@
|
|||||||
#include "instance_map.h"
|
#include "instance_map.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "mysql_connection.h"
|
#include "mysql_connection.h"
|
||||||
#include "priv.h"
|
#include "port.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -47,10 +49,17 @@ public:
|
|||||||
private:
|
private:
|
||||||
ulong total_connection_count;
|
ulong total_connection_count;
|
||||||
Thread_info thread_info;
|
Thread_info thread_info;
|
||||||
|
|
||||||
|
int sockets[2];
|
||||||
|
int num_sockets;
|
||||||
|
fd_set read_fds;
|
||||||
private:
|
private:
|
||||||
void handle_new_mysql_connection(Vio *vio);
|
void handle_new_mysql_connection(Vio *vio);
|
||||||
|
int create_tcp_socket();
|
||||||
|
int create_unix_socket(struct sockaddr_un &unix_socket_address);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int LISTEN_BACK_LOG_SIZE = 5; // standard backlog size
|
||||||
|
|
||||||
Listener_thread::Listener_thread(const Listener_thread_args &args) :
|
Listener_thread::Listener_thread(const Listener_thread_args &args) :
|
||||||
Listener_thread_args(args.thread_registry, args.options, args.user_map,
|
Listener_thread_args(args.thread_registry, args.options, args.user_map,
|
||||||
@ -58,6 +67,7 @@ Listener_thread::Listener_thread(const Listener_thread_args &args) :
|
|||||||
,total_connection_count(0)
|
,total_connection_count(0)
|
||||||
,thread_info(pthread_self())
|
,thread_info(pthread_self())
|
||||||
{
|
{
|
||||||
|
num_sockets= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -78,30 +88,134 @@ Listener_thread::~Listener_thread()
|
|||||||
|
|
||||||
void Listener_thread::run()
|
void Listener_thread::run()
|
||||||
{
|
{
|
||||||
enum { LISTEN_BACK_LOG_SIZE = 5 }; // standard backlog size
|
|
||||||
int flags;
|
|
||||||
int arg= 1; /* value to be set by setsockopt */
|
|
||||||
int unix_socket;
|
|
||||||
uint im_port;
|
|
||||||
/* we use this var to check whether we are running on LinuxThreads */
|
/* we use this var to check whether we are running on LinuxThreads */
|
||||||
pid_t thread_pid;
|
pid_t thread_pid;
|
||||||
|
int n;
|
||||||
|
|
||||||
thread_pid= getpid();
|
thread_pid= getpid();
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
|
struct sockaddr_un unix_socket_address;
|
||||||
/* set global variable */
|
/* set global variable */
|
||||||
linuxthreads= (thread_pid != manager_pid);
|
linuxthreads= (thread_pid != manager_pid);
|
||||||
|
#endif
|
||||||
|
|
||||||
thread_registry.register_thread(&thread_info);
|
thread_registry.register_thread(&thread_info);
|
||||||
|
|
||||||
my_thread_init();
|
my_thread_init();
|
||||||
|
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
|
||||||
/* I. prepare 'listen' sockets */
|
/* I. prepare 'listen' sockets */
|
||||||
|
if (create_tcp_socket())
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
|
if (create_unix_socket(unix_socket_address))
|
||||||
|
goto err;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* II. Listen sockets and spawn childs */
|
||||||
|
for (int i=0; i < num_sockets; i++)
|
||||||
|
n = max(n, sockets[i]);
|
||||||
|
n++;
|
||||||
|
|
||||||
|
while (thread_registry.is_shutdown() == false)
|
||||||
|
{
|
||||||
|
fd_set read_fds_arg= read_fds;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When using valgrind 2.0 this syscall doesn't get kicked off by a
|
||||||
|
signal during shutdown. This results in failing assert
|
||||||
|
(Thread_registry::~Thread_registry). Valgrind 2.2 works fine.
|
||||||
|
*/
|
||||||
|
int rc= select(n, &read_fds_arg, 0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
if (rc == -1 && errno != EINTR)
|
||||||
|
{
|
||||||
|
log_error("Listener_thread::run(): select() failed, %s",
|
||||||
|
strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int socket_index=0; socket_index < num_sockets; socket_index++)
|
||||||
|
{
|
||||||
|
/* Assuming that rc > 0 as we asked to wait forever */
|
||||||
|
if (FD_ISSET(sockets[socket_index], &read_fds_arg))
|
||||||
|
{
|
||||||
|
int client_fd= accept(sockets[socket_index], 0, 0);
|
||||||
|
/* accept may return -1 (failure or spurious wakeup) */
|
||||||
|
if (client_fd >= 0) // connection established
|
||||||
|
{
|
||||||
|
Vio *vio = vio_new(client_fd, socket_index==0?VIO_TYPE_SOCKET:VIO_TYPE_TCPIP,
|
||||||
|
socket_index==0?1:0);
|
||||||
|
if (vio != 0)
|
||||||
|
handle_new_mysql_connection(vio);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shutdown(client_fd, SHUT_RDWR);
|
||||||
|
close(client_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* III. Release all resources and exit */
|
||||||
|
|
||||||
|
log_info("Listener_thread::run(): shutdown requested, exiting...");
|
||||||
|
|
||||||
|
for (int i=0; i < num_sockets; i++)
|
||||||
|
close(sockets[i]);
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
|
unlink(unix_socket_address.sun_path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
thread_registry.unregister_thread(&thread_info);
|
||||||
|
my_thread_end();
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
thread_registry.unregister_thread(&thread_info);
|
||||||
|
thread_registry.request_shutdown();
|
||||||
|
my_thread_end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_non_blocking(int socket)
|
||||||
|
{
|
||||||
|
#ifndef __WIN__
|
||||||
|
int flags= fcntl(socket, F_GETFL, 0);
|
||||||
|
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
#else
|
||||||
|
u_long arg = 1;
|
||||||
|
ioctlsocket(socket, FIONBIO, &arg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_no_inherit(int socket)
|
||||||
|
{
|
||||||
|
#ifndef __WIN__
|
||||||
|
int flags= fcntl(socket, F_GETFD, 0);
|
||||||
|
fcntl(socket, F_SETFD, flags | FD_CLOEXEC);
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int Listener_thread::create_tcp_socket()
|
||||||
|
{
|
||||||
|
/* value to be set by setsockopt */
|
||||||
|
int arg= 1;
|
||||||
|
|
||||||
int ip_socket= socket(AF_INET, SOCK_STREAM, 0);
|
int ip_socket= socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (ip_socket == INVALID_SOCKET)
|
if (ip_socket == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
log_error("Listener_thead::run(): socket(AF_INET) failed, %s",
|
log_error("Listener_thead::run(): socket(AF_INET) failed, %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto err;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_in ip_socket_address;
|
struct sockaddr_in ip_socket_address;
|
||||||
@ -115,7 +229,7 @@ void Listener_thread::run()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
im_bind_addr= htonl(INADDR_ANY);
|
im_bind_addr= htonl(INADDR_ANY);
|
||||||
im_port= options.port_number;
|
uint im_port= options.port_number;
|
||||||
|
|
||||||
ip_socket_address.sin_family= AF_INET;
|
ip_socket_address.sin_family= AF_INET;
|
||||||
ip_socket_address.sin_addr.s_addr = im_bind_addr;
|
ip_socket_address.sin_addr.s_addr = im_bind_addr;
|
||||||
@ -130,154 +244,86 @@ void Listener_thread::run()
|
|||||||
{
|
{
|
||||||
log_error("Listener_thread::run(): bind(ip socket) failed, '%s'",
|
log_error("Listener_thread::run(): bind(ip socket) failed, '%s'",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto err;
|
close(ip_socket);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(ip_socket, LISTEN_BACK_LOG_SIZE))
|
if (listen(ip_socket, LISTEN_BACK_LOG_SIZE))
|
||||||
{
|
{
|
||||||
log_error("Listener_thread::run(): listen(ip socket) failed, %s",
|
log_error("Listener_thread::run(): listen(ip socket) failed, %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto err;
|
close(ip_socket);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
/* set the socket nonblocking */
|
|
||||||
flags= fcntl(ip_socket, F_GETFL, 0);
|
|
||||||
fcntl(ip_socket, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
/* make sure that instances won't be listening our sockets */
|
|
||||||
flags= fcntl(ip_socket, F_GETFD, 0);
|
|
||||||
fcntl(ip_socket, F_SETFD, flags | FD_CLOEXEC);
|
|
||||||
|
|
||||||
|
/* set the socket nonblocking */
|
||||||
|
set_non_blocking(ip_socket);
|
||||||
|
|
||||||
|
/* make sure that instances won't be listening our sockets */
|
||||||
|
set_no_inherit(ip_socket);
|
||||||
|
|
||||||
|
FD_SET(ip_socket, &read_fds);
|
||||||
|
sockets[num_sockets++] = ip_socket;
|
||||||
log_info("accepting connections on ip socket");
|
log_info("accepting connections on ip socket");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------*/
|
#ifndef __WIN__
|
||||||
unix_socket= socket(AF_UNIX, SOCK_STREAM, 0);
|
int Listener_thread::create_unix_socket(
|
||||||
|
struct sockaddr_un &unix_socket_address)
|
||||||
|
{
|
||||||
|
int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (unix_socket == INVALID_SOCKET)
|
if (unix_socket == INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s",
|
log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
goto err;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_un unix_socket_address;
|
|
||||||
bzero(&unix_socket_address, sizeof(unix_socket_address));
|
bzero(&unix_socket_address, sizeof(unix_socket_address));
|
||||||
|
|
||||||
unix_socket_address.sun_family= AF_UNIX;
|
unix_socket_address.sun_family= AF_UNIX;
|
||||||
strmake(unix_socket_address.sun_path, options.socket_file_name,
|
strmake(unix_socket_address.sun_path, options.socket_file_name,
|
||||||
sizeof(unix_socket_address.sun_path));
|
sizeof(unix_socket_address.sun_path));
|
||||||
unlink(unix_socket_address.sun_path); /* in case we have stale socket file */
|
unlink(unix_socket_address.sun_path); // in case we have stale socket file
|
||||||
|
|
||||||
|
/*
|
||||||
|
POSIX specifies default permissions for a pathname created by bind
|
||||||
|
to be 0777. We need everybody to have access to the socket.
|
||||||
|
*/
|
||||||
|
mode_t old_mask= umask(0);
|
||||||
|
if (bind(unix_socket, (struct sockaddr *) &unix_socket_address,
|
||||||
|
sizeof(unix_socket_address)))
|
||||||
{
|
{
|
||||||
/*
|
log_error("Listener_thread::run(): bind(unix socket) failed, "
|
||||||
POSIX specifies default permissions for a pathname created by bind
|
|
||||||
to be 0777. We need everybody to have access to the socket.
|
|
||||||
*/
|
|
||||||
mode_t old_mask= umask(0);
|
|
||||||
if (bind(unix_socket, (struct sockaddr *) &unix_socket_address,
|
|
||||||
sizeof(unix_socket_address)))
|
|
||||||
{
|
|
||||||
log_error("Listener_thread::run(): bind(unix socket) failed, "
|
|
||||||
"socket file name is '%s', error '%s'",
|
"socket file name is '%s', error '%s'",
|
||||||
unix_socket_address.sun_path, strerror(errno));
|
unix_socket_address.sun_path, strerror(errno));
|
||||||
goto err;
|
close(unix_socket);
|
||||||
}
|
return -1;
|
||||||
umask(old_mask);
|
|
||||||
|
|
||||||
if (listen(unix_socket, LISTEN_BACK_LOG_SIZE))
|
|
||||||
{
|
|
||||||
log_error("Listener_thread::run(): listen(unix socket) failed, %s",
|
|
||||||
strerror(errno));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the socket nonblocking */
|
|
||||||
flags= fcntl(unix_socket, F_GETFL, 0);
|
|
||||||
fcntl(unix_socket, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
/* make sure that instances won't be listening our sockets */
|
|
||||||
flags= fcntl(unix_socket, F_GETFD, 0);
|
|
||||||
fcntl(unix_socket, F_SETFD, flags | FD_CLOEXEC);
|
|
||||||
}
|
}
|
||||||
log_info("accepting connections on unix socket %s",
|
|
||||||
unix_socket_address.sun_path);
|
umask(old_mask);
|
||||||
|
|
||||||
/* II. Listen sockets and spawn childs */
|
if (listen(unix_socket, LISTEN_BACK_LOG_SIZE))
|
||||||
|
|
||||||
{
|
{
|
||||||
int n= max(unix_socket, ip_socket) + 1;
|
log_error("Listener_thread::run(): listen(unix socket) failed, %s",
|
||||||
fd_set read_fds;
|
strerror(errno));
|
||||||
|
close(unix_socket);
|
||||||
FD_ZERO(&read_fds);
|
return -1;
|
||||||
FD_SET(unix_socket, &read_fds);
|
|
||||||
FD_SET(ip_socket, &read_fds);
|
|
||||||
|
|
||||||
while (thread_registry.is_shutdown() == false)
|
|
||||||
{
|
|
||||||
fd_set read_fds_arg= read_fds;
|
|
||||||
|
|
||||||
/*
|
|
||||||
When using valgrind 2.0 this syscall doesn't get kicked off by a
|
|
||||||
signal during shutdown. This results in failing assert
|
|
||||||
(Thread_registry::~Thread_registry). Valgrind 2.2 works fine.
|
|
||||||
*/
|
|
||||||
int rc= select(n, &read_fds_arg, 0, 0, 0);
|
|
||||||
|
|
||||||
|
|
||||||
if (rc == -1 && errno != EINTR)
|
|
||||||
log_error("Listener_thread::run(): select() failed, %s",
|
|
||||||
strerror(errno));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Assuming that rc > 0 as we asked to wait forever */
|
|
||||||
if (FD_ISSET(unix_socket, &read_fds_arg))
|
|
||||||
{
|
|
||||||
int client_fd= accept(unix_socket, 0, 0);
|
|
||||||
/* accept may return -1 (failure or spurious wakeup) */
|
|
||||||
if (client_fd >= 0) // connection established
|
|
||||||
{
|
|
||||||
if (Vio *vio= vio_new(client_fd, VIO_TYPE_SOCKET, 1))
|
|
||||||
handle_new_mysql_connection(vio);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shutdown(client_fd, SHUT_RDWR);
|
|
||||||
close(client_fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (FD_ISSET(ip_socket, &read_fds_arg))
|
|
||||||
{
|
|
||||||
int client_fd= accept(ip_socket, 0, 0);
|
|
||||||
/* accept may return -1 (failure or spurious wakeup) */
|
|
||||||
if (client_fd >= 0) // connection established
|
|
||||||
{
|
|
||||||
if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0))
|
|
||||||
handle_new_mysql_connection(vio);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shutdown(client_fd, SHUT_RDWR);
|
|
||||||
close(client_fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* III. Release all resources and exit */
|
/* set the socket nonblocking */
|
||||||
|
set_non_blocking(unix_socket);
|
||||||
|
|
||||||
log_info("Listener_thread::run(): shutdown requested, exiting...");
|
/* make sure that instances won't be listening our sockets */
|
||||||
|
set_no_inherit(unix_socket);
|
||||||
|
|
||||||
close(unix_socket);
|
log_info("accepting connections on unix socket %s", unix_socket_address.sun_path);
|
||||||
close(ip_socket);
|
sockets[num_sockets++] = unix_socket;
|
||||||
unlink(unix_socket_address.sun_path);
|
FD_SET(unix_socket, &read_fds);
|
||||||
|
return 0;
|
||||||
thread_registry.unregister_thread(&thread_info);
|
|
||||||
my_thread_end();
|
|
||||||
return;
|
|
||||||
|
|
||||||
err:
|
|
||||||
thread_registry.unregister_thread(&thread_info);
|
|
||||||
thread_registry.request_shutdown();
|
|
||||||
my_thread_end();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,7 +31,7 @@ pthread_handler_decl(listener, arg);
|
|||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
class Thread_registry;
|
class Thread_registry;
|
||||||
class Options;
|
struct Options;
|
||||||
class User_map;
|
class User_map;
|
||||||
class Instance_map;
|
class Instance_map;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "port.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
|
@ -30,7 +30,9 @@
|
|||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <thr_alarm.h>
|
#include <thr_alarm.h>
|
||||||
|
#ifndef __WIN__
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int create_pid_file(const char *pid_file_name)
|
static int create_pid_file(const char *pid_file_name)
|
||||||
@ -50,6 +52,61 @@ static int create_pid_file(const char *pid_file_name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
|
void set_signals(sigset_t *mask)
|
||||||
|
{
|
||||||
|
/* block signals */
|
||||||
|
sigemptyset(mask);
|
||||||
|
sigaddset(mask, SIGINT);
|
||||||
|
sigaddset(mask, SIGTERM);
|
||||||
|
sigaddset(mask, SIGPIPE);
|
||||||
|
sigaddset(mask, SIGHUP);
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
/*
|
||||||
|
We want this signal to be blocked in all theads but the signal
|
||||||
|
one. It is needed for the thr_alarm subsystem to work.
|
||||||
|
*/
|
||||||
|
sigaddset(mask,THR_SERVER_ALARM);
|
||||||
|
|
||||||
|
/* all new threads will inherite this signal mask */
|
||||||
|
pthread_sigmask(SIG_BLOCK, mask, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
In our case the signal thread also implements functions of alarm thread.
|
||||||
|
Here we init alarm thread functionality. We suppose that we won't have
|
||||||
|
more then 10 alarms at the same time.
|
||||||
|
*/
|
||||||
|
init_thr_alarm(10);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool have_signal;
|
||||||
|
|
||||||
|
void onsignal(int signo)
|
||||||
|
{
|
||||||
|
have_signal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_signals(sigset_t *set)
|
||||||
|
{
|
||||||
|
signal(SIGINT, onsignal);
|
||||||
|
signal(SIGTERM, onsignal);
|
||||||
|
have_signal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_sigwait(const sigset_t *set, int *sig)
|
||||||
|
{
|
||||||
|
// MSG msg;
|
||||||
|
while (!have_signal)
|
||||||
|
{
|
||||||
|
Sleep(100);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
manager - entry point to the main instance manager process: start
|
manager - entry point to the main instance manager process: start
|
||||||
@ -98,21 +155,8 @@ void manager(const Options &options)
|
|||||||
if (create_pid_file(options.pid_file_name))
|
if (create_pid_file(options.pid_file_name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* block signals */
|
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
sigemptyset(&mask);
|
set_signals(&mask);
|
||||||
sigaddset(&mask, SIGINT);
|
|
||||||
sigaddset(&mask, SIGTERM);
|
|
||||||
sigaddset(&mask, SIGPIPE);
|
|
||||||
sigaddset(&mask, SIGHUP);
|
|
||||||
/*
|
|
||||||
We want this signal to be blocked in all theads but the signal
|
|
||||||
one. It is needed for the thr_alarm subsystem to work.
|
|
||||||
*/
|
|
||||||
sigaddset(&mask,THR_SERVER_ALARM);
|
|
||||||
|
|
||||||
/* all new threads will inherite this signal mask */
|
|
||||||
pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
|
||||||
|
|
||||||
/* create the listener */
|
/* create the listener */
|
||||||
{
|
{
|
||||||
@ -166,12 +210,7 @@ void manager(const Options &options)
|
|||||||
bool shutdown_complete;
|
bool shutdown_complete;
|
||||||
|
|
||||||
shutdown_complete= FALSE;
|
shutdown_complete= FALSE;
|
||||||
/*
|
|
||||||
In our case the signal thread also implements functions of alarm thread.
|
|
||||||
Here we init alarm thread functionality. We suppose that we won't have
|
|
||||||
more then 10 alarms at the same time.
|
|
||||||
*/
|
|
||||||
init_thr_alarm(10);
|
|
||||||
/* init list of guarded instances */
|
/* init list of guarded instances */
|
||||||
guardian_thread.lock();
|
guardian_thread.lock();
|
||||||
|
|
||||||
@ -185,8 +224,6 @@ void manager(const Options &options)
|
|||||||
*/
|
*/
|
||||||
pthread_cond_signal(&guardian_thread.COND_guardian);
|
pthread_cond_signal(&guardian_thread.COND_guardian);
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
while (!shutdown_complete)
|
while (!shutdown_complete)
|
||||||
{
|
{
|
||||||
int status= 0;
|
int status= 0;
|
||||||
@ -197,11 +234,11 @@ void manager(const Options &options)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (signo) {
|
#ifndef __WIN__
|
||||||
case THR_SERVER_ALARM:
|
if (THR_SERVER_ALARM == signo)
|
||||||
process_alarm(signo);
|
process_alarm(signo);
|
||||||
break;
|
else
|
||||||
default:
|
#endif
|
||||||
{
|
{
|
||||||
if (!guardian_thread.is_stopped())
|
if (!guardian_thread.is_stopped())
|
||||||
{
|
{
|
||||||
@ -215,16 +252,16 @@ void manager(const Options &options)
|
|||||||
shutdown_complete= TRUE;
|
shutdown_complete= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
/* delete the pid file */
|
/* delete the pid file */
|
||||||
my_delete(options.pid_file_name, MYF(0));
|
my_delete(options.pid_file_name, MYF(0));
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
/* free alarm structures */
|
/* free alarm structures */
|
||||||
end_thr_alarm(1);
|
end_thr_alarm(1);
|
||||||
/* don't pthread_exit to kill all threads who did not shut down in time */
|
/* don't pthread_exit to kill all threads who did not shut down in time */
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
class Options;
|
struct Options;
|
||||||
|
|
||||||
void manager(const Options &options);
|
void manager(const Options &options);
|
||||||
|
|
||||||
|
@ -23,12 +23,16 @@
|
|||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#ifndef __WIN__
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifdef __WIN__
|
||||||
|
#include "windowsservice.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Few notes about Instance Manager architecture:
|
Few notes about Instance Manager architecture:
|
||||||
@ -55,10 +59,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void init_environment(char *progname);
|
static void init_environment(char *progname);
|
||||||
|
#ifndef __WIN__
|
||||||
static void daemonize(const char *log_file_name);
|
static void daemonize(const char *log_file_name);
|
||||||
static void angel(const Options &options);
|
static void angel(const Options &options);
|
||||||
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);
|
||||||
|
#else
|
||||||
|
int HandleServiceOptions(Options options);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -78,6 +86,7 @@ int main(int argc, char *argv[])
|
|||||||
if (options.load(argc, argv))
|
if (options.load(argc, argv))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
if ((user_info= check_user(options.user)))
|
if ((user_info= check_user(options.user)))
|
||||||
{
|
{
|
||||||
if (set_user(options.user, user_info))
|
if (set_user(options.user, user_info))
|
||||||
@ -94,6 +103,12 @@ int main(int argc, char *argv[])
|
|||||||
/* forks again, and returns only in child: parent becomes angel */
|
/* forks again, and returns only in child: parent becomes angel */
|
||||||
angel(options);
|
angel(options);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#ifdef NDEBUG
|
||||||
|
return HandleServiceOptions(options);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
manager(options);
|
manager(options);
|
||||||
options.cleanup();
|
options.cleanup();
|
||||||
my_end(0);
|
my_end(0);
|
||||||
@ -105,11 +120,11 @@ err:
|
|||||||
|
|
||||||
/******************* Auxilary functions implementation **********************/
|
/******************* Auxilary functions implementation **********************/
|
||||||
|
|
||||||
|
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
||||||
/* Change to run as another user if started with --user */
|
/* Change to run as another user if started with --user */
|
||||||
|
|
||||||
static struct passwd *check_user(const char *user)
|
static struct passwd *check_user(const char *user)
|
||||||
{
|
{
|
||||||
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
|
||||||
struct passwd *user_info;
|
struct passwd *user_info;
|
||||||
uid_t user_id= geteuid();
|
uid_t user_id= geteuid();
|
||||||
|
|
||||||
@ -150,7 +165,6 @@ static struct passwd *check_user(const char *user)
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
log_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n", user);
|
log_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n", user);
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +186,7 @@ static int set_user(const char *user, struct passwd *user_info)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -188,6 +202,7 @@ static void init_environment(char *progname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
/*
|
/*
|
||||||
Become a UNIX service
|
Become a UNIX service
|
||||||
SYNOPSYS
|
SYNOPSYS
|
||||||
@ -342,3 +357,4 @@ spawn:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
295
server-tools/instance-manager/mysqlmanager.vcproj
Executable file
295
server-tools/instance-manager/mysqlmanager.vcproj
Executable file
@ -0,0 +1,295 @@
|
|||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="7.10"
|
||||||
|
Name="mysqlmanager"
|
||||||
|
ProjectGUID="{6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}"
|
||||||
|
Keyword="Win32Proj">
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"/>
|
||||||
|
</Platforms>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="Debug"
|
||||||
|
IntermediateDirectory="Debug"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="..\include"
|
||||||
|
PreprocessorDefinitions="MYSQL_INSTANCE_MANAGER;MYSQL_SERVER;_DEBUG;SAFEMALLOC;SAFE_MUTEX;_WINDOWS;CONSOLE"
|
||||||
|
MinimalRebuild="TRUE"
|
||||||
|
ExceptionHandling="FALSE"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="1"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="4"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wsock32.lib"
|
||||||
|
OutputFile="$(OutDir)/mysqlmanager.exe"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
ProgramDatabaseFile="$(OutDir)/mysqlmanager.pdb"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="Release"
|
||||||
|
IntermediateDirectory="Release"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="2">
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AdditionalIncludeDirectories="..\include"
|
||||||
|
PreprocessorDefinitions="MYSQL_INSTANCE_MANAGER;MYSQL_SERVER;_WINDOWS;CONSOLE"
|
||||||
|
ExceptionHandling="FALSE"
|
||||||
|
RuntimeLibrary="0"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
Detect64BitPortabilityProblems="TRUE"
|
||||||
|
DebugInformationFormat="3"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="wsock32.lib"
|
||||||
|
OutputFile="$(OutDir)/mysqlmanager.exe"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="TRUE"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebDeploymentTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedWrapperGeneratorTool"/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Source Files"
|
||||||
|
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\buffer.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\client.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\command.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\commands.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\factory.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\libmysql\get_password.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\guardian.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\IMService.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance_map.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance_options.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\listener.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\log.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\manager.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\messages.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\mini_client_errors.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mysql_connection.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mysqlmanager.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\net_serv.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\options.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\pack.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\parse.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\parse_output.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\password.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\priv.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\protocol.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\service_funcs.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sql\sql_state.c">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\thread_registry.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\user_map.cc">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\WindowsService.cpp">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Header Files"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||||
|
<File
|
||||||
|
RelativePath=".\buffer.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\command.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\commands.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\factory.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\guardian.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\IMService.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance_map.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\instance_options.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\listener.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\log.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\manager.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\messages.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mysql_connection.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\mysql_manager_error.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\options.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\parse.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\parse_output.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\port.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\priv.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\protocol.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\thread_registry.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\user_map.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\WindowsService.h">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
@ -21,7 +21,7 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
#include "port.h"
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <my_getopt.h>
|
#include <my_getopt.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
@ -30,19 +30,29 @@
|
|||||||
#define QUOTE2(x) #x
|
#define QUOTE2(x) #x
|
||||||
#define QUOTE(x) QUOTE2(x)
|
#define QUOTE(x) QUOTE2(x)
|
||||||
|
|
||||||
|
const char *default_password_file_name = QUOTE(DEFAULT_PASSWORD_FILE_NAME);
|
||||||
|
const char *default_log_file_name = QUOTE(DEFAULT_LOG_FILE_NAME);
|
||||||
|
char default_config_file[FN_REFLEN] = "/etc/my.cnf";
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
char Options::run_as_service;
|
char Options::run_as_service;
|
||||||
const char *Options::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
|
const char *Options::user= 0; /* No default value */
|
||||||
|
#else
|
||||||
|
char Options::install_as_service;
|
||||||
|
char Options::remove_service;
|
||||||
|
#endif
|
||||||
|
const char *Options::log_file_name= default_log_file_name;
|
||||||
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
|
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
|
||||||
const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
|
const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
|
||||||
const char *Options::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
|
const char *Options::password_file_name= default_password_file_name;
|
||||||
const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
|
const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
|
||||||
const char *Options::first_option= 0; /* No default value */
|
const char *Options::first_option= 0; /* No default value */
|
||||||
const char *Options::bind_address= 0; /* No default value */
|
const char *Options::bind_address= 0; /* No default value */
|
||||||
const char *Options::user= 0; /* No default value */
|
|
||||||
uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
|
uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
|
||||||
uint Options::port_number= DEFAULT_PORT;
|
uint Options::port_number= DEFAULT_PORT;
|
||||||
/* just to declare */
|
/* just to declare */
|
||||||
char **Options::saved_argv;
|
char **Options::saved_argv;
|
||||||
|
const char *Options::config_file = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
List of options, accepted by the instance manager.
|
List of options, accepted by the instance manager.
|
||||||
@ -55,8 +65,13 @@ enum options {
|
|||||||
OPT_SOCKET,
|
OPT_SOCKET,
|
||||||
OPT_PASSWORD_FILE,
|
OPT_PASSWORD_FILE,
|
||||||
OPT_MYSQLD_PATH,
|
OPT_MYSQLD_PATH,
|
||||||
|
#ifndef __WIN__
|
||||||
OPT_RUN_AS_SERVICE,
|
OPT_RUN_AS_SERVICE,
|
||||||
OPT_USER,
|
OPT_USER,
|
||||||
|
#else
|
||||||
|
OPT_INSTALL_SERVICE,
|
||||||
|
OPT_REMOVE_SERVICE,
|
||||||
|
#endif
|
||||||
OPT_MONITORING_INTERVAL,
|
OPT_MONITORING_INTERVAL,
|
||||||
OPT_PORT,
|
OPT_PORT,
|
||||||
OPT_BIND_ADDRESS
|
OPT_BIND_ADDRESS
|
||||||
@ -107,7 +122,14 @@ static struct my_option my_long_options[] =
|
|||||||
(gptr *) &Options::monitoring_interval,
|
(gptr *) &Options::monitoring_interval,
|
||||||
0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
|
0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
|
||||||
0, 0, 0, 0, 0 },
|
0, 0, 0, 0, 0 },
|
||||||
|
#ifdef __WIN__
|
||||||
|
{ "install", OPT_INSTALL_SERVICE, "Install as system service.",
|
||||||
|
(gptr *) &Options::install_as_service, (gptr*) &Options::install_as_service,
|
||||||
|
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
|
||||||
|
{ "remove", OPT_REMOVE_SERVICE, "Remove system service.",
|
||||||
|
(gptr *)&Options::remove_service, (gptr*) &Options::remove_service,
|
||||||
|
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
|
||||||
|
#else
|
||||||
{ "run-as-service", OPT_RUN_AS_SERVICE,
|
{ "run-as-service", OPT_RUN_AS_SERVICE,
|
||||||
"Daemonize and start angel process.", (gptr *) &Options::run_as_service,
|
"Daemonize and start angel process.", (gptr *) &Options::run_as_service,
|
||||||
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
|
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
|
||||||
@ -116,7 +138,7 @@ static struct my_option my_long_options[] =
|
|||||||
(gptr *) &Options::user,
|
(gptr *) &Options::user,
|
||||||
(gptr *) &Options::user,
|
(gptr *) &Options::user,
|
||||||
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
|
||||||
|
#endif
|
||||||
{ "version", 'V', "Output version information and exit.", 0, 0, 0,
|
{ "version", 'V', "Output version information and exit.", 0, 0, 0,
|
||||||
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
|
||||||
|
|
||||||
@ -214,20 +236,44 @@ C_MODE_END
|
|||||||
int Options::load(int argc, char **argv)
|
int Options::load(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
char** argv_ptr = argv;
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
setup_windows_defaults(*argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
config_file=NULL;
|
||||||
if (argc >= 2)
|
if (argc >= 2)
|
||||||
{
|
{
|
||||||
|
if (is_prefix(argv[1], "--defaults-file="))
|
||||||
|
config_file=argv[1];
|
||||||
if (is_prefix(argv[1],"--defaults-file=") ||
|
if (is_prefix(argv[1],"--defaults-file=") ||
|
||||||
is_prefix(argv[1],"--defaults-extra-file="))
|
is_prefix(argv[1],"--defaults-extra-file="))
|
||||||
Options::first_option= argv[1];
|
Options::first_option= argv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we were not given a config file on the command line so we
|
||||||
|
// set have to construct a new argv array
|
||||||
|
if (config_file == NULL)
|
||||||
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
::GetModuleFileName(NULL, default_config_file, sizeof(default_config_file));
|
||||||
|
char *filename = strstr(default_config_file, "mysqlmanager.exe");
|
||||||
|
strcpy(filename, "my.ini");
|
||||||
|
#endif
|
||||||
|
config_file = default_config_file;
|
||||||
|
}
|
||||||
|
|
||||||
/* config-file options are prepended to command-line ones */
|
/* config-file options are prepended to command-line ones */
|
||||||
load_defaults("my", default_groups, &argc, &argv);
|
load_defaults(config_file, default_groups, &argc, &argv);
|
||||||
|
|
||||||
|
rc= handle_options(&argc, &argv, my_long_options, get_one_option);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
Options::saved_argv= argv;
|
Options::saved_argv= argv;
|
||||||
|
|
||||||
if ((rc= handle_options(&argc, &argv, my_long_options, get_one_option)) != 0)
|
|
||||||
return rc;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,4 +281,31 @@ void Options::cleanup()
|
|||||||
{
|
{
|
||||||
/* free_defaults returns nothing */
|
/* free_defaults returns nothing */
|
||||||
free_defaults(Options::saved_argv);
|
free_defaults(Options::saved_argv);
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
free((char*)default_password_file_name);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
|
||||||
|
char* change_extension(const char *src, const char *newext)
|
||||||
|
{
|
||||||
|
char *dot = (char*)strrchr(src, '.');
|
||||||
|
if (!dot) return (char*)src;
|
||||||
|
|
||||||
|
int newlen = dot-src+strlen(newext)+1;
|
||||||
|
char *temp = (char*)malloc(newlen);
|
||||||
|
bzero(temp, newlen);
|
||||||
|
strncpy(temp, src, dot-src+1);
|
||||||
|
strcat(temp, newext);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Options::setup_windows_defaults(const char *progname)
|
||||||
|
{
|
||||||
|
Options::password_file_name = default_password_file_name = change_extension(progname, "passwd");
|
||||||
|
Options::log_file_name = default_log_file_name = change_extension(progname, "log");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -28,23 +28,32 @@
|
|||||||
|
|
||||||
struct Options
|
struct Options
|
||||||
{
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
static char install_as_service;
|
||||||
|
static char remove_service;
|
||||||
|
#else
|
||||||
static char run_as_service; /* handle_options doesn't support bool */
|
static char run_as_service; /* handle_options doesn't support bool */
|
||||||
|
static const char *user;
|
||||||
|
#endif
|
||||||
static const char *log_file_name;
|
static const char *log_file_name;
|
||||||
static const char *pid_file_name;
|
static const char *pid_file_name;
|
||||||
static const char *socket_file_name;
|
static const char *socket_file_name;
|
||||||
static const char *password_file_name;
|
static const char *password_file_name;
|
||||||
static const char *default_mysqld_path;
|
static const char *default_mysqld_path;
|
||||||
static const char *user;
|
|
||||||
/* the option which should be passed to process_default_option_files */
|
/* the option which should be passed to process_default_option_files */
|
||||||
static const char *first_option;
|
static const char *first_option;
|
||||||
static uint monitoring_interval;
|
static uint monitoring_interval;
|
||||||
static uint port_number;
|
static uint port_number;
|
||||||
static const char *bind_address;
|
static const char *bind_address;
|
||||||
|
static const char *config_file;
|
||||||
|
|
||||||
static char **saved_argv;
|
static char **saved_argv;
|
||||||
|
|
||||||
static int load(int argc, char **argv);
|
int load(int argc, char **argv);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
#ifdef __WIN__
|
||||||
|
void setup_windows_defaults(const char *progname);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
|
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
25
server-tools/instance-manager/port.h
Executable file
25
server-tools/instance-manager/port.h
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PORT_H
|
||||||
|
#define INCLUDES_MYSQL_INSTANCE_MANAGER_PORT_H
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
|
||||||
|
#define vsnprintf _vsnprintf
|
||||||
|
|
||||||
|
#define SIGKILL 9
|
||||||
|
#define SHUT_RDWR 0x2
|
||||||
|
|
||||||
|
//TODO: fix this
|
||||||
|
#define DEFAULT_MONITORING_INTERVAL 20
|
||||||
|
#define DEFAULT_PORT 2273
|
||||||
|
#define PROTOCOL_VERSION 10
|
||||||
|
|
||||||
|
typedef int pid_t;
|
||||||
|
|
||||||
|
#undef popen
|
||||||
|
#define popen(A,B) _popen(A,B)
|
||||||
|
|
||||||
|
#endif /* __WIN__ */
|
||||||
|
|
||||||
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORT_H */
|
||||||
|
|
||||||
|
|
@ -14,7 +14,9 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include <my_global.h>
|
||||||
#include "priv.h"
|
#include "priv.h"
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||||
pid_t manager_pid;
|
pid_t manager_pid;
|
||||||
|
@ -17,17 +17,23 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef __WIN__
|
||||||
|
#include "port.h"
|
||||||
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
/* the pid of the manager process (of the signal thread on the LinuxThreads) */
|
||||||
extern pid_t manager_pid;
|
extern pid_t manager_pid;
|
||||||
|
|
||||||
|
#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
|
||||||
system using LinuxThreads
|
system using LinuxThreads
|
||||||
*/
|
*/
|
||||||
extern bool linuxthreads;
|
extern bool linuxthreads;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const char mysqlmanager_version[];
|
extern const char mysqlmanager_version[];
|
||||||
extern const int mysqlmanager_version_length;
|
extern const int mysqlmanager_version_length;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <thr_alarm.h>
|
#include <thr_alarm.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
/* Kick-off signal handler */
|
/* Kick-off signal handler */
|
||||||
|
|
||||||
enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 };
|
enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 };
|
||||||
@ -34,7 +35,7 @@ enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 };
|
|||||||
static void handle_signal(int __attribute__((unused)) sig_no)
|
static void handle_signal(int __attribute__((unused)) sig_no)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: think about moving signal information (now it's shutdown_in_progress)
|
TODO: think about moving signal information (now it's shutdown_in_progress)
|
||||||
@ -76,12 +77,13 @@ Thread_registry::~Thread_registry()
|
|||||||
|
|
||||||
void Thread_registry::register_thread(Thread_info *info)
|
void Thread_registry::register_thread(Thread_info *info)
|
||||||
{
|
{
|
||||||
|
#ifndef __WIN__
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler= handle_signal;
|
sa.sa_handler= handle_signal;
|
||||||
sa.sa_flags= 0;
|
sa.sa_flags= 0;
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sigaction(THREAD_KICK_OFF_SIGNAL, &sa, 0);
|
sigaction(THREAD_KICK_OFF_SIGNAL, &sa, 0);
|
||||||
|
#endif
|
||||||
info->current_cond= 0;
|
info->current_cond= 0;
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_thread_registry);
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
@ -156,6 +158,7 @@ void Thread_registry::deliver_shutdown()
|
|||||||
pthread_mutex_lock(&LOCK_thread_registry);
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
shutdown_in_progress= true;
|
shutdown_in_progress= true;
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
/* to stop reading from the network we need to flush alarm queue */
|
/* to stop reading from the network we need to flush alarm queue */
|
||||||
end_thr_alarm(0);
|
end_thr_alarm(0);
|
||||||
/*
|
/*
|
||||||
@ -163,6 +166,8 @@ void Thread_registry::deliver_shutdown()
|
|||||||
stopped alarm processing.
|
stopped alarm processing.
|
||||||
*/
|
*/
|
||||||
process_alarm(THR_SERVER_ALARM);
|
process_alarm(THR_SERVER_ALARM);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (info= head.next; info != &head; info= info->next)
|
for (info= head.next; info != &head; info= info->next)
|
||||||
{
|
{
|
||||||
pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
|
pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
|
||||||
|
@ -36,7 +36,8 @@ struct User
|
|||||||
|
|
||||||
int User::init(const char *line)
|
int User::init(const char *line)
|
||||||
{
|
{
|
||||||
const char *name_begin, *name_end, *password;
|
const char *name_begin, *name_end;
|
||||||
|
char *password;
|
||||||
|
|
||||||
if (line[0] == '\'' || line[0] == '"')
|
if (line[0] == '\'' || line[0] == '"')
|
||||||
{
|
{
|
||||||
@ -44,7 +45,7 @@ int User::init(const char *line)
|
|||||||
name_end= strchr(name_begin, line[0]);
|
name_end= strchr(name_begin, line[0]);
|
||||||
if (name_end == 0 || name_end[1] != ':')
|
if (name_end == 0 || name_end[1] != ':')
|
||||||
goto err;
|
goto err;
|
||||||
password= name_end + 2;
|
password= (char*)(name_end + 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -52,13 +53,18 @@ int User::init(const char *line)
|
|||||||
name_end= strchr(name_begin, ':');
|
name_end= strchr(name_begin, ':');
|
||||||
if (name_end == 0)
|
if (name_end == 0)
|
||||||
goto err;
|
goto err;
|
||||||
password= name_end + 1;
|
password= (char*)(name_end + 1);
|
||||||
}
|
}
|
||||||
user_length= name_end - name_begin;
|
user_length= name_end - name_begin;
|
||||||
if (user_length > USERNAME_LENGTH)
|
if (user_length > USERNAME_LENGTH)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* assume that newline characater is present */
|
/* assume that newline characater is present */
|
||||||
|
if (password[strlen(password)-2] == '\r')
|
||||||
|
{
|
||||||
|
password[strlen(password)-2] = '\n';
|
||||||
|
password[strlen(password)-1] = 0;
|
||||||
|
}
|
||||||
if (strlen(password) != SCRAMBLED_PASSWORD_CHAR_LENGTH + 1)
|
if (strlen(password) != SCRAMBLED_PASSWORD_CHAR_LENGTH + 1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user