/// <inheritdoc /> protected sealed override async Task InitControllers(Action callBeforeRecurse, Task chatTask, DualReattachInformation reattachInfo, CancellationToken cancellationToken) { var serverToReattach = reattachInfo?.Alpha ?? reattachInfo?.Bravo; var serverToKill = reattachInfo?.Bravo ?? reattachInfo?.Alpha; // vice versa if (serverToKill == serverToReattach) { serverToKill = null; } if (reattachInfo?.AlphaIsActive == false) { var temp = serverToReattach; serverToReattach = serverToKill; serverToKill = temp; } // don't need a new dmb if reattaching var doesntNeedNewDmb = serverToReattach != null; var dmbToUse = doesntNeedNewDmb ? null : DmbFactory.LockNextDmb(1); // if this try catches something, both servers are killed bool inactiveServerWasKilled = false; try { // start the alpha server task, either by launch a new process or attaching to an existing one // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail // The tasks pertaining to server startup times are in the ISessionControllers Task <ISessionController> serverLaunchTask, inactiveReattachTask; if (!doesntNeedNewDmb) { dmbToUse = await PrepServerForLaunch(dmbToUse, cancellationToken).ConfigureAwait(false); serverLaunchTask = SessionControllerFactory.LaunchNew( dmbToUse, null, ActiveLaunchParameters, true, true, false, cancellationToken); } else { serverLaunchTask = SessionControllerFactory.Reattach(serverToReattach, cancellationToken); } bool thereIsAnInactiveServerToKill = serverToKill != null; if (thereIsAnInactiveServerToKill) { inactiveReattachTask = SessionControllerFactory.Reattach(serverToKill, cancellationToken); } else { inactiveReattachTask = Task.FromResult <ISessionController>(null); } // retrieve the session controller Server = await serverLaunchTask.ConfigureAwait(false); // failed reattaches will return null Server?.SetHighPriority(); var inactiveServerController = await inactiveReattachTask.ConfigureAwait(false); inactiveServerController?.Dispose(); inactiveServerWasKilled = inactiveServerController != null; // possiblity of null servers due to failed reattaches if (Server == null) { callBeforeRecurse(); await NotifyOfFailedReattach(thereIsAnInactiveServerToKill && !inactiveServerWasKilled, cancellationToken).ConfigureAwait(false); return; } await CheckLaunchResult(Server, "Server", cancellationToken).ConfigureAwait(false); Server.EnableCustomChatCommands(); } catch { // kill the controllers bool serverWasActive = Server != null; DisposeAndNullControllers(); // server didn't get control of this dmb if (dmbToUse != null && !serverWasActive) { dmbToUse.Dispose(); } if (serverToKill != null && !inactiveServerWasKilled) { serverToKill.Dmb.Dispose(); } throw; } }
/// <inheritdoc /> public Task Save(DualReattachInformation reattachInformation, CancellationToken cancellationToken) => databaseContextFactory.UseContext(async(db) =>