private bool TryParseReadWriteIndexOrFail() { // If the read-write index doesn't exist. Just keep 'ReadWriteIndex' empty as it is. if (!File.Exists(m_Owner.ReadWriteIndexPath)) { return(true); } try { using (var stream = File.OpenRead(m_Owner.ReadWriteIndexPath)) { using (var br = new BinaryReader(stream)) { ReadWriteIndex.FromBinary(br); } } } catch (Exception e) { CoreLog.Warning($"Cannot parse the index file with exception '{e}'. Will try to clean up read-write path."); ReadWriteIndex.Clear(); return(!File.Exists(m_Owner.ReadWriteIndexPath) || m_Owner.TryCleanUpReadWritePathOrFail(Fail)); } return(true); }
public virtual void Complete() { if (isSuppressed) { return; } if (isCompleted) { throw new InvalidOperationException(Strings.ExMeasurementIsAlreadyCompleted); } isCompleted = true; timeSpent = HighResolutionTime.Now.Subtract(initialTime); memoryAllocated = GC.GetTotalMemory((options & MeasurementOptions.CollectGarbageOnLeave) > 0) - initialBytesAllocated; if ((options & MeasurementOptions.Log) > 0) { if ((options & MeasurementOptions.LogEnter) > 0) { CoreLog.Info("Measurement: Leave {0}.", this); } else { CoreLog.Info("Measurement: {0}.", this); } } }
/// <summary> /// Runs the game mode of this runner. /// </summary> /// <returns>true if shut down by the game mode, false otherwise.</returns> /// <exception cref="Exception">Thrown if a game mode is already running.</exception> public bool Run() { InternalStorage.RunningClient = this; // Prepare the syncronization context _messageQueue = new NoWaitMessageQueue(); _synchronizationContext = new SampSharpSynchronizationContext(_messageQueue); SynchronizationContext.SetSynchronizationContext(_synchronizationContext); _mainThread = Thread.CurrentThread.ManagedThreadId; _running = true; CoreLog.Log(CoreLogLevel.Initialisation, "SampSharp GameMode Client"); CoreLog.Log(CoreLogLevel.Initialisation, "-------------------------"); CoreLog.Log(CoreLogLevel.Initialisation, $"v{CoreVersion.Version.ToString(3)}, (C)2014-2020 Tim Potze"); CoreLog.Log(CoreLogLevel.Initialisation, "Hosted run mode is active."); CoreLog.Log(CoreLogLevel.Initialisation, ""); // TODO: Verify plugin version _gameModeProvider.Initialize(this); return(true); }
private bool VerifyVersionData(ServerCommandData data) { CoreLog.Log(CoreLogLevel.Debug, $"Received {data.Command} while waiting for server announcement."); if (data.Command == ServerCommand.Announce) { var protocolVersion = ValueConverter.ToUInt32(data.Data, 0); var pluginVersion = ValueConverter.ToVersion(data.Data, 4); if (protocolVersion != CoreVersion.ProtocolVersion) { var updatee = protocolVersion > CoreVersion.ProtocolVersion ? "game mode" : "server"; CoreLog.Log(CoreLogLevel.Error, $"Protocol version mismatch! The server is running protocol {protocolVersion} but the game mode is running {CoreVersion.ProtocolVersion}"); CoreLog.Log(CoreLogLevel.Error, $"Please update your {updatee}."); return(false); } CoreLog.Log(CoreLogLevel.Info, $"Connected to version {pluginVersion.ToString(3)} via protocol {protocolVersion}"); ServerPath = ValueConverter.ToString(data.Data, 8, Encoding.ASCII); return(true); } CoreLog.Log(CoreLogLevel.Error, $"Received command {data.Command.ToString().ToLower()} instead of announce."); return(false); }
internal override void Init() { CoreLog.DebugFormat("[AssetCache Init] {0}", Path); m_LastLoadingProgress = 0f; Owner.m_AssetPathsNotReadyOrFailure.Add(Path); var resourceCache = Owner.EnsureResourceCache(ResourcePath); resourceCache.IncreaseRetainCount(); if (DependencyAssetPaths.Count <= 0) { CoreLog.DebugFormat("[AssetCache Init] {0} no dep. observe resource.", Path); Status = AssetCacheStatus.WaitingForResource; resourceCache.AddObserver(this); return; } Status = AssetCacheStatus.WaitingForDeps; foreach (var depAssetPath in DependencyAssetPaths) { var depAssetCache = Owner.EnsureAssetCache(depAssetPath); depAssetCache.IncreaseRetainCount(); depAssetCache.AddObserver(this); } }
/// <summary> /// 服务器初始化确定在线离线 /// </summary> /// <param name="url">在线服务地址</param> /// <returns>返回是否初始化成功</returns> public static bool ServiceIni(string url) { try { //检测服务是否正常连接 若无法连接 开启离线模式 GlobalVar.TestService = new CoreClient(url); GlobalVar.TestService.Send("Test"); IsOnLine = true; } catch (Exception ex) { CoreLog.Error(ex); //离线服务开启 if (DialogResult.Yes != MessageBox.Show(@"离线中!是否还要继续?", @"提示", MessageBoxButtons.YesNo)) { return(false); } IsOnLine = false; var httpUrl = new CoreClientHost(typeof(Test.Service.Ws)).Open(); GlobalVar.TestService = new CoreClient(httpUrl); //设置本地数据库 LocalDatabaseHelp.SetDatabase(); } return(true); }
/// <inheritdoc/> /// <exception cref="ArgumentOutOfRangeException"><c>hints.SourceModel</c> or <c>hints.TargetModel</c> /// is out of range.</exception> public Difference Compare(IModel source, IModel target, HintSet hints) { Source = source; Target = target; Hints = hints ?? new HintSet(Source, Target); if (Hints.SourceModel != Source) { throw new ArgumentOutOfRangeException("hints.SourceModel"); } if (Hints.TargetModel != Target) { throw new ArgumentOutOfRangeException("hints.TargetModel"); } var previous = currentAsync.Value; currentAsync.Value = this; Results = new Dictionary <object, Difference>(); try { Stage = ComparisonStage.BaseComparison; Visit(Source, Target); CoreLog.Info("Base comparison complete."); Stage = ComparisonStage.ReferenceComparison; return(Visit(Source, Target)); } finally { currentAsync.Value = previous; Results = null; } }
/// <summary> /// Метод вывода в основную консоль текстовой информации. /// </summary> /// <param name="str"></param> /// <param name="c"></param> void addDataToCoreLog(string str, Color c) { CoreLog.AppendText(str); CoreLog.Select(CoreLog.TextLength - str.Length, CoreLog.TextLength); CoreLog.SelectionColor = c; CoreLog.AppendText("\n"); }
/// <summary> /// Waits for the next command sent by the server. /// </summary> /// <returns>The command sent by the server.</returns> public virtual async Task<ServerCommandData> ReceiveAsync() { AssertNotDisposed(); while (true) { if (_buffer.TryPop(out var command)) return command; try { var task = _stream?.ReadAsync(_readBuffer, 0, _readBuffer.Length, _source.Token); if (task == null) throw new StreamCommunicationClientClosedException(); var len = await task; if (_stream == null) throw new StreamCommunicationClientClosedException(); if (_readBuffer.Length == len) { CoreLog.Log(CoreLogLevel.Error, "Network buffer overflow detected!"); } _buffer.Push(_readBuffer, 0, len); } catch (TaskCanceledException) { throw new StreamCommunicationClientClosedException(); } } }
private void OnSendCompleted(object sender, SocketAsyncEventArgs e) { foreach (var packet in m_PacketsToSendList) { Handler.OnRecycle(packet); } // Sending failed. if (e.SocketError != SocketError.Success) { CoreLog.DebugFormat("[TcpChannel OnSendCompleted] Failure, SocketError={0}.", e.SocketError); Close(); OnError("Sending data failed. Error data is a SocketError.", e.SocketError); return; } CoreLog.DebugFormat("[TcpChannel OnSendCompleted] Success, bytesTransferred={0}.", e.BytesTransferred); lock (m_PacketsToSend) { if (m_PacketsToSend.Count <= 0) { Interlocked.Exchange(ref m_IsSending, 0); return; } CopyPacketsToSend(); } DoSend(); }
private void button1_Click(object sender, EventArgs e) { var xcs = Convert.ToInt32(textBox2.Text); var xccs = Convert.ToInt32(textBox3.Text); for (var i = 0; i < xcs; i++) { var i1 = i; new Thread(() => { CoreLog.Info("xc :" + i1 + " Start"); var cc = new CoreClient(textBox1.Text); for (var j = 0; j < xccs; j++) { CoreLog.Info("xc :" + i1 + " j :" + j + " ks"); var n = CorePublic.GenerateId(); var user = new user { id = n, name = i1 + "并发测试" + j }; var ret = cc.Send <int>("Insert", user); CoreLog.Info("id :" + n + " xc :" + i1 + " j :" + j + " " + (ret == 1)); Thread.Sleep(10); } } ).Start(); } }
internal override void Init() { CoreLog.DebugFormat("[ResourceCache Reuse] {0}", Path); Owner.m_ResourcePathsNotReadyOrFailure.Add(Path); Status = ResourceCacheStatus.WaitingForSlot; StartTicking(); }
private async Task NetworkingRoutine() { try { while (_running) { var data = await CommunicationClient.ReceiveAsync(); if (!_running) { return; } _commandWaitQueue.Release(data); } } catch (StreamCommunicationClientClosedException) { CoreLog.Log(CoreLogLevel.Warning, "Network routine ended because the communication with the SA:MP server was closed."); } catch (Exception e) { CoreLog.Log(CoreLogLevel.Error, "Network routine died! " + e); } }
/// <inheritdoc /> public void Tick() { if (!_didInitialize || _timers.Count == 0) { return; } var timestamp = Stopwatch.GetTimestamp(); // Don't user foreach for performance reasons // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < _timers.Count; i++) { var timer = _timers[i]; while ((timer.NextTick > _lastTick || timestamp < _lastTick) && timer.NextTick <= timestamp) { try { timer.Invoke(); } catch (Exception e) { CoreLog.Log(CoreLogLevel.Error, $"Timer threw an exception: {e}"); } timer.NextTick += timer.IntervalTicks; } } _lastTick = timestamp; }
internal override void Reset() { CoreLog.DebugFormat("[AssetCache Reset] {0}", Path); m_CopiedAssetObservers.Clear(); m_AssetObservers.Clear(); m_CopiedAssetAccessors.Clear(); m_AssetAccessors.Clear(); StopTicking(); StopAndResetLoadingTask(); AssetObject = null; foreach (var depAssetPath in DependencyAssetPaths) { var depAssetCache = Owner.EnsureAssetCache(depAssetPath); depAssetCache.RemoveObserver(this); depAssetCache.ReduceRetainCount(); } var resourceCache = Owner.EnsureResourceCache(ResourcePath); resourceCache.RemoveObserver(this); resourceCache.ReduceRetainCount(); DependencyAssetPaths = null; Status = AssetCacheStatus.None; Owner.m_AssetPathsNotReadyOrFailure.Remove(Path); m_DependencyAssetReadyCount = 0; ResourcePath = null; IsScene = false; m_LastLoadingProgress = 0; base.Reset(); }
private async void Initialize() { _mainThread = Thread.CurrentThread.ManagedThreadId; CoreLog.Log(CoreLogLevel.Initialisation, "SampSharp GameMode Client"); CoreLog.Log(CoreLogLevel.Initialisation, "-------------------------"); CoreLog.Log(CoreLogLevel.Initialisation, $"v{CoreVersion.Version.ToString(3)}, (C)2014-2020 Tim Potze"); CoreLog.Log(CoreLogLevel.Initialisation, "Multi-process run mode is active. FOR DEVELOPMENT PURPOSES ONLY!"); CoreLog.Log(CoreLogLevel.Initialisation, "Run your server in hosted run mode for production environments. See https://sampsharp.net/running-in-production for more information."); CoreLog.Log(CoreLogLevel.Initialisation, ""); AppDomain.CurrentDomain.ProcessExit += (sender, args) => { CoreLog.Log(CoreLogLevel.Info, "Shutdown signal received"); ShutDown(); if (_mainRoutine != null && !_mainRoutine.IsCompleted) { _mainRoutine.Wait(); } if (_networkingRoutine != null && !_networkingRoutine.IsCompleted) { _networkingRoutine.Wait(); } }; CoreLog.Log(CoreLogLevel.Info, $"Connecting to the server via {CommunicationClient}..."); await CommunicationClient.Connect(); _running = true; CoreLog.Log(CoreLogLevel.Info, "Set up networking routine..."); StartNetworkingRoutine(); CoreLog.Log(CoreLogLevel.Info, "Connected! Waiting for server announcement..."); ServerCommandData data; do { data = await _commandWaitQueue.WaitAsync(); // Could receive ticks if reconnecting. } while (data.Command == ServerCommand.Tick); if (!VerifyVersionData(data)) { return; } CoreLog.Log(CoreLogLevel.Info, "Initializing game mode provider..."); _gameModeProvider.Initialize(this); CoreLog.Log(CoreLogLevel.Info, "Sending start signal to server..."); Send(ServerCommand.Start, new[] { (byte)_startBehaviour }); CoreLog.Log(CoreLogLevel.Info, "Set up main routine..."); _mainRoutine = MainRoutine(); }
public void ShutDown() { CoreLog.Debug("[NetModule ShutDown] channel count is " + m_Channels.Count); foreach (var channel in m_Channels) { channel.Close(); } m_Channels.Clear(); }
/// <summary> /// Registers the specified command. /// </summary> /// <param name="command">The command.</param> public virtual void Register(ICommand command) { if (command == null) { throw new ArgumentNullException(nameof(command)); } CoreLog.Log(CoreLogLevel.Debug, $"Registering command {command}"); _commands.Add(command); }
public static void LogInfo(Type type, params object[] messages) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < messages.Length; i++) { sb.Append(messages[i]); } CoreLog.Info(ReplaceNewLines(String.Format(TypeBldStr, type, sb.ToString()))); }
internal virtual void ReduceRetainCount() { if (m_RetainCount <= 0) { throw new InvalidOperationException(Utility.Text.Format("Reducing retain count to negative, on '{0}' ({1}).", Path, GetType().Name)); } --m_RetainCount; CoreLog.DebugFormat("[{0} ReduceRetainCount] '{2}' to {1}", GetType().Name, m_RetainCount, Path); }
/// <summary> /// Autoloads the controllers in the specified assembly. /// </summary> /// <param name="assembly">The assembly.</param> public void AutoloadControllersForAssembly(Assembly assembly) { foreach (var type in assembly.GetExportedTypes() .Where(t => t.GetTypeInfo().IsClass&& typeof(IController).GetTypeInfo().IsAssignableFrom(t) && t.GetTypeInfo().GetCustomAttribute <ControllerAttribute>() != null)) { CoreLog.Log(CoreLogLevel.Debug, $"Autoloading type {type}..."); _controllers.Override(Activator.CreateInstance(type) as IController); } }
private void AutoloadPoolTypes() { var types = new List <Type>(); foreach (var poolType in new[] { typeof(BaseMode), GetType() }.Concat(_extensions.Select(e => e.GetType())) .Select(t => t.GetTypeInfo().Assembly) .Distinct() .SelectMany(a => a.GetTypes()) .Where(t => t.GetTypeInfo().IsClass&& t.GetTypeInfo().GetCustomAttribute <PooledTypeAttribute>() != null) .Distinct()) { // If poolType or subclass of poolType is already in types, continue. if (types.Any(t => t == poolType || poolType.GetTypeInfo().IsAssignableFrom(t))) { CoreLog.Log(CoreLogLevel.Debug, $"Pool of type {poolType} is not autoloaded because a subclass of it will already be loaded."); continue; } // Remove all types in types where type is supertype of poolType. foreach (var t in types.Where(t => t.GetTypeInfo().IsAssignableFrom(poolType)).ToArray()) { CoreLog.Log(CoreLogLevel.Debug, $"No longer autoloading type {poolType} because a subclass of it is going to be loaded."); types.Remove(t); } CoreLog.Log(CoreLogLevel.Debug, $"Autoloading pool of type {poolType}."); types.Add(poolType); } var poolTypes = new[] { typeof(IdentifiedPool <>), typeof(IdentifiedOwnedPool <,>) }; foreach (var type in types) { var pool = type; do { pool = pool.GetTypeInfo().BaseType; } while (pool != null && (!pool.GetTypeInfo().IsGenericType || !poolTypes.Contains(pool.GetGenericTypeDefinition()))); if (pool == null) { CoreLog.Log(CoreLogLevel.Debug, $"Skipped autoloading pool of type {type} because it's not a subtype of a pool."); continue; } pool.GetTypeInfo().GetMethod("Register", new[] { typeof(Type) }).Invoke(null, new object[] { type }); } }
/// <summary> /// Invokes the native with the specified arguments. /// </summary> /// <param name="arguments">The arguments.</param> /// <returns>The return value of the native.</returns> public int Invoke(params object[] arguments) { if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (Parameters.Length != arguments.Length) { throw new ArgumentOutOfRangeException(nameof(arguments), "Invalid argument count"); } IEnumerable <byte> data = ValueConverter.GetBytes(Handle); if (CoreLog.DoesLog(CoreLogLevel.Verbose)) { CoreLog.LogVerbose("Invoking {0}({1})", Name, string.Join(", ", arguments)); } int length; for (var i = 0; i < Parameters.Length; i++) { length = GetLength(i, arguments); data = data .Concat(new[] { (byte)Parameters[i].ArgumentType }) .Concat(Parameters[i].GetBytes(arguments[i], length, _gameModeClient)); } var response = _gameModeClient.InvokeNative(data); if (response.Length < 4) { CoreLog.Log(CoreLogLevel.Warning, "Native call returned no response, execution probably failed."); return(0); } var result = ValueConverter.ToInt32(response, 0); var respPos = 4; for (var i = 0; i < Parameters.Length; i++) { length = GetLength(i, arguments); var value = Parameters[i].GetReferenceArgument(response, ref respPos, length, result, _gameModeClient); if (value != null) { arguments[i] = value; } } return(result); }
private void CreateEventsFromAssemblies() { // Find methods with EventAttribute in any ISystem in any assembly. var events = new AssemblyScanner() .IncludeAllAssemblies() .IncludeNonPublicMembers() .Implements <ISystem>() .ScanMethods <EventAttribute>(); // Gather event data, compile invoker and add the data to the events collection. foreach (var(method, attribute) in events) { CoreLog.LogDebug("Adding event listener on {0}.{1}.", method.DeclaringType, method.Name); var name = attribute.Name ?? method.Name; if (!_events.TryGetValue(name, out var @event)) { _events[name] = @event = new Event(Invoke); } var argsPtr = 0; // The current pointer in the event arguments array. var parameterSources = method.GetParameters() .Select(info => new MethodParameterSource(info)) .ToArray(); // Determine the source of each parameter. foreach (var source in parameterSources) { var type = source.Info.ParameterType; if (typeof(Component).IsAssignableFrom(type)) { // Components are provided by the entity in the arguments array of the event. source.ParameterIndex = argsPtr++; source.IsComponent = true; } else if (type.IsValueType || DefaultParameterTypes.Contains(type)) { // Default types are passed straight trough. source.ParameterIndex = argsPtr++; } else { // Other types are provided trough Dependency Injection. source.IsService = true; } } var invoker = CreateInvoker(method, parameterSources, argsPtr); @event.Invokers.Add(invoker); } }
/// <summary> /// Initializes new instance of this type. /// </summary> /// <param name="name">The measurement name.</param> /// <param name="options">The measurement options.</param> /// <param name="operationCount">The operation count.</param> public Measurement(string name, MeasurementOptions options, int operationCount) { this.options = options; this.operationCount = operationCount; Name = name; if ((options & MeasurementOptions.LogEnter) > 0) { CoreLog.Info("Measurement: Enter {0}.", FullName); } initialBytesAllocated = GC.GetTotalMemory((options & MeasurementOptions.CollectGarbageOnEnter) > 0); initialTime = HighResolutionTime.Now; }
private void LoadExtensions() { var load = new List <Assembly>(); // Create a dependency-ordered list of extensions. var loading = new List <Assembly>(); foreach ( var assembly in GetType() .GetTypeInfo() .Assembly.GetReferencedAssemblies() .Select(Assembly.Load) .Concat(new[] { GetType().GetTypeInfo().Assembly }) .Distinct() .Where(a => a.GetCustomAttributes <SampSharpExtensionAttribute>().Any())) { AddExtensionToLoadList(assembly, load, loading); } // Load extensions according to dependency list. foreach (var assembly in load) { var attributes = assembly.GetCustomAttributes <SampSharpExtensionAttribute>(); foreach (var extensionType in attributes.Select(attribute => attribute.Type)) { if (extensionType == null) { continue; } if (!typeof(IExtension).GetTypeInfo().IsAssignableFrom(extensionType)) { CoreLog.Log(CoreLogLevel.Warning, $"The extension from {assembly} could not be loaded. The specified extension type does not inherit from IExtension."); continue; } if (!extensionType.GetTypeInfo().Assembly.Equals(assembly)) { CoreLog.Log(CoreLogLevel.Warning, $"The extension from {assembly} could not be loaded. The specified extension type is not part of the assembly."); continue; } if (_extensions.Any(e => e.GetType() == extensionType)) { CoreLog.Log(CoreLogLevel.Warning, $"The extension from {assembly} could not be loaded. The specified extension type was already loaded."); continue; } // Register the extension to the plugin. var extension = (IExtension)Activator.CreateInstance(extensionType); RegisterExtension(extension); } } }
/// <inheritdoc/> public virtual void Dump() { if (Count == 0) { CoreLog.Info("None"); return; } foreach (var node in list) { node.Dump(); } }
private void CreateTimersFromAssemblies(long tick) { // Find methods with TimerAttribute in any ISystem in any assembly. var events = new AssemblyScanner() .IncludeAllAssemblies() .IncludeNonPublicMembers() .Implements <ISystem>() .ScanMethods <TimerAttribute>(); // Create timer invokers and store timer info in registry. foreach (var(method, attribute) in events) { CoreLog.LogDebug("Adding timer on {0}.{1}.", method.DeclaringType, method.Name); if (!IsValidInterval(attribute.IntervalTimeSpan)) { CoreLog.Log(CoreLogLevel.Error, $"Timer {method} could not be registered the interval {attribute.IntervalTimeSpan} is invalid."); continue; } var service = _serviceProvider.GetService(method.DeclaringType); if (service == null) { CoreLog.Log(CoreLogLevel.Debug, "Skipping timer registration because service could not be loaded."); continue; } var parameterInfos = method.GetParameters() .Select(info => new MethodParameterSource(info) { IsService = true }) .ToArray(); var compiled = MethodInvokerFactory.Compile(method, parameterInfos); if (attribute.IntervalTimeSpan < LowInterval) { CoreLog.Log(CoreLogLevel.Warning, $"Timer {method.DeclaringType}.{method.Name} has a low interval of {attribute.IntervalTimeSpan}."); } var timer = new TimerInfo { IsActive = true, Invoke = () => compiled(service, null, _serviceProvider, null), IntervalTicks = attribute.IntervalTimeSpan.Ticks, NextTick = tick + attribute.IntervalTimeSpan.Ticks }; _timers.Add(timer); } }
/// <summary> /// Registers the type to use when initializing new instances. /// </summary> /// <param name="type">The type.</param> /// <exception cref="System.ArgumentNullException">Thrown if type is null</exception> /// <exception cref="System.ArgumentException">type must be of type TInstance;type</exception> public static void Register(Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!typeof(TInstance).GetTypeInfo().IsAssignableFrom(type)) { throw new ArgumentException("type must be of type " + typeof(TInstance), nameof(type)); } CoreLog.Log(CoreLogLevel.Debug, $"Type {type} registered to pool."); InstanceType = type; }
/// <summary> /// Starts the backup engines. /// </summary> /// <returns>True if successful, otherwise false.</returns> private async Task <bool> StartBackupEnginesAsync() { // each backup engine instance shares the same logger. // this means a single log file for all engine instances- and each engine will prepend its log messages with a context tag. try { BackupEngineInstances = new List <BackupEngine>(); var instanceCountSettingName = ArchivialLibrary.Constants.RuntimeSettingNames.BackupEngineInstancesCount; var instanceCount = Convert.ToInt32(await ClientDatabase.GetApplicationOptionAsync(instanceCountSettingName).ConfigureAwait(false)); var startupDelaySettingName = ArchivialLibrary.Constants.RuntimeSettingNames.BackupEngineStartupDelayInSeconds; var startupDelaySeconds = Convert.ToInt32(await ClientDatabase.GetApplicationOptionAsync(startupDelaySettingName).ConfigureAwait(false)); for (int i = 0; i < instanceCount; i++) { CoreLog.WriteSystemEvent( string.Format("Waiting {0} seconds between Backup Engine starts to reduce sudden filesystem load.", startupDelaySeconds), EventLogEntryType.Information, ArchivialLibrary.Constants.EventIDs.BackupEngineWaitingForNextStart, true); await Task.Delay(TimeSpan.FromSeconds(startupDelaySeconds)).ConfigureAwait(false); var engineLog = new Logger(string.Format("{0}-{1}", ArchivialLibrary.Constants.Logging.BackupComponentName, i)); engineLog.Start( CoreSettings.GetEventlogName(), CoreSettings.GetEventlogName(), CoreSettings.GetLogFilesDirectory()); var instance = new BackupEngine(ClientDatabase, engineLog, i, CoreSettings); instance.Stopped += Backup_Stopped; instance.BeginStart(); BackupEngineInstances.Add(instance); CoreLog.WriteSystemEvent( string.Format("Backup Engine instance {0} has started.", i), EventLogEntryType.Information, ArchivialLibrary.Constants.EventIDs.StartedBackupEngine, true); } return(true); } catch (Exception ex) { var message = "Failed to start the backup engine."; var context = CoreLog.GenerateFullContextStackTrace(); CoreLog.WriteSystemEvent(message, ex, context, ArchivialLibrary.Constants.EventIDs.FailedBackupEngine, true); return(false); } }