/// <summary> /// Stop this plugin and all required dependencies /// </summary> /// <param name="module"></param> public void Stop(IServerModule module) { if (!AvailableModules.Contains(module)) { return; } // First we have to find all running modules that depend on this service var dependingServices = _dependencyManager.GetDependencyBranch(module).Dependends.Select(item => item.RepresentedModule); // Now we will stop all of them recursivly foreach (var dependingService in dependingServices.Where(dependend => dependend.State.HasFlag(ServerModuleState.Running) || dependend.State == ServerModuleState.Starting)) { // We will enque the service to make sure it is restarted later on AddWaitingService(module, dependingService); Stop(dependingService); } // Since stop is synchron we don't need an event try { module.Stop(); } catch { Console.WriteLine("Failed to stop service <{0}>", module.Name); } }
private IReadOnlyList <IServerModule> StartDependencies(IServerModule module, IDictionary <object, IServerModule> facadeProviders) { // Get all dependencies of this plugin service var dependencyServices = new List <IServerModule>(); foreach (var importingProperty in GetImportingProperties(module)) { if (!importingProperty.Attribute.IsStartDependency) { continue; } var propType = importingProperty.Property.PropertyType; if (propType.IsArray) { propType = propType.GetElementType(); } var dependencyProviders = facadeProviders.Where(facadePair => propType.IsInstanceOfType(facadePair.Key)); foreach (var dependencyProvider in dependencyProviders) { dependencyServices.Add(dependencyProvider.Value); } } return(dependencyServices); }
private void StartModule(IServerModule module) { // Check for any failed dependencies var hasfailedDependecies = _dependencyManager.GetDependencyBranch(module).Dependencies .Any(item => item.RepresentedModule.State == ServerModuleState.Failure); // Don't try to start modules which initialization has been failed or for which dependency initializations have failed if (module.State == ServerModuleState.Failure || hasfailedDependecies) { return; } // Now we check for any not running dependencies and start them var awaitingDependecies = _dependencyManager.GetDependencyBranch(module).Dependencies .Where(item => !item.RepresentedModule.State.HasFlag(ServerModuleState.Running)) .Select(item => item.RepresentedModule).ToArray(); if (awaitingDependecies.Any()) { EnqueServiceAndStartDependencies(awaitingDependecies, module); } else { ThreadPool.QueueUserWorkItem(ExecuteModuleStart, module); } }
private void ModuleChangedState(IServerModule module, ServerModuleState newState) { // Check if it switched to running if (!newState.HasFlag(ServerModuleState.Running)) { return; } // Now we start every service waiting on this service to return lock (WaitingModules) { if (!WaitingModules.ContainsKey(module)) { return; } // To increase boot speed we fork plugin start if more than one dependents was found foreach (var waitingModule in WaitingModules[module].ToArray()) { WaitingModules[module].Remove(waitingModule); StartModule(waitingModule); } // We remove this service for now after we started every dependend WaitingModules.Remove(module); } }
/// <summary> /// Restart the module and all of its dependencies /// </summary> /// <param name="module"></param> public void ReincarnateModule(IServerModule module) { // Stop execution _moduleStopper.Stop(module); // Start all desired _moduleStarter.Start(module); }
/// <inheritdoc /> public void Initialize(IServerModule module) { if (!AvailableModules.Contains(module)) { return; // Module not executable } module.Initialize(); }
/// <summary> /// Add a module which is designed to handle certain kind of requests. /// </summary> /// <param name="module">Module</param> /// <remarks> /// <para> /// Used to process messages to generate responses. /// </para> /// </remarks> public void AddHandler(IServerModule module) { if (module == null) { throw new ArgumentNullException("module"); } _requestModules.Add(module); }
/// <summary> /// Add a module which is used to check if the user have access to execute the incoming message /// </summary> /// <param name="module">Module</param> /// <remarks> /// <para> /// You can for instance user role based authentication on each message to verify that /// </para> /// </remarks> public void AddAuthorization(IServerModule module) { if (module == null) { throw new ArgumentNullException("module"); } _authorizeModules.Add(module); }
public void RegisterServerModule(IServerModule module) { module.Init(this, AgentController); var info = module.GetModuleInfo(); ServerModules.Add(info); OnServerEvent?.Invoke(this, new ServerEvent(ServerEventType.ServerModuleRegistered, info.Name)); Log.Logger.Information("SERVER {Event} {ModuleName}", ServerEventType.ServerModuleRegistered.ToString(), info.Name); }
public void AddModule(IServerModule module) { if (_modules.ContainsKey(module.GetType())) { throw new Exception("A module already exists in the server: " + module.GetType()); } _modules[module.GetType()] = module; }
private WaitCallback SingleReincarnate(IServerModule plugin) { var callback = new WaitCallback(state => { Console.WriteLine("Restarting " + plugin.Name); ModuleManager.ReincarnateModule(plugin); }); return(callback); }
/// <summary> /// Invokes the specified method on the given <see cref="IServerModule"/> instance with the /// given arguments. /// </summary> /// <param name="HandlerModule">The instance on which the method will be invoked.</param> /// <param name="Method">The <see cref="MethodInfo"/> instance that holds information about the method that will be invoked.</param> /// <param name="Arguments">An array of arguments to be passed to the method.</param> /// <returns>The invoked method's return value.</returns> private object InvokeHandlerMethod(IServerModule HandlerModule, MethodInfo Method, object[] Arguments) { #region Error checking if (HandlerModule == null || Method == null || Arguments == null) { return(String.Empty); } #endregion ParameterInfo[] ParamInfo = Method.GetParameters(); object Result = null; //If the method has no parameters: if (ParamInfo.Length == 0) { Result = Method.Invoke(HandlerModule, null); } //If the method has parameters: else { bool HasParams = ParamInfo.Last().GetCustomAttribute(typeof(ParamArrayAttribute)) != null; //If the method has "params"-type parameters: if (HasParams) { object[] RealParameters = new object[ParamInfo.Length]; int ParamsIndex = ParamInfo.Length - 1; //Map the regular parameters for (int i = 0; i < ParamsIndex; i++) { RealParameters[i] = Arguments[i]; } //Map the "params" parameters Type ParamsType = ParamInfo.Last().ParameterType.GetElementType(); Array ParamsValues = Array.CreateInstance(ParamsType, Arguments.Length - ParamsIndex); for (int i = 0; i < ParamsValues.Length; i++) { ParamsValues.SetValue(Arguments[i + ParamsIndex], i); } RealParameters[ParamsIndex] = ParamsValues; Arguments = RealParameters; } Result = Method.Invoke(HandlerModule, Arguments); } return(Result); }
private static IReadOnlyList <ImportingProperty> GetImportingProperties(IServerModule plugin) { var dependencyAttributes = from prop in plugin.GetType().GetProperties() let att = prop.GetCustomAttribute <RequiredModuleApiAttribute>() where att != null select new ImportingProperty { Property = prop, Attribute = att }; return(dependencyAttributes.ToList()); }
private void FillArray(Type propType, ImportingProperty importingProperty, IServerModule module, IDictionary <object, IServerModule> facadeProviders) { var elemType = propType.GetElementType(); var facades = facadeProviders.Keys.Where(elemType.IsInstanceOfType).ToArray(); var facadeArray = Array.CreateInstance(elemType, facades.Length); for (int i = 0; i < facades.Length; i++) { facadeArray.SetValue(facades[i], i); } importingProperty.Property.SetValue(module, facadeArray); }
/// <summary> /// Sends the commands to the module console /// </summary> private void ModuleCommandExecutor(string[] fullCommand, IServerModule module) { var console = module.Console; if (fullCommand[0] == "man") { Console.WriteLine(module.GetType().GetDescription()); } else { console.ExecuteCommand(fullCommand.Skip(2).ToArray(), Console.WriteLine); } }
/// <summary> /// Hozzáad egy modult a szerverhez. /// </summary> /// <param name="Module">A szerverhez csatolandó modul.</param> public void AttachModule(IServerModule Module) { #region Error checking if (Module == null) { return; } if (this.Modules.Any(x => x.ModuleName == Module.ModuleName)) { return; } #endregion this.Modules.Add(Module); }
protected void AddWaitingService(IServerModule dependency, IServerModule dependend) { lock (WaitingModules) { if (WaitingModules.ContainsKey(dependency)) { if (!WaitingModules[dependency].Contains(dependend)) { WaitingModules[dependency].Add(dependend); } } else { WaitingModules[dependency] = new List <IServerModule> { dependend }; } } }
private void FillFacade(Type propType, ImportingProperty importingProperty, IServerModule service, IDictionary <object, IServerModule> facadeProviders) { var match = facadeProviders.Keys.FirstOrDefault(propType.IsInstanceOfType); if (match != null) { importingProperty.Property.SetValue(service, match); } else if (importingProperty.Attribute.IsOptional) { _logger.Log(LogLevel.Warning, "Found no module hosting a facade of type {0} which is referenced by {1}.{2}", propType.Name, service.Name, importingProperty.Property); } else { _logger.Log(LogLevel.Error, "Found no module hosting a facade of type {0} which is required by {1}.{2}", propType.Name, service.Name, importingProperty.Property); importingProperty.Missing = true; } }
/// <summary> /// Opens the module specific console /// </summary> /// <param name="module">The module.</param> private void ModuleSpecificConsole(IServerModule module) { var console = module.Console; Console.Clear(); Console.WriteLine("Welcome to the '{0}' module. Type 'help' to print the possible commands.", module.Name); Console.WriteLine(); var command = string.Empty; while (command != "bye") { WriteModulePostString(module); command = CommandHelper.ReadCommand(ModuleManager); switch (command) { case "help": Console.WriteLine(module.GetType().GetDescription()); break; case "quit": case "bye": case "exit": break; default: var parts = command.Split(' '); Console.WriteLine(); console.ExecuteCommand(parts, Console.WriteLine); Console.WriteLine(); break; } } Console.WriteLine(); Console.WriteLine("Exiting module console...bye!"); Console.WriteLine(); }
/// <summary> /// Finds the module that can execute the specified command and executes it. /// Also sends the result of the invocation to the client. /// </summary> /// <param name="ClientStream">A <see cref="StreamWriter"/> instance where the response is written.</param> /// <param name="Module">The name of the module.</param> /// <param name="Command">The command to execute.</param> /// <param name="Arguments">An array of the command's arguments.</param> /// <returns>True if the command is executed successfully, false if not.</returns> private bool ExecuteHandlerMethod(StreamWriter ClientStream, string Module, string Command, string[] Arguments) { #region Error checking if (ClientStream == null) { return(false); } Arguments = Arguments ?? new string[0]; #endregion IServerModule HandlerModule = this.Modules.FirstOrDefault(x => x.ModuleName == Module); MethodInfo Method = HandlerModule?.GetType().GetMethod(Command); #region Error checking if (HandlerModule == null || Method == null) { return(false); } if (!Method.GetCustomAttributes(typeof(ServerCommandAttribute)).Any()) { return(false); } #endregion object Result = this.InvokeHandlerMethod(HandlerModule, Method, Arguments); ServerResponse <object> Response = ServerResponse <object> .GetSuccess(Result); ClientStream.WriteLine( JsonConvert.SerializeObject(Response, JsonConfig) ); return(true); }
/// <summary> /// Get the start dependencies of the given module. /// </summary> /// <param name="service">The server module for which the dependencies should be fetched.</param> /// <returns>An amount of start dependencies for the requested module.</returns> public IEnumerable <IServerModule> StartDependencies(IServerModule service) { return(_dependencyManager.GetDependencyBranch(service)?.Dependencies.Select(item => item.RepresentedModule) ?? Enumerable.Empty <IServerModule>()); }
/// <summary> /// Get all start dependencies of this plugin /// </summary> public IModuleDependency GetDependencyBranch(IServerModule plugin) { return(_cache.ContainsKey(plugin) ? _cache[plugin] : null); }
/// <summary> /// Initialize a server module /// </summary> /// <param name="module"></param> public void InitializeModule(IServerModule module) { _moduleStarter.Initialize(module); }
/// <summary> /// Start a specific module and all its dependencies /// </summary> /// <param name="module">Module to start</param> public void StartModule(IServerModule module) { _moduleStarter.Start(module); }
/// <summary> /// Stop a specific module /// </summary> /// <param name="module">Module to stop</param> public void StopModule(IServerModule module) { _moduleStopper.Stop(module); }
public void InitializeModule(IServerModule nextModule) { // The runtime does not have a next module - it is always at the very end of the // module pipeline, so there is nothing to do here. }
public void AddModuleAndInitialize(IServerModule module) { AddModule(module); InitializeModules(); }
/// <summary> /// Add a module which is used to check if the user have access to execute the incoming message /// </summary> /// <param name="module">Module</param> /// <remarks> /// <para> /// You can for instance user role based authentication on each message to verify that /// </para> /// </remarks> public void AddAuthorization(IServerModule module) { if (module == null) throw new ArgumentNullException("module"); _authorizeModules.Add(module); }
public void InitializeModule(IServerModule nextModule) { // The runtime does not have a next module - it is always at the very end of the // module pipeline, so there is nothing to do here. }
public bool ContainsModule(IServerModule module) { return(_modules.ContainsKey(module.GetType())); }
/// <summary> /// Get or set a services behaviour using /// </summary> /// <typeparam name="T">Type of behaviour</typeparam> public IBehaviourAccess <T> BehaviourAccess <T>(IServerModule plugin) { return(ABehaviourAccess.Create <T>(_config, plugin)); }
/// <summary> /// Add a module which is designed to handle certain kind of requests. /// </summary> /// <param name="module">Module</param> /// <remarks> /// <para> /// Used to process messages to generate responses. /// </para> /// </remarks> public void AddPostHandler(IServerModule module) { if (module == null) throw new ArgumentNullException("module"); _requestModules.Add(module); }
public ModuleDependencyBranch(IServerModule representedModule) { RepresentedModule = representedModule; }