summaryrefslogtreecommitdiff
path: root/sql/mysql_upgrade_service.cc
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2018-11-13 13:10:32 +0100
committerVladislav Vaintroub <wlad@mariadb.com>2018-11-15 18:03:30 +0100
commita93ac8d95fd504412bd819325bfaa816e317786c (patch)
treec1f79a3fa8c68661df72a3a92c626ca808ba38d9 /sql/mysql_upgrade_service.cc
parentefc235d84d0df8a9895a5ae71c829303bbd39c8f (diff)
downloadmariadb-git-a93ac8d95fd504412bd819325bfaa816e317786c.tar.gz
MDEV-16448 mysql_upgrade_service remove my.ini variables that are no more valid
MDEV-16447 incorporate Innodb slow shutdown into mysql_upgrade_service.exe
Diffstat (limited to 'sql/mysql_upgrade_service.cc')
-rw-r--r--sql/mysql_upgrade_service.cc189
1 files changed, 140 insertions, 49 deletions
diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc
index 1a3df4f5536..9ea78accf44 100644
--- a/sql/mysql_upgrade_service.cc
+++ b/sql/mysql_upgrade_service.cc
@@ -29,6 +29,9 @@
#include <winservice.h>
#include <windows.h>
+#include <string>
+
+extern int upgrade_config_file(const char *myini_path);
/* We're using version APIs */
#pragma comment(lib, "version")
@@ -47,6 +50,8 @@ static char mysqlupgrade_path[MAX_PATH];
static char defaults_file_param[MAX_PATH + 16]; /*--defaults-file=<path> */
static char logfile_path[MAX_PATH];
+char my_ini_bck[MAX_PATH];
+mysqld_service_properties service_properties;
static char *opt_service;
static SC_HANDLE service;
static SC_HANDLE scm;
@@ -59,7 +64,7 @@ HANDLE logfile_handle;
Maybe,they can be made parameters
*/
static unsigned int startup_timeout= 60;
-static unsigned int shutdown_timeout= 60;
+static unsigned int shutdown_timeout= 60*60;
static struct my_option my_long_options[]=
{
@@ -112,6 +117,7 @@ static void die(const char *fmt, ...)
fprintf(stderr, "FATAL ERROR: ");
vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
if (logfile_path[0])
{
fprintf(stderr, "Additional information can be found in the log file %s",
@@ -122,6 +128,11 @@ static void die(const char *fmt, ...)
fflush(stdout);
/* Cleanup */
+ if (my_ini_bck[0])
+ {
+ MoveFileEx(my_ini_bck, service_properties.inifile,MOVEFILE_REPLACE_EXISTING);
+ }
+
/*
Stop service that we started, if it was not initally running at
program start.
@@ -309,77 +320,76 @@ void initiate_mysqld_shutdown()
}
}
-
-/*
- Change service configuration (binPath) to point to mysqld from
- this installation.
-*/
-static void change_service_config()
+static void get_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);
- if(!scm)
+ scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!scm)
die("OpenSCManager failed with %u", GetLastError());
- service= OpenService(scm, opt_service, SERVICE_ALL_ACCESS);
+ service = OpenService(scm, opt_service, SERVICE_ALL_ACCESS);
if (!service)
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);
+ BYTE config_buffer[8 * 1024];
+ LPQUERY_SERVICE_CONFIGW config = (LPQUERY_SERVICE_CONFIGW)config_buffer;
+ DWORD size = sizeof(config_buffer);
DWORD needed;
if (!QueryServiceConfigW(service, config, size, &needed))
die("QueryServiceConfig failed with %u", GetLastError());
- mysqld_service_properties props;
- if (get_mysql_service_properties(config->lpBinaryPathName, &props))
+ if (get_mysql_service_properties(config->lpBinaryPathName, &service_properties))
{
die("Not a valid MySQL service");
}
- int my_major= MYSQL_VERSION_ID/10000;
- int my_minor= (MYSQL_VERSION_ID %10000)/100;
- int my_patch= MYSQL_VERSION_ID%100;
+ int my_major = MYSQL_VERSION_ID / 10000;
+ 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_major && my_minor < props.version_minor))
+ if (my_major < service_properties.version_major ||
+ (my_major == service_properties.version_major && my_minor < service_properties.version_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);
+ ", my version is %d.%d.%d", service_properties.version_major, service_properties.version_minor,
+ service_properties.version_patch, my_major, my_minor, my_patch);
}
-
- if(props.inifile[0] == 0)
+ if (service_properties.inifile[0] == 0)
{
/*
Weird case, no --defaults-file in service definition, need to create one.
*/
- sprintf_s(props.inifile, MAX_PATH, "%s\\my.ini", props.datadir);
+ sprintf_s(service_properties.inifile, MAX_PATH, "%s\\my.ini", service_properties.datadir);
}
+ sprintf(defaults_file_param, "--defaults-file=%s", service_properties.inifile);
+}
+/*
+ Change service configuration (binPath) to point to mysqld from
+ this installation.
+*/
+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;
/*
Write datadir to my.ini, after converting backslashes to
unix style slashes.
*/
- strcpy_s(buf, MAX_PATH, props.datadir);
+ strcpy_s(buf, MAX_PATH, service_properties.datadir);
for(i= 0; buf[i]; i++)
{
if (buf[i] == '\\')
buf[i]= '/';
}
- WritePrivateProfileString("mysqld", "datadir",buf, props.inifile);
+ WritePrivateProfileString("mysqld", "datadir",buf, service_properties.inifile);
/*
Remove basedir from defaults file, otherwise the service wont come up in
the new version, and will complain about mismatched message file.
*/
- WritePrivateProfileString("mysqld", "basedir",NULL, props.inifile);
+ WritePrivateProfileString("mysqld", "basedir",NULL, service_properties.inifile);
/*
Replace default-character-set with character-set-server, to avoid
@@ -397,7 +407,7 @@ static void change_service_config()
default_character_set, defaults_file);
}
- sprintf(defaults_file_param,"--defaults-file=%s", props.inifile);
+ sprintf(defaults_file_param,"--defaults-file=%s", service_properties.inifile);
sprintf_s(commandline, "\"%s\" \"%s\" \"%s\"", mysqld_path,
defaults_file_param, opt_service);
if (!ChangeServiceConfig(service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
@@ -449,23 +459,97 @@ int main(int argc, char **argv)
reads them from pipe and uses as progress indicator.
*/
setvbuf(stdout, NULL, _IONBF, 0);
+ int phase = 0;
+ int max_phases=10;
+ get_service_config();
- log("Phase 1/8: Changing service configuration");
- change_service_config();
+ bool my_ini_exists;
+ bool old_mysqld_exe_exists;
- log("Phase 2/8: Stopping service");
+ log("Phase %d/%d: Stopping service", ++phase,max_phases);
stop_mysqld_service();
+ my_ini_exists = (GetFileAttributes(service_properties.inifile) != INVALID_FILE_ATTRIBUTES);
+ if (!my_ini_exists)
+ {
+ HANDLE h = CreateFile(service_properties.inifile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ 0, CREATE_NEW, 0 ,0);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(h);
+ }
+ else if (GetLastError() != ERROR_FILE_EXISTS)
+ {
+ die("Can't create ini file %s, last error %u", service_properties.inifile, GetLastError());
+ }
+ }
+
+ old_mysqld_exe_exists = (GetFileAttributes(service_properties.mysqld_exe) != INVALID_FILE_ATTRIBUTES);
+ log("Phase %d/%d: Fixing server config file%s", ++phase, max_phases, my_ini_exists ? "" : "(skipped)");
+
+ snprintf(my_ini_bck, sizeof(my_ini_bck), "%s.BCK", service_properties.inifile);
+ CopyFile(service_properties.inifile, my_ini_bck, FALSE);
+ upgrade_config_file(service_properties.inifile);
+
+ log("Phase %d/%d: Ensuring innodb slow shutdown%s", ++phase, max_phases,
+ old_mysqld_exe_exists?",this can take some time":"(skipped)");
+
+ char socket_param[FN_REFLEN];
+ sprintf_s(socket_param, "--socket=mysql_upgrade_service_%d",
+ GetCurrentProcessId());
+
+ DWORD start_duration_ms = 0;
+
+ if (old_mysqld_exe_exists)
+ {
+ /* Start/stop server with --loose-innodb-fast-shutdown=0 */
+ mysqld_process = (HANDLE)run_tool(P_NOWAIT, service_properties.mysqld_exe,
+ defaults_file_param, "--loose-innodb-fast-shutdown=0", "--skip-networking",
+ "--enable-named-pipe", socket_param, "--skip-slave-start", NULL);
+
+ if (mysqld_process == INVALID_HANDLE_VALUE)
+ {
+ die("Cannot start mysqld.exe process, last error =%u", GetLastError());
+ }
+ char pipe_name[64];
+ snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\mysql_upgrade_service_%u",
+ GetCurrentProcessId());
+ for (;;)
+ {
+ if (WaitForSingleObject(mysqld_process, 0) != WAIT_TIMEOUT)
+ die("mysqld.exe did not start");
+
+ if (WaitNamedPipe(pipe_name, 0))
+ {
+ // Server started, shut it down.
+ initiate_mysqld_shutdown();
+ if (WaitForSingleObject((HANDLE)mysqld_process, shutdown_timeout * 1000) != WAIT_OBJECT_0)
+ {
+ die("Could not shutdown server started with '--innodb-fast-shutdown=0'");
+ }
+ DWORD exit_code;
+ if (!GetExitCodeProcess((HANDLE)mysqld_process, &exit_code))
+ {
+ die("Could not get mysqld's exit code");
+ }
+ if (exit_code)
+ {
+ die("Could not get successfully shutdown mysqld");
+ }
+ CloseHandle(mysqld_process);
+ break;
+ }
+ Sleep(500);
+ start_duration_ms += 500;
+ }
+ }
/*
Start mysqld.exe as non-service skipping privileges (so we do not
care about the password). But disable networking and enable pipe
for communication, for security reasons.
*/
- char socket_param[FN_REFLEN];
- sprintf_s(socket_param,"--socket=mysql_upgrade_service_%d",
- GetCurrentProcessId());
- log("Phase 3/8: Starting mysqld for upgrade");
+ log("Phase %d/%d: Starting mysqld for upgrade",++phase,max_phases);
mysqld_process= (HANDLE)run_tool(P_NOWAIT, mysqld_path,
defaults_file_param, "--skip-networking", "--skip-grant-tables",
"--enable-named-pipe", socket_param,"--skip-slave-start", NULL);
@@ -475,8 +559,8 @@ int main(int argc, char **argv)
die("Cannot start mysqld.exe process, errno=%d", errno);
}
- log("Phase 4/8: Waiting for startup to complete");
- DWORD start_duration_ms= 0;
+ log("Phase %d/%d: Waiting for startup to complete",++phase,max_phases);
+ start_duration_ms= 0;
for(;;)
{
if (WaitForSingleObject(mysqld_process, 0) != WAIT_TIMEOUT)
@@ -493,7 +577,7 @@ int main(int argc, char **argv)
start_duration_ms+= 500;
}
- log("Phase 5/8: Running mysql_upgrade");
+ log("Phase %d/%d: Running mysql_upgrade",++phase,max_phases);
int upgrade_err= (int) run_tool(P_WAIT, mysqlupgrade_path,
"--protocol=pipe", "--force", socket_param,
NULL);
@@ -501,10 +585,13 @@ int main(int argc, char **argv)
if (upgrade_err)
die("mysql_upgrade failed with error code %d\n", upgrade_err);
- log("Phase 6/8: Initiating server shutdown");
+ log("Phase %d/%d: Changing service configuration", ++phase, max_phases);
+ change_service_config();
+
+ log("Phase %d/%d: Initiating server shutdown",++phase, max_phases);
initiate_mysqld_shutdown();
- log("Phase 7/8: Waiting for shutdown to complete");
+ log("Phase %d/%d: Waiting for shutdown to complete",++phase, max_phases);
if (WaitForSingleObject(mysqld_process, shutdown_timeout*1000)
!= WAIT_OBJECT_0)
{
@@ -514,7 +601,7 @@ int main(int argc, char **argv)
CloseHandle(mysqld_process);
mysqld_process= NULL;
- log("Phase 8/8: Starting service%s",
+ log("Phase %d/%d: Starting service%s",++phase,max_phases,
(initial_service_state == SERVICE_RUNNING)?"":" (skipped)");
if (initial_service_state == SERVICE_RUNNING)
{
@@ -527,6 +614,10 @@ int main(int argc, char **argv)
CloseServiceHandle(scm);
if (logfile_handle)
CloseHandle(logfile_handle);
+ if(my_ini_bck[0])
+ {
+ DeleteFile(my_ini_bck);
+ }
my_end(0);
exit(0);
}