From fbbe03f1d2c3497783e161f54c2f488f3c083b3b Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Fri, 10 Aug 2018 10:51:58 -0400 Subject: [PATCH] Remove Executor and Session --- .../Components/InstanceFactory.cs | 13 +-- .../Components/Watchdog/Executor.cs | 87 ------------------- .../Components/Watchdog/IExecutor.cs | 31 ------- .../Components/Watchdog/ISession.cs | 11 --- .../Components/Watchdog/ISessionBase.cs | 13 --- .../Components/Watchdog/ISessionController.cs | 14 ++- .../Components/Watchdog/Session.cs | 75 ---------------- .../Components/Watchdog/SessionController.cs | 49 ++++++++--- .../Watchdog/SessionControllerFactory.cs | 52 ++++++++--- src/Tgstation.Server.Host/Core/Application.cs | 1 - 10 files changed, 90 insertions(+), 256 deletions(-) delete mode 100644 src/Tgstation.Server.Host/Components/Watchdog/Executor.cs delete mode 100644 src/Tgstation.Server.Host/Components/Watchdog/IExecutor.cs delete mode 100644 src/Tgstation.Server.Host/Components/Watchdog/ISession.cs delete mode 100644 src/Tgstation.Server.Host/Components/Watchdog/ISessionBase.cs delete mode 100644 src/Tgstation.Server.Host/Components/Watchdog/Session.cs diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs index 89125b337b..da99e976e7 100644 --- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs +++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs @@ -52,11 +52,6 @@ namespace Tgstation.Server.Host.Components /// readonly ICryptographySuite cryptographySuite; - /// - /// The for the - /// - readonly IExecutor executor; - /// /// The for the /// @@ -92,13 +87,12 @@ namespace Tgstation.Server.Host.Components /// The value of /// The value of /// The value of - /// The value of /// The value of /// The value of /// The value of /// The value of /// The value of - public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, IServerControl serverUpdater, ICryptographySuite cryptographySuite, IExecutor executor, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IProviderFactory providerFactory, IProcessExecutor processExecutor) + public InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, IServerControl serverUpdater, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IProviderFactory providerFactory, IProcessExecutor processExecutor) { this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory)); @@ -106,8 +100,7 @@ namespace Tgstation.Server.Host.Components this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender)); this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater)); - this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite )); - this.executor = executor ?? throw new ArgumentNullException(nameof(executor)); + this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite)); this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager)); this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory)); this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller)); @@ -144,7 +137,7 @@ namespace Tgstation.Server.Host.Components var chat = chatFactory.CreateChat(metadata.ChatSettings); try { - var sessionControllerFactory = new SessionControllerFactory(executor, byond, byondTopicSender, cryptographySuite, application, gameIoManager, chat, loggerFactory, metadata.CloneMetadata()); + var sessionControllerFactory = new SessionControllerFactory(processExecutor, byond, byondTopicSender, cryptographySuite, application, gameIoManager, chat, loggerFactory, metadata.CloneMetadata()); var reattachInfoHandler = new ReattachInfoHandler(databaseContextFactory, dmbFactory, metadata.CloneMetadata()); var watchdogFactory = new WatchdogFactory(chat, sessionControllerFactory, serverUpdater, loggerFactory, reattachInfoHandler, databaseContextFactory, byondTopicSender, eventConsumer, metadata.CloneMetadata()); var watchdog = watchdogFactory.CreateWatchdog(dmbFactory, metadata.DreamDaemonSettings); diff --git a/src/Tgstation.Server.Host/Components/Watchdog/Executor.cs b/src/Tgstation.Server.Host/Components/Watchdog/Executor.cs deleted file mode 100644 index 130e1d0b96..0000000000 --- a/src/Tgstation.Server.Host/Components/Watchdog/Executor.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Globalization; -using Tgstation.Server.Api.Models; -using Tgstation.Server.Api.Models.Internal; -using Tgstation.Server.Host.Components.Byond; -using Tgstation.Server.Host.Core; - -namespace Tgstation.Server.Host.Components.Watchdog -{ - /// - sealed class Executor : IExecutor - { - /// - /// The for the - /// - readonly IProcessExecutor processExecutor; - - /// - /// The for the - /// - readonly ILogger logger; - - /// - /// Change a given into the appropriate DreamDaemon command line word - /// - /// The level to change - /// A representation of the command line parameter - static string SecurityWord(DreamDaemonSecurity securityLevel) - { - switch (securityLevel) - { - case DreamDaemonSecurity.Safe: - return "safe"; - case DreamDaemonSecurity.Trusted: - return "trusted"; - case DreamDaemonSecurity.Ultrasafe: - return "ultrasafe"; - default: - throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel)); - } - } - - /// - /// Construct an - /// - /// The value of - /// The value of - public Executor(IProcessExecutor processExecutor, ILogger logger) - { - this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); - this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - /// - public ISession AttachToDreamDaemon(int processId, IByondExecutableLock byondLock) => new Session(processExecutor.GetProcess(processId), byondLock); - - /// - public ISession RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, IByondExecutableLock byondLock, IDmbProvider dmbProvider, string parameters, bool useSecondaryPort, bool useSecondaryDirectory) - { - if (launchParameters == null) - throw new ArgumentNullException(nameof(launchParameters)); - if (byondLock == null) - throw new ArgumentNullException(nameof(byondLock)); - if (dmbProvider == null) - throw new ArgumentNullException(nameof(dmbProvider)); - if (parameters == null) - throw new ArgumentNullException(nameof(parameters)); - - var fileName = byondLock.DreamDaemonPath; - var workingDirectory = useSecondaryDirectory ? dmbProvider.SecondaryDirectory : dmbProvider.PrimaryDirectory; - - var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} {2}-close -{3} -verbose -public -params \"{4}\"", - dmbProvider.DmbName, - useSecondaryPort ? launchParameters.SecondaryPort : launchParameters.PrimaryPort, - launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty, - SecurityWord(launchParameters.SecurityLevel.Value), - parameters); - - logger.LogTrace("Running DreamDaemon in {0}: {1} {2}", workingDirectory, fileName, arguments); - - var proc = processExecutor.LaunchProcess(fileName, workingDirectory, arguments); - - return new Session(proc, byondLock); - } - } -} diff --git a/src/Tgstation.Server.Host/Components/Watchdog/IExecutor.cs b/src/Tgstation.Server.Host/Components/Watchdog/IExecutor.cs deleted file mode 100644 index 127244af15..0000000000 --- a/src/Tgstation.Server.Host/Components/Watchdog/IExecutor.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Tgstation.Server.Api.Models.Internal; -using Tgstation.Server.Host.Components.Byond; - -namespace Tgstation.Server.Host.Components.Watchdog -{ - /// - /// For creating s - /// - interface IExecutor - { - /// - /// Run a dream daemon instance - /// - /// The - /// The for the new - /// The for the .dmb to run - /// The value of the -params command line option - /// If the field of should be used - /// If the field of should be used - /// A new - ISession RunDreamDaemon(DreamDaemonLaunchParameters launchParameters, IByondExecutableLock byondLock, IDmbProvider dmbProvider, string parameters, bool useSecondaryPort, bool useSecondaryDirectory); - - /// - /// Attach to a running instance of DreamDaemon - /// - /// The - /// The for the new - /// A new - ISession AttachToDreamDaemon(int processId, IByondExecutableLock byondLock); - } -} diff --git a/src/Tgstation.Server.Host/Components/Watchdog/ISession.cs b/src/Tgstation.Server.Host/Components/Watchdog/ISession.cs deleted file mode 100644 index 1728cc2ad3..0000000000 --- a/src/Tgstation.Server.Host/Components/Watchdog/ISession.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Tgstation.Server.Host.Core; - -namespace Tgstation.Server.Host.Components.Watchdog -{ - /// - /// Represents a dream daemon process - /// - interface ISession : ISessionBase, IProcess - { - } -} \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/Watchdog/ISessionBase.cs b/src/Tgstation.Server.Host/Components/Watchdog/ISessionBase.cs deleted file mode 100644 index bd1d9ee0dc..0000000000 --- a/src/Tgstation.Server.Host/Components/Watchdog/ISessionBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Threading.Tasks; -using Tgstation.Server.Host.Core; - -namespace Tgstation.Server.Host.Components.Watchdog -{ - interface ISessionBase : IProcessBase - { - /// - /// A that completes when DreamDaemon starts pumping the windows message queue after loading a .dmb or when it crashes - /// - Task LaunchResult { get; } - } -} diff --git a/src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs b/src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs index 6624d03145..6a703f5fc9 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs @@ -1,20 +1,26 @@ using System.Threading; using System.Threading.Tasks; +using Tgstation.Server.Host.Core; namespace Tgstation.Server.Host.Components.Watchdog { /// - /// Handles communication with a + /// Handles communication with a DreamDaemon /// - interface ISessionController : ISessionBase + interface ISessionController : IProcessBase { + /// + /// A that completes when DreamDaemon starts pumping the windows message queue after loading a .dmb or when it crashes + /// + Task LaunchResult { get; } + /// /// If the of is being used /// bool IsPrimary { get; } /// - /// If the DMAPI was validated. This field may only be access once completes + /// If the DMAPI was validated. This field may only be access once completes /// bool ApiValidated { get; } @@ -44,7 +50,7 @@ namespace Tgstation.Server.Host.Components.Watchdog Task OnReboot { get; } /// - /// Releases the without terminating it. Also calls + /// Releases the without terminating it. Also calls /// /// which can be used to create a new similar to this one ReattachInformation Release(); diff --git a/src/Tgstation.Server.Host/Components/Watchdog/Session.cs b/src/Tgstation.Server.Host/Components/Watchdog/Session.cs deleted file mode 100644 index 01a1a7bdd9..0000000000 --- a/src/Tgstation.Server.Host/Components/Watchdog/Session.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Threading.Tasks; -using Tgstation.Server.Host.Components.Byond; -using Tgstation.Server.Host.Core; - -namespace Tgstation.Server.Host.Components.Watchdog -{ - /// - sealed class Session : ISession - { - /// - public int Id => process.Id; - - /// - public Task Startup => process.Startup; - - /// - public Task LaunchResult { get; } - - /// - public Task Lifetime => process.Lifetime; - - /// - /// The actual - /// - readonly IProcess process; - /// - /// The for the - /// - readonly IByondExecutableLock byondLock; - - /// - /// Construct a - /// - /// The value of - /// The value of - public Session(IProcess process, IByondExecutableLock byondLock) - { - this.process = process ?? throw new ArgumentNullException(nameof(process)); - this.byondLock = byondLock ?? throw new ArgumentNullException(nameof(byondLock)); - - async Task GetLaunchResult() - { - var startTime = DateTimeOffset.Now; - await process.Startup.ConfigureAwait(false); - var result = new LaunchResult - { - ExitCode = process.Lifetime.IsCompleted ? (int?)await process.Lifetime.ConfigureAwait(false) : null, - StartupTime = DateTimeOffset.Now - startTime - }; - return result; - }; - LaunchResult = GetLaunchResult(); - } - - /// - public void Dispose() - { - process.Dispose(); - byondLock.Dispose(); - } - - /// - public void Terminate() => process.Terminate(); - - /// - public string GetErrorOutput() => process.GetErrorOutput(); - - /// - public string GetStandardOutput() => process.GetStandardOutput(); - - /// - public string GetCombinedOutput() => process.GetCombinedOutput(); - } -} diff --git a/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs b/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs index afb239d6fe..4a6e5a8c03 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs @@ -8,7 +8,9 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api.Models; +using Tgstation.Server.Host.Components.Byond; using Tgstation.Server.Host.Components.Chat; +using Tgstation.Server.Host.Core; namespace Tgstation.Server.Host.Components.Watchdog { @@ -72,10 +74,10 @@ namespace Tgstation.Server.Host.Components.Watchdog } /// - public Task LaunchResult => session.LaunchResult; + public Task LaunchResult { get; } /// - public Task Lifetime => session.Lifetime; + public Task Lifetime => process.Lifetime; /// public Task OnReboot => rebootTcs.Task; @@ -96,9 +98,14 @@ namespace Tgstation.Server.Host.Components.Watchdog readonly IInteropContext interopContext; /// - /// The for the + /// The for the /// - readonly ISession session; + readonly IProcess process; + + /// + /// The for the + /// + readonly IByondExecutableLock byondLock; /// /// The for the @@ -144,7 +151,7 @@ namespace Tgstation.Server.Host.Components.Watchdog bool apiValidated; /// - /// If should be kept alive instead + /// If should be kept alive instead /// bool released; @@ -152,18 +159,20 @@ namespace Tgstation.Server.Host.Components.Watchdog /// Construct a /// /// The value of - /// The value of + /// The value of + /// The value of /// The value of /// The value of /// The value of /// The value of /// The value of - public SessionController(ReattachInformation reattachInformation, ISession session, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, IInteropContext interopContext, IChat chat, ILogger logger) + public SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, IInteropContext interopContext, IChat chat, ILogger logger) { this.chatJsonTrackingContext = chatJsonTrackingContext; //null valid this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation)); this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender)); - this.session = session ?? throw new ArgumentNullException(nameof(session)); + this.process = process ?? throw new ArgumentNullException(nameof(process)); + this.byondLock = byondLock ?? throw new ArgumentNullException(nameof(byondLock)); this.interopContext = interopContext ?? throw new ArgumentNullException(nameof(interopContext)); this.chat = chat ?? throw new ArgumentNullException(nameof(chat)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -176,6 +185,19 @@ namespace Tgstation.Server.Host.Components.Watchdog released = false; rebootTcs = new TaskCompletionSource(); + + async Task GetLaunchResult() + { + var startTime = DateTimeOffset.Now; + await process.Startup.ConfigureAwait(false); + var result = new LaunchResult + { + ExitCode = process.Lifetime.IsCompleted ? (int?)await process.Lifetime.ConfigureAwait(false) : null, + StartupTime = DateTimeOffset.Now - startTime + }; + return result; + }; + LaunchResult = GetLaunchResult(); } /// @@ -201,8 +223,11 @@ namespace Tgstation.Server.Host.Components.Watchdog if (disposing) { if (!released) - session.Terminate(); - session.Dispose(); + { + process.Terminate(); + byondLock.Dispose(); + } + process.Dispose(); interopContext.Dispose(); Dmb?.Dispose(); //will be null when released chatJsonTrackingContext.Dispose(); @@ -213,8 +238,8 @@ namespace Tgstation.Server.Host.Components.Watchdog if (logger != null) logger.LogError("Being disposed via finalizer!"); if (!released) - if (session != null) - session.Terminate(); + if (process != null) + process.Terminate(); else if (logger != null) logger.LogCritical("Unable to terminate active DreamDaemon session due to finalizer ordering!"); } diff --git a/src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs index ea25ecc487..e915aa4084 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Tgstation.Server.Api.Models; using Tgstation.Server.Api.Models.Internal; using Tgstation.Server.Host.Components.Byond; using Tgstation.Server.Host.Components.Chat; @@ -21,9 +22,9 @@ namespace Tgstation.Server.Host.Components.Watchdog sealed class SessionControllerFactory : ISessionControllerFactory { /// - /// The for the + /// The for the /// - readonly IExecutor executor; + readonly IProcessExecutor processExecutor; /// /// The for the @@ -65,10 +66,30 @@ namespace Tgstation.Server.Host.Components.Watchdog /// readonly Api.Models.Instance instance; + /// + /// Change a given into the appropriate DreamDaemon command line word + /// + /// The level to change + /// A representation of the command line parameter + static string SecurityWord(DreamDaemonSecurity securityLevel) + { + switch (securityLevel) + { + case DreamDaemonSecurity.Safe: + return "safe"; + case DreamDaemonSecurity.Trusted: + return "trusted"; + case DreamDaemonSecurity.Ultrasafe: + return "ultrasafe"; + default: + throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel)); + } + } + /// /// Construct a /// - /// The value of + /// The value of /// The value of /// The value of /// The value of @@ -77,9 +98,9 @@ namespace Tgstation.Server.Host.Components.Watchdog /// The value of /// The value of /// The value of - public SessionControllerFactory(IExecutor executor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Api.Models.Instance instance) + public SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Api.Models.Instance instance) { - this.executor = executor ?? throw new ArgumentNullException(nameof(executor)); + this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor)); this.byond = byond ?? throw new ArgumentNullException(nameof(byond)); this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender)); this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite)); @@ -150,7 +171,14 @@ namespace Tgstation.Server.Host.Components.Watchdog var context = new InteropContext(ioManager, loggerFactory.CreateLogger(), basePath, interopInfo.ServerCommandsJson); try { - var session = executor.RunDreamDaemon(launchParameters, byondLock, dmbProvider, parameters, !primaryPort, !primaryDirectory); + var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} {2}-close -{3} -verbose -public -params \"{4}\"", + dmbProvider.DmbName, + primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort, + launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty, + SecurityWord(launchParameters.SecurityLevel.Value), + parameters); + + var process = processExecutor.LaunchProcess(byondLock.DreamDaemonPath, basePath, arguments); try { return new SessionController(new ReattachInformation @@ -159,15 +187,15 @@ namespace Tgstation.Server.Host.Components.Watchdog Dmb = dmbProvider, IsPrimary = primaryDirectory, Port = portToUse.Value, - ProcessId = session.Id, + ProcessId = process.Id, ChatChannelsJson = interopInfo.ChatChannelsJson, ChatCommandsJson = interopInfo.ChatCommandsJson, ServerCommandsJson = interopInfo.ServerCommandsJson, - }, session, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger()); + }, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger()); } catch { - session.Dispose(); + process.Dispose(); throw; } } @@ -207,14 +235,14 @@ namespace Tgstation.Server.Host.Components.Watchdog var context = new InteropContext(ioManager, loggerFactory.CreateLogger(), basePath, reattachInformation.ServerCommandsJson); try { - var session = executor.AttachToDreamDaemon(reattachInformation.ProcessId, byondLock); + var process = processExecutor.GetProcess(reattachInformation.ProcessId); try { - return new SessionController(reattachInformation, session, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger()); + return new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger()); } catch { - session.Dispose(); + process.Dispose(); throw; } } diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index 03eeab5463..17149ce438 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -199,7 +199,6 @@ namespace Tgstation.Server.Host.Core } services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(new ByondTopicSender {