diff options
author | Vladislav Vaintroub <wlad@montyprogram.com> | 2011-03-09 20:21:03 +0100 |
---|---|---|
committer | Vladislav Vaintroub <wlad@montyprogram.com> | 2011-03-09 20:21:03 +0100 |
commit | d4a3a7b90ef06cb3eaf68317c42020e2980d3777 (patch) | |
tree | 94351c78c87bd6588e648dee70a7da84eb2b5d9c /sql/mysql_upgrade_service.cc | |
parent | 7ac23980b8009c7d446b008208f1bd6ba6ae9839 (diff) | |
download | mariadb-git-d4a3a7b90ef06cb3eaf68317c42020e2980d3777.tar.gz |
mwl#59 - windows installer.
Address Monty's review comments
Diffstat (limited to 'sql/mysql_upgrade_service.cc')
-rw-r--r-- | sql/mysql_upgrade_service.cc | 195 |
1 files changed, 83 insertions, 112 deletions
diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc index 1f18ef2ab40..68d97936e7d 100644 --- a/sql/mysql_upgrade_service.cc +++ b/sql/mysql_upgrade_service.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Monty Program Ab +/* Copyright (C) 2010-2011 Monty Program Ab & Vladislav Vaintroub This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,15 +28,14 @@ #include <mysql_version.h> #include <winservice.h> -#include <stdlib.h> -#include <stdio.h> #include <windows.h> /* We're using version APIs */ #pragma comment(lib, "version") #define USAGETEXT \ -"mysql_upgrade_service.exe Ver 1.42 for Windows\n" \ +"mysql_upgrade_service.exe Ver 1.00 for Windows\n" \ +"Copyright (C) 2010-2011 Monty Program Ab & Vladislav Vaintroub" \ "This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n" \ "and you are welcome to modify and redistribute it under the GPL v2 license\n" \ "Usage: mysql_upgrade_service.exe [OPTIONS]\n" \ @@ -66,7 +65,7 @@ static struct my_option my_long_options[]= { {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"service", 's', "Name of the existing Windows service", + {"service", 'S', "Name of the existing Windows service", &opt_service, &opt_service, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, }; @@ -93,17 +92,12 @@ get_one_option(int optid, static void log(const char *fmt, ...) { va_list args; - char buf[4096]; - /* Print the error message */ va_start(args, fmt); - if (fmt) - { - vsprintf_s(buf, fmt, args); - fprintf(stdout, "%s\n", buf); - } + vfprintf(stdout,fmt, args); va_end(args); - my_end(0); + fputc('\n', stdout);
+ fflush(stdout); } @@ -111,46 +105,47 @@ static void die(const char *fmt, ...) { va_list args; DBUG_ENTER("die"); - char buf[4096]; /* Print the error message */ va_start(args, fmt); - if (fmt) + + fprintf(stderr, "FATAL ERROR: "); + vfprintf(stderr, fmt, args); + if (logfile_path[0]) { - fprintf(stderr, "FATAL ERROR: "); - int count= vsprintf_s(buf, fmt, args); - fprintf(stderr, "%s.", buf); - if(logfile_path[0]) - { - fprintf(stderr, "Additional information can be found in the log file %s", - logfile_path); - } + fprintf(stderr, "Additional information can be found in the log file %s", + logfile_path); } va_end(args); - + fputc('\n', stderr);
+ fflush(stdout); /* Cleanup */ - if(service && initial_service_state != -1) + + /*
+ Stop service that we started, if it was not initally running at
+ program start.
+ */ + if (initial_service_state != -1 && initial_service_state != SERVICE_RUNNING) { - /* Stop service if it was not running */ - if(initial_service_state != SERVICE_RUNNING) - { - SERVICE_STATUS service_status; - ControlService(service, SERVICE_CONTROL_STOP, &service_status); - } - CloseServiceHandle(service); + SERVICE_STATUS service_status; + ControlService(service, SERVICE_CONTROL_STOP, &service_status); } - if(scm) - CloseServiceHandle(scm); - /* Stop mysqld.exe if it was started for upgrade */ - if(mysqld_process) + if (scm) + CloseServiceHandle(scm); + if (service) + CloseServiceHandle(service); + /* Stop mysqld.exe, if it was started for upgrade */ + if (mysqld_process) TerminateProcess(mysqld_process, 3); - if(logfile_handle) + if (logfile_handle) CloseHandle(logfile_handle); my_end(0); + exit(1); } + /* spawn-like function to run subprocesses. We also redirect the full output to the log file. @@ -166,43 +161,44 @@ static void die(const char *fmt, ...) @return intptr containing either process handle, if P_NOWAIT is used or return code of the process (if P_WAIT is used) */ + static intptr_t run_tool(int wait_flag, const char *program,...) { static char cmdline[32*1024]; + char *end; va_list args; va_start(args, program); - if(!program) + if (!program) die("Invalid call to run_tool"); + end= strxmov(cmdline, "\"", program, "\"", NullS); - strcpy_s(cmdline, "\""); - strcat_s(cmdline, program); - strcat_s(cmdline, "\""); for(;;) { char *param= va_arg(args,char *); if(!param) break; - strcat_s(cmdline, " \""); - strcat_s(cmdline, param); - strcat_s(cmdline, "\""); + end= strxmov(end, " \"", param, "\"", NullS); } va_end(args); /* Create output file if not alredy done */ - if(!logfile_handle) + if (!logfile_handle) { char tmpdir[FN_REFLEN]; GetTempPath(FN_REFLEN, tmpdir); sprintf_s(logfile_path, "%s\\mysql_upgrade_service.%s.log", tmpdir, opt_service); - logfile_handle = CreateFile(logfile_path, GENERIC_WRITE, FILE_SHARE_READ, + logfile_handle= CreateFile(logfile_path, GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, 0, NULL); - if(!logfile_handle) - die("Cannot open log file %s", logfile_path); + if (!logfile_handle) + { + die("Cannot open log file %s, windows error %u", + logfile_path, GetLastError()); + } } /* Start child process */ - STARTUPINFO si={0}; + STARTUPINFO si= {0}; si.cb= sizeof(si); si.hStdInput= GetStdHandle(STD_INPUT_HANDLE); si.hStdError= logfile_handle; @@ -216,13 +212,13 @@ static intptr_t run_tool(int wait_flag, const char *program,...) } CloseHandle(pi.hThread); - if(wait_flag == P_NOWAIT) + if (wait_flag == P_NOWAIT) { - /* Do not wait for process to complete, return handle */ + /* Do not wait for process to complete, return handle. */ return (intptr_t)pi.hProcess; } - /* Eait for process to complete */ + /* Wait for process to complete. */ if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0) { die("WaitForSingleObject() failed"); @@ -236,7 +232,6 @@ static intptr_t run_tool(int wait_flag, const char *program,...) } - void stop_mysqld_service() { DWORD needed; @@ -249,7 +244,7 @@ void stop_mysqld_service() sizeof(SERVICE_STATUS_PROCESS), &needed)) { - die("QueryServiceStatusEx failed (%d)\n", GetLastError()); + die("QueryServiceStatusEx failed (%u)\n", GetLastError()); } /* @@ -257,7 +252,7 @@ void stop_mysqld_service() exit. */ if(initial_service_state == -1) - initial_service_state =ssp.dwCurrentState; + initial_service_state= ssp.dwCurrentState; switch(ssp.dwCurrentState) { @@ -266,12 +261,13 @@ void stop_mysqld_service() case SERVICE_RUNNING: if(!ControlService(service, SERVICE_CONTROL_STOP, (SERVICE_STATUS *)&ssp)) - die("ControlService failed, error %d\n", GetLastError()); + die("ControlService failed, error %u\n", GetLastError()); case SERVICE_START_PENDING: case SERVICE_STOP_PENDING: if(timeout < 0) - die("Service does not stop after 1 minute timeout"); + die("Service does not stop after %d seconds timeout",shutdown_timeout); Sleep(100); + timeout -= 100; break; default: die("Unexpected service state %d",ssp.dwCurrentState); @@ -280,33 +276,6 @@ void stop_mysqld_service() } -/* Helper routine. Used to prevent downgrades by mysql_upgrade_service */ -void get_file_version(const wchar_t *path, int *major, int *minor) -{ - *major= *minor=0; - DWORD version_handle; - char *ver= 0; - VS_FIXEDFILEINFO info; - UINT len; - void *p; - - DWORD size = GetFileVersionInfoSizeW(path, &version_handle); - if (size == 0) - return; - ver = new char[size]; - if(!GetFileVersionInfoW(path, version_handle, size, ver)) - goto end; - - if(!VerQueryValue(ver,"\\",&p,&len)) - goto end; - memcpy(&info,p ,sizeof(VS_FIXEDFILEINFO)); - - *major = (info.dwFileVersionMS & 0xFFFF0000) >> 16; - *minor = (info.dwFileVersionMS & 0x0000FFFF); -end: - delete []ver; -} - /* Shutdown mysql server. Not using mysqladmin, since our --skip-grant-tables do not work anymore after mysql_upgrade @@ -340,21 +309,22 @@ static void change_service_config() char defaults_file[MAX_PATH]; char default_character_set[64]; char buf[MAX_PATH]; + char commandline[3*MAX_PATH + 19]; int i; - scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + scm= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!scm) - die("OpenSCManager failed with %d", GetLastError()); + die("OpenSCManager failed with %u", GetLastError()); service= OpenService(scm, opt_service, SERVICE_ALL_ACCESS); if (!service) - die("OpenService failed with %d", GetLastError()); + die("OpenService failed with %u", GetLastError()); BYTE config_buffer[8*1024]; LPQUERY_SERVICE_CONFIGW config= (LPQUERY_SERVICE_CONFIGW)config_buffer; - DWORD size=sizeof(config_buffer); + DWORD size= sizeof(config_buffer); DWORD needed; if (!QueryServiceConfigW(service, config, size, &needed)) - die("QueryServiceConfig failed with %d\n", GetLastError()); + die("QueryServiceConfig failed with %u", GetLastError()); mysqld_service_properties props; if (get_mysql_service_properties(config->lpBinaryPathName, &props)) @@ -363,14 +333,15 @@ static void change_service_config() } int my_major= MYSQL_VERSION_ID/10000; - int my_minor= (MYSQL_VERSION_ID - 10000*my_major)/100; + int my_minor= (MYSQL_VERSION_ID %10000)/100; + int my_patch= MYSQL_VERSION_ID%100; if(my_major < props.version_major || - (my_major == props.version_minor && my_minor < props.version_patch)) + (my_major == props.version_major && my_minor < props.version_minor)) { - die("Can not downgrade, the service is currently running as version %d.%d" - ", my version is %d.%d", props.version_major, props.version_minor, - my_major, my_minor); + die("Can not downgrade, the service is currently running as version %d.%d.%d" + ", my version is %d.%d.%d", props.version_major, props.version_minor, + props.version_patch, my_major, my_minor, my_patch); } if(props.inifile[0] == 0) @@ -386,7 +357,7 @@ static void change_service_config() unix style slashes. */ strcpy_s(buf, MAX_PATH, props.datadir); - for(i=0; buf[i]; i++) + for(i= 0; buf[i]; i++) { if (buf[i] == '\\') buf[i]= '/'; @@ -395,7 +366,7 @@ static void change_service_config() /* Remove basedir from defaults file, otherwise the service wont come up in - the new version, and will complain about mismatched message file. + the new version, and will complain about mismatched message file. */ WritePrivateProfileString("mysqld", "basedir",NULL, props.inifile); @@ -404,10 +375,10 @@ static void change_service_config() "default-character-set is deprecated and will be replaced ..." message. */ - default_character_set[0]=0; + default_character_set[0]= 0; GetPrivateProfileString("mysqld", "default-character-set", NULL, default_character_set, sizeof(default_character_set), defaults_file); - if(default_character_set[0]) + if (default_character_set[0]) { WritePrivateProfileString("mysqld", "default-character-set", NULL, defaults_file); @@ -416,19 +387,17 @@ static void change_service_config() } sprintf(defaults_file_param,"--defaults-file=%s", props.inifile); - char commandline[3*MAX_PATH + 19]; sprintf_s(commandline, "\"%s\" \"%s\" \"%s\"", mysqld_path, defaults_file_param, opt_service); if (!ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, commandline, NULL, NULL, NULL, NULL, NULL, NULL)) { - die("ChangeServiceConfigW failed with %d", GetLastError()); + die("ChangeServiceConfig failed with %u", GetLastError()); } } - int main(int argc, char **argv) { int error; @@ -439,8 +408,8 @@ int main(int argc, char **argv) /* Parse options */ if ((error= handle_options(&argc, &argv, my_long_options, get_one_option))) die(""); - if(!opt_service) - die("service parameter is mandatory"); + if (!opt_service) + die("--service=# parameter is mandatory"); /* Get full path to mysqld, we need it when changing service configuration. @@ -448,17 +417,17 @@ int main(int argc, char **argv) and mysql_upgrade_service.exe are in the same directory. */ GetModuleFileName(NULL, bindir, FN_REFLEN); - p = strrchr(bindir, FN_LIBCHAR); + p= strrchr(bindir, FN_LIBCHAR); if(p) { - *p=0; + *p= 0; } sprintf_s(mysqld_path, "%s\\mysqld.exe", bindir); sprintf_s(mysqladmin_path, "%s\\mysqladmin.exe", bindir); sprintf_s(mysqlupgrade_path, "%s\\mysql_upgrade.exe", bindir); char *paths[]= {mysqld_path, mysqladmin_path, mysqlupgrade_path}; - for(int i=0; i< 3;i++) + for(int i= 0; i< 3;i++) { if(GetFileAttributes(paths[i]) == INVALID_FILE_ATTRIBUTES) die("File %s does not exist", paths[i]); @@ -466,7 +435,7 @@ int main(int argc, char **argv) /* Messages written on stdout should not be buffered, GUI upgrade program - read them from pipe and uses as progress indicator. + reads them from pipe and uses as progress indicator. */ setvbuf(stdout, NULL, _IONBF, 0); @@ -476,7 +445,6 @@ int main(int argc, char **argv) log("Phase 2/8: Stopping service"); stop_mysqld_service(); - /* Start mysqld.exe as non-service skipping privileges (so we do not care about the password). But disable networking and enable pipe @@ -491,14 +459,14 @@ int main(int argc, char **argv) defaults_file_param, "--skip-networking", "--skip-grant-tables", "--enable-named-pipe", socket_param, NULL); - if(mysqld_process == INVALID_HANDLE_VALUE) + if (mysqld_process == INVALID_HANDLE_VALUE) { die("Cannot start mysqld.exe process, errno=%d", errno); } log("Phase 4/8: Waiting for startup to complete"); DWORD start_duration_ms= 0; - for (int i=0; ; i++) + for(;;) { if (WaitForSingleObject(mysqld_process, 0) != WAIT_TIMEOUT) die("mysqld.exe did not start"); @@ -515,10 +483,13 @@ int main(int argc, char **argv) } log("Phase 5/8: Running mysql_upgrade"); - int upgrade_err = (int) run_tool(P_WAIT, mysqlupgrade_path, + int upgrade_err= (int) run_tool(P_WAIT, mysqlupgrade_path, "--protocol=pipe", "--force", socket_param, NULL); + if (upgrade_err) + die("mysql_upgrade failed with error code %d\n", upgrade_err); + log("Phase 6/8: Initiating server shutdown"); initiate_mysqld_shutdown(); @@ -543,7 +514,7 @@ int main(int argc, char **argv) opt_service, logfile_path); CloseServiceHandle(service); CloseServiceHandle(scm); - if(logfile_handle) + if (logfile_handle) CloseHandle(logfile_handle); my_end(0); exit(0); |