/// <inheritdoc /> protected sealed override async Task <IDmbProvider> PrepServerForLaunch(IDmbProvider dmbToUse, CancellationToken cancellationToken) { if (ActiveSwappable != null) { throw new InvalidOperationException("Expected activeSwappable to be null!"); } if (startupDmbProvider != null) { throw new InvalidOperationException("Expected startupDmbProvider to be null!"); } Logger.LogTrace("Prep for server launch. pendingSwappable is {0}available", pendingSwappable == null ? "not " : String.Empty); // Add another lock to the startup DMB because it'll be used throughout the lifetime of the watchdog startupDmbProvider = await DmbFactory.FromCompileJob(dmbToUse.CompileJob, cancellationToken).ConfigureAwait(false); pendingSwappable ??= new SwappableDmbProvider(dmbToUse, GameIOManager, symlinkFactory); ActiveSwappable = pendingSwappable; pendingSwappable = null; try { await InitialLink(cancellationToken).ConfigureAwait(false); } catch { // We won't worry about disposing activeSwappable here as we can't dispose dmbToUse here. ActiveSwappable = null; throw; } return(ActiveSwappable); }
/// <inheritdoc /> protected override async Task DisposeAndNullControllersImpl() { await base.DisposeAndNullControllersImpl().ConfigureAwait(false); // If we reach this point, we can guarantee PrepServerForLaunch will be called before starting again. ActiveSwappable = null; pendingSwappable?.Dispose(); pendingSwappable = null; startupDmbProvider?.Dispose(); startupDmbProvider = null; }
/// <inheritdoc /> protected override MonitorAction HandleNormalReboot() { if (pendingSwappable != null) { Logger.LogTrace("Replacing activeSwappable with pendingSwappable..."); Server.ReplaceDmbProvider(pendingSwappable); ActiveSwappable = pendingSwappable; pendingSwappable = null; } else { Logger.LogTrace("Nothing to do as pendingSwappable is null."); } return(MonitorAction.Continue); }
/// <inheritdoc /> protected override async Task <MonitorAction> HandleNormalReboot(CancellationToken cancellationToken) { if (pendingSwappable != null) { var updateTask = BeforeApplyDmb(pendingSwappable.CompileJob, cancellationToken); Logger.LogTrace("Replacing activeSwappable with pendingSwappable..."); Server.ReplaceDmbProvider(pendingSwappable); ActiveSwappable = pendingSwappable; pendingSwappable = null; await updateTask.ConfigureAwait(false); } else { Logger.LogTrace("Nothing to do as pendingSwappable is null."); } return(MonitorAction.Continue); }
/// <inheritdoc /> protected override async Task HandleNewDmbAvailable(CancellationToken cancellationToken) { IDmbProvider compileJobProvider = DmbFactory.LockNextDmb(1); bool canSeamlesslySwap = true; if (compileJobProvider.CompileJob.ByondVersion != ActiveCompileJob.ByondVersion) { // have to do a graceful restart Logger.LogDebug( "Not swapping to new compile job {0} as it uses a different BYOND version ({1}) than what is currently active {2}. Queueing graceful restart instead...", compileJobProvider.CompileJob.Id, compileJobProvider.CompileJob.ByondVersion, ActiveCompileJob.ByondVersion); canSeamlesslySwap = false; } if (compileJobProvider.CompileJob.DmeName != ActiveCompileJob.DmeName) { Logger.LogDebug( "Not swapping to new compile job {0} as it uses a different .dmb name ({1}) than what is currently active {2}. Queueing graceful restart instead...", compileJobProvider.CompileJob.Id, compileJobProvider.CompileJob.DmeName, ActiveCompileJob.DmeName); canSeamlesslySwap = false; } if (!canSeamlesslySwap) { compileJobProvider.Dispose(); await base.HandleNewDmbAvailable(cancellationToken).ConfigureAwait(false); return; } SwappableDmbProvider windowsProvider = null; bool suspended = false; try { windowsProvider = new SwappableDmbProvider(compileJobProvider, GameIOManager, symlinkFactory); Logger.LogDebug("Swapping to compile job {0}...", windowsProvider.CompileJob.Id); try { Server.Suspend(); suspended = true; } catch (Exception ex) { Logger.LogWarning(ex, "Exception while suspending server!"); } await windowsProvider.MakeActive(cancellationToken).ConfigureAwait(false); } catch (Exception ex) { Logger.LogError(ex, "Exception while swapping"); IDmbProvider providerToDispose = windowsProvider ?? compileJobProvider; providerToDispose.Dispose(); throw; } // Let this throw hard if it fails if (suspended) { Server.Resume(); } pendingSwappable?.Dispose(); pendingSwappable = windowsProvider; }