Exemplo n.º 1
0
        public static bool TryStartSqlProcess(HttpContext context, string exe, string arguments, out MySqlProcess process)
        {
            lock (_lockObj)
            {
                process = _process;
                if (process != null)
                {
                    try
                    {
                        if (!process.HasExited)
                        {
                            context.Response.StatusCode = 409;
                            context.Response.Write(string.Format("The process {0}:{1} is still running!", process.Id, process.ProcessName));
                            context.Response.End();
                            return(false);
                        }
                    }
                    catch (Exception)
                    {
                    }

                    _process = null;
                }

                _process = MySqlProcess.Start(exe, arguments);
                process  = _process;
                return(true);
            }
        }
Exemplo n.º 2
0
        private Exception TerminateProcess(MySqlProcess process, Exception ex)
        {
            process.Kill();

            Trace("{0}:{1} killed.", process.ProcessName, process.Id);

            return(new InvalidOperationException(String.Format("Wait for process {0}:{1} failed with {2}", process.ProcessName, process.Id, ex), ex));
        }
Exemplo n.º 3
0
        private async Task HandleResponse(HttpContext context)
        {
            var process = _process;

            if (process != null)
            {
                if (!process.HasExited)
                {
                    try
                    {
                        if (process.StartTime.Add(Utils.MySqlTimeout) < DateTime.UtcNow)
                        {
                            throw new TimeoutException(String.Format("Execute sql process {0}:{1} has exceeded {2} timeout", process.ProcessName, process.Id, Utils.MySqlTimeout));
                        }
                    }
                    catch (Exception ex)
                    {
                        _process = null;
                        throw TerminateProcess(process, ex);
                    }

                    // return location
                    var location = new Uri(context.Request.Url, Utils.GetPath("{0}/dump/status"));
                    context.Response.Headers["Location"] = location.AbsoluteUri;
                    context.Response.StatusCode          = 202;
                    return;
                }

                Trace("{0}:{1} exited with {2}.", process.ProcessName, process.Id, process.ExitCode);

                if (process.ExitCode != 0)
                {
                    throw new InvalidOperationException(String.Format("{0}:{1} exit with {2}!  {3}", process.ProcessName, process.Id, process.ExitCode, process.Output));
                }
            }

            _process = null;
            var prefix = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME");

            if (String.IsNullOrEmpty(prefix))
            {
                prefix = "mysqldump";
            }

            var fileName = String.Format("{0}-{1:yy-MM-dd-HH-mm-ss}.sql", prefix, DateTime.UtcNow);

            context.Response.ContentType = "text/plain";
            context.Response.Headers["Content-Disposition"] = "attachment; filename=" + fileName;
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            using (var fs = File.OpenRead(_resultFile))
            {
                await fs.CopyToAsync(context.Response.OutputStream);
            }
            context.Response.End();

            Utils.SafeExecute(() => File.Delete(_resultFile), _tracer);
        }
Exemplo n.º 4
0
        public override async Task ProcessRequestAsync(HttpContext context)
        {
            if (context.Request.RawUrl.IndexOf(Utils.GetPath("{0}/dump/status"), StringComparison.OrdinalIgnoreCase) == 0)
            {
                await HandleResponse(context);

                return;
            }

            var exe = Path.Combine(BasePath, "bin", "mysqldump.exe");
            // --single-transaction aquires a REPEATABLE READ lock for the time of the dump to ensure consistency
            // http://dev.mysql.com/doc/refman/5.6/en/mysqldump.html#option_mysqldump_single-transaction
            var arguments = string.Format(@"--single-transaction -u{0} -p{1} -h{2} --port={3} --result-file={4} {5}", UserID, Password, Server, Port, _resultFile, Database);

            Trace("\"{0}\" {1}", exe, arguments.Replace(Password, "*****"));

            MySqlProcess process;

            if (!TryStartSqlProcess(context, exe, arguments, out process))
            {
                return;
            }

            var processName = process.ProcessName;
            var processId   = process.Id;

            _process = process;
            Trace("{0}:{1} started", processName, processId);

            if (context.Request.QueryString["async"] == "1")
            {
                await HandleResponse(context);

                return;
            }

            try
            {
                // wait for exit
                await process.WaitForExitAsync(Utils.MySqlTimeout);
            }
            catch (Exception ex)
            {
                _process = null;
                throw TerminateProcess(process, ex);
            }

            // to flush all output
            process.WaitForExit();

            await HandleResponse(context);
        }
Exemplo n.º 5
0
        public async override Task ProcessRequestAsync(HttpContext context)
        {
            var exe       = Path.Combine(BasePath, "bin", "mysql.exe");
            var arguments = string.Format(@"-u{0} -p{1} -h{2} --port={3} {4}", UserID, Password, Server, Port, Database);

            Trace("\"{0}\" {1}", exe, arguments.Replace(Password, "*****"));

            var process     = MySqlProcess.Start(exe, arguments);
            var processName = process.ProcessName;
            var processId   = process.Id;

            Trace("{0}:{1} started", processName, processId);

            Func <CancellationToken, Task> executeSql = async(CancellationToken cancellationToken) =>
            {
                await context.Request.InputStream.CopyToAsync(process.Input, 4096, cancellationToken);

                await process.Input.FlushAsync(cancellationToken);

                var quitCmd = Encoding.UTF8.GetBytes("\n\\q\n");
                await process.Input.WriteAsync(quitCmd, 0, quitCmd.Length, cancellationToken);

                await process.Input.FlushAsync(cancellationToken);

                if (!cancellationToken.IsCancellationRequested)
                {
                    // to flush all output
                    process.WaitForExit();
                }
            };

            var cts   = new CancellationTokenSource();
            var tasks = new[] { Task.Delay(Utils.MySqlTimeout, cts.Token), executeSql(cts.Token) };
            var task  = await Task.WhenAny(tasks);

            // cancel all pending tasks
            cts.Cancel();

            // first task is Delay.  This implies timeout.
            if (task == tasks[0])
            {
                process.Kill();

                Trace("{0}:{1} killed.", processName, processId);

                throw new TimeoutException(String.Format("Execute sql process {0}:{1} has exceeded {2} timeout", processName, processId, Utils.MySqlTimeout));
            }

            // to ensure successful in executing query and process has exited
            await task;

            Trace("{0}:{1} exited with {2}.", processName, processId, process.ExitCode);

            if (process.ExitCode != 0)
            {
                throw new InvalidOperationException(String.Format("{0}:{1} exit with {2}!  {3}", processName, processId, process.ExitCode, process.Output));
            }

            context.Response.StatusCode = 200;
            context.Response.Write(process.Output);
            context.Response.End();
        }