SolvedConfigStatus SolveStatus(Guid pluginId)
        {
            // Set default status/actions
            ConfigPluginStatus finalStatus = ConfigPluginStatus.Manual;
            ConfigUserAction   userAction  = ConfigUserAction.None;

            if (finalStatus != ConfigPluginStatus.Disabled)
            {
                // Gets the systemStatus, if any.
                ConfigPluginStatus systemStatus = _cfg.GetSystemConfiguration(false).PluginStatusCollection.GetStatus(pluginId, finalStatus);
                // Sets it if more restrictive
                if (systemStatus > finalStatus || systemStatus == ConfigPluginStatus.Disabled)
                {
                    finalStatus = systemStatus;
                }

                if (finalStatus != ConfigPluginStatus.Disabled)
                {
                    // Gets the user status, if any.
                    ConfigPluginStatus userStatus = _cfg.GetUserConfiguration(false).PluginStatusCollection.GetStatus(pluginId, finalStatus);
                    // Sets it if more restrictive.
                    if (userStatus > finalStatus || userStatus == ConfigPluginStatus.Disabled)
                    {
                        finalStatus = userStatus;
                    }

                    if (finalStatus != ConfigPluginStatus.Disabled)
                    {
                        // Gets the UserAction, if any.
                        userAction = _cfg.GetUserConfiguration(false).LiveUserConfiguration.GetAction(pluginId);
                    }
                }
            }
            // Solves UserAction and finalStatus
            SolvedConfigStatus solvedStatus = finalStatus == ConfigPluginStatus.Disabled ? SolvedConfigStatus.Disabled : SolvedConfigStatus.Optional;

            if (userAction == ConfigUserAction.Started || (finalStatus == ConfigPluginStatus.AutomaticStart && userAction != ConfigUserAction.Stopped))
            {
                solvedStatus = SolvedConfigStatus.MustExistAndRun;
            }
            else if (userAction == ConfigUserAction.Stopped)
            {
                solvedStatus = SolvedConfigStatus.Disabled;
            }
            return(solvedStatus);
        }
Ejemplo n.º 2
0
 private bool DoUpdateStatus(bool isAvailable, SolvedConfigStatus s)
 {
     if (FinalStatus == (SolvedConfigStatus)(-1))
     {
         // Initialization, two cases:
         // - The plugin/service is available: we must trigger a change only if the SolvedConfigStatus differs from Optional.
         // - The plugin/service is NOT available: we must trigger a change only if the SolvedConfigStatus differs from Disabled.
         FinalStatus   = isAvailable ? SolvedConfigStatus.Optional : SolvedConfigStatus.Disabled;
         RunningStatus = FinalStatus;
     }
     // Already initialized.
     if (s != FinalStatus)
     {
         FinalStatus = s;
         return(true);
     }
     return(false);
 }
        private SolvedPluginConfigElement SetStatus(Guid pluginId)
        {
            SolvedConfigStatus        newSolvedStatus = SolveStatus(pluginId);
            SolvedPluginConfigElement currentElement;

            if (_dic.TryGetValue(pluginId, out currentElement))
            {
                if (currentElement.Status == newSolvedStatus)
                {
                    return(null);
                }
                currentElement.Status = newSolvedStatus;
            }
            else
            {
                currentElement = new SolvedPluginConfigElement(pluginId, newSolvedStatus);
                _dic.Add(pluginId, currentElement);
            }
            return(currentElement);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Launches ComputeCombination for each "plugin status combination".
        /// Gets the lower cost among all the combinations generated.
        /// </summary>
        internal ExecutionPlan ObtainBestPlan(Dictionary <object, SolvedConfigStatus> finalConfig, bool stopLaunchedOptionals)
        {
            _finalConfig = finalConfig;
            if (_parseMap == null)
            {
                _parseMap = new BitArray(_discoverer.Plugins.Count);
            }
            else
            {
                _parseMap.Length = _discoverer.Plugins.Count;
            }
            _mappingArray.Clear();
            _mappingDic.Clear();

            int disabledCount = 0;

            // Locking plugins :
            // - If a plugin is disabled, it should not be launched, we do not add it to the map
            // - If a plugin needs to be started (MustExistAndRun),  we lock its value to true
            // - If a plugin is the only implemention of a service and that this service has to be started, we lock this plugin's value to true
            // - If a plugin has no service references and does not implement any services as well, and that it is not asked to be
            //   started and it is NOT running or it is running but stopLaunchedOptionals is true, we lock its value to false;
            int index = 0;

            foreach (IPluginInfo pI in _discoverer.Plugins)
            {
                // SolvedConfigStatus of the actual plugin.
                SolvedConfigStatus pluginStatus = _finalConfig.GetValueWithDefault(pI, SolvedConfigStatus.Optional);
                if (pluginStatus == SolvedConfigStatus.Disabled)
                {
                    // If a plugin is disabled, it should not be launched, we do not add it to the map.
                    disabledCount++;
                    continue;
                }

                // SolvedConfigStatus of the implemented service if any.
                SolvedConfigStatus serviceStatus = pI.Service != null
                    ? _finalConfig.GetValueWithDefault(pI.Service, SolvedConfigStatus.Optional)
                    : SolvedConfigStatus.Optional;

                if (serviceStatus == SolvedConfigStatus.Disabled)
                {
                    // If a plugin is disabled, it should not be launched, we do not add it to the map
                    disabledCount++;
                    continue;
                }

                // Here, we have no more disabled plugins.
                // Initializes a PluginData for this particular plugin and allocates
                // a new index in the bit array.
                Debug.Assert(index == _mappingArray.Count);
                PluginData pluginData = new PluginData(pI, index, IsPluginRunning(pI));
                _mappingArray.Add(pluginData);
                _mappingDic.Add(pI, pluginData);

                if (pluginStatus == SolvedConfigStatus.MustExistAndRun ||
                    (serviceStatus == SolvedConfigStatus.MustExistAndRun && pI.Service.Implementations.Count == 1))
                {
                    // If a plugin needs to be started (MustExistAndRun), we lock its value to true.
                    // If a plugin is the only implemention of a service and that this service has to be started, we lock this plugin's value to true.
                    _parseMap.Set(index, true);
                    pluginData.Locked = true;
                }
                else if (pI.Service == null && pI.ServiceReferences.Count == 0)  // This plugin is independent.
                {
                    // This is only an optimization.
                    // The cost function gives a cost to the stop or the start of a plugin. When a plugin is independant like in this case, we lock its
                    // status by taking into account the requirement (should it run? MustExistTryStart/OptionalTryStart) and its current status (IsPluginRunning)
                    // and the stopLaunchedOptionals boolean.
                    if ((pluginStatus != SolvedConfigStatus.MustExistTryStart || pluginStatus != SolvedConfigStatus.OptionalTryStart) &&
                        (!pluginData.IsRunning || stopLaunchedOptionals))
                    {
                        // If a plugin has no service references and does not implement any services as well,
                        // and that it is not asked to be started AND it is not running, we lock its value to false;
                        _parseMap.Set(index, false);
                        // We do not set thereWillBeNoChange to false: there will ACTUALLY be no changes
                        // since the plugin is NOT running.
                    }
                    else
                    {
                        // If a plugin has no service references and does not implement any services as well,
                        // and that it is asked to be started OR is currently running, we lock its value to true;
                        _parseMap.Set(index, true);
                    }
                    pluginData.Locked = true;
                }
                index++;
            }

            // Trim the parseMap, to remove indexes that should have been filled by disabled plugins.
            Debug.Assert(_parseMap.Length >= disabledCount);
            _parseMap.Length -= disabledCount;

            // If the parseMap has a length of 0, it means either that there are no plugins or that all plugins are disabled.
            // In either of these cases, we don't calculate any execution plan. But we still have a valid execution plan, it just doesn't have any plugins to launch.

            BitArray bestCombination = _parseMap;

            if (_parseMap.Length > 0)
            {
                int    bestCost          = Int32.MaxValue;
                double combinationsCount = Math.Pow(2, _parseMap.Length - _mappingDic.Values.Count((e) => { return(e.Locked == true); }));

                for (int i = 0; i < combinationsCount; i++)
                {
                    int cost = ComputeCombination(stopLaunchedOptionals);
                    Debug.Assert(cost >= 0);
                    // Return if the cost is equal to 0 (no better solution).
                    if (cost == 0)
                    {
                        return(_lastBestPlan = GenerateExecutionPlan(_parseMap));
                    }
                    if (cost < bestCost)
                    {
                        bestCost        = cost;
                        bestCombination = (BitArray)_parseMap.Clone();
                    }
                    GenerateNextCombination();
                }
                // If there is no valid combination, we return an impossible plan and
                // we do not keep it as the LastBestPlan.
                if (bestCost == Int32.MaxValue)
                {
                    return(GenerateExecutionPlan(null));
                }
            }
            return(_lastBestPlan = GenerateExecutionPlan(bestCombination));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets the index of the plugin which cost to calculate, together with the current parseMap
        /// Returns how much launching (or not) this plugin costs.
        /// </summary>
        /// <param name="i">The index of the plugin to compute</param>
        /// <returns>The plugin's cost</returns>
        int ComputeElementCost(int i, bool stopLaunchedOptionals)
        {
            int cost = 0;

            // Gets the actual plugin's SolvedConfigStatus.
            PluginData  plugin       = _mappingArray[i];
            IPluginInfo actualPlugin = plugin.PluginInfo;

            Debug.Assert(actualPlugin != null);

            SolvedConfigStatus status = _finalConfig.GetValueWithDefault(actualPlugin, SolvedConfigStatus.Optional);

            if (actualPlugin.Service != null)
            {
                var serviceStatus = _finalConfig.GetValueWithDefault(actualPlugin.Service.AssemblyQualifiedName, SolvedConfigStatus.Optional);
                status = status < serviceStatus ? serviceStatus : status;
            }

            // If the plugin has to be started.
            if (_parseMap[i])
            {
                // Check its references.
                foreach (IServiceReferenceInfo serviceRef in actualPlugin.ServiceReferences)
                {
                    if (!CheckReference(serviceRef, _parseMap, ref cost))
                    {
                        return(int.MaxValue);
                    }
                }

                #region Check the cost regarding the plugin's requirement, when the plugin is to be started

                // If the plugin needs to be started, but its not currently running.
                // we increase the cost only if the plugin is not absolutely needed.
                if (!plugin.IsRunning)
                {
                    switch (status)
                    {
                    case SolvedConfigStatus.Optional:
                    case SolvedConfigStatus.MustExist:
                        cost += 10;
                        break;

                    case SolvedConfigStatus.Disabled:
                        return(Int32.MaxValue);
                    }
                }

                #endregion
            }
            // If the plugin doesn't need to be started (0 in the parseMap)
            else
            {
                // Here we check if the plugin can be stopped

                // If the plugin implements a service, and if the service has a MustExistAndRun requirement
                // and if this plugin is the only implementation of this service, so we return the max value.
                // Otherwise, if we find a substitute, the combinaison is possible.
                if (actualPlugin.Service != null)
                {
                    bool substitue = false;

                    if (_finalConfig.GetValueWithDefault(actualPlugin.Service, SolvedConfigStatus.Optional) == SolvedConfigStatus.MustExistAndRun)
                    {
                        for (int idx = 0; idx < _parseMap.Length; idx++)
                        {
                            if (_parseMap[idx] &&
                                _mappingArray[idx].PluginInfo.Service != null &&
                                _mappingArray[idx].PluginInfo.Service == actualPlugin.Service)
                            {
                                substitue = true;
                                break;
                            }
                        }
                        if (!substitue)
                        {
                            return(int.MaxValue);
                        }
                    }
                }
                else if (status == SolvedConfigStatus.MustExistAndRun)
                {
                    return(int.MaxValue);
                }

                // If this plugin is already running and stopLaunchedOptionals is set to false, don't stop it.
                if (plugin.IsRunning && !stopLaunchedOptionals)
                {
                    cost += 10;
                }

                #region Check the cost regarding the plugin's requirement when the plugin won't be started

                // if we wanted this plugin started ...
                if (status == SolvedConfigStatus.MustExistTryStart || status == SolvedConfigStatus.OptionalTryStart)
                {
                    cost += 10;
                }

                #endregion
            }

            return(cost);
        }
 public SolvedPluginConfigElement( Guid pluginId, SolvedConfigStatus status )
 {
     PluginId = pluginId;
     Status = status;
 }
Ejemplo n.º 7
0
 /// <summary>
 /// A new FinalResult is created the first time the PluginId is met.
 /// Since we do not even know if it exists in the discoverer, we set its
 /// status to "unknown" (-1).
 /// If it is not here, nothing changed if the status is Disabled.
 /// If it is available, nothing changed if the status is Optional.
 /// </summary>
 public FinalResult()
 {
     FinalStatus   = (SolvedConfigStatus)(-1);
     RunningStatus = (SolvedConfigStatus)(-1);
 }
Ejemplo n.º 8
0
 public void SetRunningStatus(SolvedConfigStatus configured)
 {
     RunningStatus = configured;
 }
Ejemplo n.º 9
0
 public SolvedPluginConfigElement(Guid pluginId, SolvedConfigStatus status)
 {
     PluginId = pluginId;
     Status   = status;
 }