Commit 875b0e63 authored by unknown's avatar unknown
Browse files

initial import of Windows port of IM.


server-tools/instance-manager/commands.cc:
  type cleanups for compiling on Windows
  now using Options::config_file for the location of the single 
  my.cnf file we are using
server-tools/instance-manager/guardian.cc:
  pthread_mutex_lock and unlock do not return a value on Windows
  so we return 0 in all cases
server-tools/instance-manager/instance.cc:
  big changes here.
  Had to implement Windows versions of launch_and_wait and kill()
server-tools/instance-manager/instance.h:
  added some function defs
server-tools/instance-manager/instance_map.cc:
  pthread_mutex_lock and unlock do not return a value on Windows
  Also, now using only the file named as Options::config_file
server-tools/instance-manager/instance_options.h:
  added reference to port.h
server-tools/instance-manager/listener.cc:
  reworked and simplified the socket handling code.
  Added windows versions of the code that sets the sockets to be
  non-blocking and non-inheritable
server-tools/instance-manager/listener.h:
  change Options to always be a struct.  Really surprised GCC was 
  letting this go.  Options was declared to be struct in some places
  and class in other places.
server-tools/instance-manager/log.cc:
  added reference to port.h
server-tools/instance-manager/manager.cc:
  moved all the signal code inside some #ifndef __WIN__ blocks
server-tools/instance-manager/manager.h:
  change Options to always be a struct.  Really surprised GCC was 
  letting this go.  Options was declared to be struct in some places
  and class in other places.
server-tools/instance-manager/mysqlmanager.cc:
  added in the Windows service code.
server-tools/instance-manager/options.cc:
  Added in the windows options for running as a service and the code
  for loading settings only from a single file
server-tools/instance-manager/options.h:
  added definitions for the new Windows service vars and routines
server-tools/instance-manager/parse_output.cc:
  added reference to port.h
server-tools/instance-manager/priv.cc:
  added reference to port.h
server-tools/instance-manager/priv.h:
  linuxthreads should not be visible on Windows
server-tools/instance-manager/thread_registry.cc:
  more __WIN__ blocking
server-tools/instance-manager/user_map.cc:
  fixed passwd file code to handle files with \r\n line endings
server-tools/instance-manager/IMService.cpp:
  New BitKeeper file ``server-tools/instance-manager/IMService.cpp''
server-tools/instance-manager/IMService.h:
  New BitKeeper file ``server-tools/instance-manager/IMService.h''
server-tools/instance-manager/WindowsService.cpp:
  New BitKeeper file ``server-tools/instance-manager/WindowsService.cpp''
server-tools/instance-manager/WindowsService.h:
  New BitKeeper file ``server-tools/instance-manager/WindowsService.h''
server-tools/instance-manager/mysqlmanager.vcproj:
  New BitKeeper file ``server-tools/instance-manager/mysqlmanager.vcproj''
server-tools/instance-manager/port.h:
  New BitKeeper file ``server-tools/instance-manager/port.h''
parent 6ae06030
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
#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 −0
Original line number Diff line number Diff line
#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 −0
Original line number Diff line number Diff line
#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 −0
Original line number Diff line number Diff line
#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);
};
+5 −4
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "mysql_manager_error.h"
#include "protocol.h"
#include "buffer.h"
#include "options.h"

#include <m_string.h>
#include <mysql.h>
@@ -469,7 +470,7 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
      size_t buff_size;
      int read_len;
      /* calculate buffer size */
      struct stat file_stat;
      MY_STAT file_stat;

      /* my_fstat doesn't use the flag parameter */
      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));

      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;
      store_to_protocol_packet(&send_buff, (char*) bf, &position, read_len);
      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, (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,
                                   (char*) log_files->value,
@@ -689,7 +690,7 @@ int Set_option::correct_file(int skip)
{
  int error;

  error= modify_defaults_file("/etc/my.cnf", option,
  error= modify_defaults_file(Options::config_file, option,
			      option_value, instance_name, skip);
  if (error > 0)
    return ER_OUT_OF_RESOURCES;
Loading