internal void UpdateFrom( IConfigurationSolver solver ) { // 1 - Removes existing items from live info that do not exist anymore in the new running context. // This raises Collection "item removed" events. // _services.RemoveWhereAndReturnsRemoved( s => solver.FindService( s.ServiceInfo.ServiceFullName ) == null ).Count(); _plugins.RemoveWhereAndReturnsRemoved( p => solver.FindPlugin( p.PluginInfo.PluginFullName ) == null ).Count(); DelayedPropertyNotification notifier = new DelayedPropertyNotification(); // 2 - Builds two lists of new Services and new Plugins and for already existing ones, // updates them with the new information. // This update does not trigger any ProprtyChanged events and consider only // direct properties of the object. // Changes to linked items (such as a Generalization reference for instance will be // done later thanks to their Bind method. // List<LiveServiceInfo> servicesToAdd = new List<LiveServiceInfo>(); foreach( var s in solver.AllServices ) { LiveServiceInfo ls = _services.GetByKey( s.ServiceInfo.ServiceFullName ); if( ls == null ) servicesToAdd.Add( new LiveServiceInfo( s, _engine ) ); else ls.UpdateFrom( s, notifier ); } List<LivePluginInfo> pluginsToAdd = new List<LivePluginInfo>(); foreach( var p in solver.AllPlugins ) { LivePluginInfo lp = _plugins.GetByKey( p.PluginInfo.PluginFullName ); if( lp == null ) pluginsToAdd.Add( new LivePluginInfo( p, _engine ) ); else lp.UpdateFrom( p, notifier ); } // 3 - Intrinsic properties have been updated. We now consider the properties that reference other items. // Func<string,LiveServiceInfo> serviceFinder = name => _services.GetByKey( name ) ?? servicesToAdd.First( ls => ls.ServiceInfo.ServiceFullName == name ); Func<string,LivePluginInfo> pluginFinder = id => _plugins.GetByKey( id ) ?? pluginsToAdd.First( lp => lp.PluginInfo.PluginFullName == id ); using( notifier.SilentMode() ) { foreach( var ls in servicesToAdd ) ls.Bind( solver.FindExistingService( ls.ServiceInfo.ServiceFullName ), serviceFinder, pluginFinder, notifier ); } foreach( var ls in _services ) ls.Bind( solver.FindExistingService( ls.ServiceInfo.ServiceFullName ), serviceFinder, pluginFinder, notifier ); using( notifier.SilentMode() ) { foreach( var lp in pluginsToAdd ) lp.Bind( solver.FindExistingPlugin( lp.PluginInfo.PluginFullName ), serviceFinder, notifier ); } foreach( var lp in _plugins ) lp.Bind( solver.FindExistingPlugin( lp.PluginInfo.PluginFullName ), serviceFinder, notifier ); // 4 - It is time to add the new comers: this raises Collection changed "item added" events. foreach( var ls in servicesToAdd ) _services.Add( ls ); foreach( var lp in pluginsToAdd ) _plugins.Add( lp ); // 5 - Raises all PropertyChanged events for all objects. notifier.RaiseEvents(); }
public IEnumerable <ServiceData> GetIncludedServices(StartDependencyImpact impact, bool forRunnableStatus) { if (_runningIncludedServices == null) { var running = Service != null ? new HashSet <ServiceData>(Service.InheritedServicesWithThis) : new HashSet <ServiceData>(); foreach (var sRef in PluginInfo.ServiceReferences) { if (sRef.Requirement == DependencyRequirement.Running) { running.Add(_solver.FindExistingService(sRef.Reference.ServiceFullName)); } } _runningIncludedServices = running.ToReadOnlyList(); bool newRunnableAdded = false; foreach (var sRef in PluginInfo.ServiceReferences) { if (sRef.Requirement == DependencyRequirement.Runnable) { newRunnableAdded |= running.Add(_solver.FindExistingService(sRef.Reference.ServiceFullName)); } } _runnableIncludedServices = newRunnableAdded ? running.ToReadOnlyList() : _runningIncludedServices; } if (impact == StartDependencyImpact.Minimal) { return(forRunnableStatus ? _runnableIncludedServices : _runningIncludedServices); } if (_inclServices == null) { _inclServices = new IReadOnlyList <ServiceData> [8]; } int iImpact = (int)impact; if (impact > StartDependencyImpact.Minimal) { --impact; } if (forRunnableStatus) { iImpact *= 2; } --iImpact; IReadOnlyList <ServiceData> i = _inclServices[iImpact]; if (i == null) { var baseSet = forRunnableStatus ? _runnableIncludedServices : _runningIncludedServices; var incl = new HashSet <ServiceData>(baseSet); bool newAdded = false; foreach (var sRef in PluginInfo.ServiceReferences) { ServiceData sr = _solver.FindExistingService(sRef.Reference.ServiceFullName); switch (sRef.Requirement) { case DependencyRequirement.RunnableRecommended: { if (impact >= StartDependencyImpact.StartRecommended) { newAdded |= incl.Add(sr); } break; } case DependencyRequirement.Runnable: { if (impact == StartDependencyImpact.FullStart) { newAdded |= incl.Add(sr); } break; } case DependencyRequirement.OptionalRecommended: { if (impact >= StartDependencyImpact.StartRecommended) { newAdded |= incl.Add(sr); } break; } case DependencyRequirement.Optional: { if (impact == StartDependencyImpact.FullStart) { newAdded |= incl.Add(sr); } break; } } } i = _inclServices[iImpact] = newAdded ? incl.ToReadOnlyList() : baseSet; } return(i); }
internal void UpdateFrom(IConfigurationSolver solver) { // 1 - Removes existing items from live info that do not exist anymore in the new running context. // This raises Collection "item removed" events. // _services.RemoveWhereAndReturnsRemoved(s => solver.FindService(s.ServiceInfo.ServiceFullName) == null).Count(); _plugins.RemoveWhereAndReturnsRemoved(p => solver.FindPlugin(p.PluginInfo.PluginFullName) == null).Count(); DelayedPropertyNotification notifier = new DelayedPropertyNotification(); // 2 - Builds two lists of new Services and new Plugins and for already existing ones, // updates them with the new information. // This update does not trigger any ProprtyChanged events and consider only // direct properties of the object. // Changes to linked items (such as a Generalization reference for instance will be // done later thanks to their Bind method. // List <LiveServiceInfo> servicesToAdd = new List <LiveServiceInfo>(); foreach (var s in solver.AllServices) { LiveServiceInfo ls = _services.GetByKey(s.ServiceInfo.ServiceFullName); if (ls == null) { servicesToAdd.Add(new LiveServiceInfo(s, _engine)); } else { ls.UpdateFrom(s, notifier); } } List <LivePluginInfo> pluginsToAdd = new List <LivePluginInfo>(); foreach (var p in solver.AllPlugins) { LivePluginInfo lp = _plugins.GetByKey(p.PluginInfo.PluginFullName); if (lp == null) { pluginsToAdd.Add(new LivePluginInfo(p, _engine)); } else { lp.UpdateFrom(p, notifier); } } // 3 - Intrinsic properties have been updated. We now consider the properties that reference other items. // Func <string, LiveServiceInfo> serviceFinder = name => _services.GetByKey(name) ?? servicesToAdd.First(ls => ls.ServiceInfo.ServiceFullName == name); Func <string, LivePluginInfo> pluginFinder = id => _plugins.GetByKey(id) ?? pluginsToAdd.First(lp => lp.PluginInfo.PluginFullName == id); using (notifier.SilentMode()) { foreach (var ls in servicesToAdd) { ls.Bind(solver.FindExistingService(ls.ServiceInfo.ServiceFullName), serviceFinder, pluginFinder, notifier); } } foreach (var ls in _services) { ls.Bind(solver.FindExistingService(ls.ServiceInfo.ServiceFullName), serviceFinder, pluginFinder, notifier); } using (notifier.SilentMode()) { foreach (var lp in pluginsToAdd) { lp.Bind(solver.FindExistingPlugin(lp.PluginInfo.PluginFullName), serviceFinder, notifier); } } foreach (var lp in _plugins) { lp.Bind(solver.FindExistingPlugin(lp.PluginInfo.PluginFullName), serviceFinder, notifier); } // 4 - It is time to add the new comers: this raises Collection changed "item added" events. foreach (var ls in servicesToAdd) { _services.Add(ls); } foreach (var lp in pluginsToAdd) { _plugins.Add(lp); } // 5 - Raises all PropertyChanged events for all objects. notifier.RaiseEvents(); }
internal PluginData(IConfigurationSolver solver, IPluginInfo p, ServiceData service, ConfigurationStatus pluginStatus, StartDependencyImpact impact = StartDependencyImpact.Unknown) { _solver = solver; PluginInfo = p; Service = service; ConfigOriginalStatus = pluginStatus; switch (pluginStatus) { case ConfigurationStatus.Disabled: _configSolvedStatus = SolvedConfigurationStatus.Disabled; break; case ConfigurationStatus.Running: _configSolvedStatus = SolvedConfigurationStatus.Running; break; default: _configSolvedStatus = SolvedConfigurationStatus.Runnable; break; } _configSolvedStatusReason = PluginRunningRequirementReason.Config; RawConfigSolvedImpact = ConfigOriginalImpact = impact; if (RawConfigSolvedImpact == StartDependencyImpact.Unknown && Service != null) { RawConfigSolvedImpact = Service.ConfigSolvedImpact; } _configSolvedImpact = RawConfigSolvedImpact; if (_configSolvedImpact == StartDependencyImpact.Unknown || (_configSolvedImpact & StartDependencyImpact.IsTryOnly) != 0) { _configSolvedImpact = StartDependencyImpact.Minimal; } if (ConfigOriginalStatus == ConfigurationStatus.Disabled) { _configDisabledReason = PluginDisabledReason.Config; } else if (p.HasError) { _configDisabledReason = PluginDisabledReason.PluginInfoHasError; } else if (Service != null) { if (Service.Disabled) { _configDisabledReason = PluginDisabledReason.ServiceIsDisabled; } else if (Service.Family.RunningPlugin != null) { _configDisabledReason = PluginDisabledReason.AnotherRunningPluginExistsInFamilyByConfig; } } // Immediately check for Runnable references to Disabled Services: this disables us. if (!Disabled) { foreach (var sRef in PluginInfo.ServiceReferences) { if (sRef.Requirement >= DependencyRequirement.Runnable) { // If the required service is already disabled, we immediately disable this plugin. if (sRef.Reference.HasError && !Disabled) { _configDisabledReason = PluginDisabledReason.RunnableReferenceServiceIsOnError; break; } ServiceData sr = _solver.FindExistingService(sRef.Reference.ServiceFullName); if (sr.Disabled && !Disabled) { _configDisabledReason = PluginDisabledReason.RunnableReferenceIsDisabled; break; } } } } if (Service != null) { Service.AddPlugin(this); } if (!Disabled) { // If the plugin is not yet disabled, we register it: // whenever the referenced service is disabled (or stopped during dynamic resolution), this // will disable (or stop) the plugin according to its ConfigSolvedImpact. foreach (var sRef in PluginInfo.ServiceReferences) { _solver.FindExistingService(sRef.Reference.ServiceFullName).RegisterPluginReference(this, sRef.Requirement); } if (Service != null && ConfigOriginalStatus == ConfigurationStatus.Running) { Service.Family.SetRunningPlugin(this); } } }
internal PluginData( IConfigurationSolver solver, IPluginInfo p, ServiceData service, ConfigurationStatus pluginStatus, StartDependencyImpact impact = StartDependencyImpact.Unknown ) { _solver = solver; PluginInfo = p; Service = service; ConfigOriginalStatus = pluginStatus; switch( pluginStatus ) { case ConfigurationStatus.Disabled: _configSolvedStatus = SolvedConfigurationStatus.Disabled; break; case ConfigurationStatus.Running: _configSolvedStatus = SolvedConfigurationStatus.Running; break; default: _configSolvedStatus = SolvedConfigurationStatus.Runnable; break; } _configSolvedStatusReason = PluginRunningRequirementReason.Config; RawConfigSolvedImpact = ConfigOriginalImpact = impact; if( RawConfigSolvedImpact == StartDependencyImpact.Unknown && Service != null ) { RawConfigSolvedImpact = Service.ConfigSolvedImpact; } _configSolvedImpact = RawConfigSolvedImpact; if( _configSolvedImpact == StartDependencyImpact.Unknown || (_configSolvedImpact & StartDependencyImpact.IsTryOnly) != 0 ) { _configSolvedImpact = StartDependencyImpact.Minimal; } if( ConfigOriginalStatus == ConfigurationStatus.Disabled ) { _configDisabledReason = PluginDisabledReason.Config; } else if( p.HasError ) { _configDisabledReason = PluginDisabledReason.PluginInfoHasError; } else if( Service != null ) { if( Service.Disabled ) { _configDisabledReason = PluginDisabledReason.ServiceIsDisabled; } else if( Service.Family.RunningPlugin != null ) { _configDisabledReason = PluginDisabledReason.AnotherRunningPluginExistsInFamilyByConfig; } } // Immediately check for Runnable references to Disabled Services: this disables us. if( !Disabled ) { foreach( var sRef in PluginInfo.ServiceReferences ) { if( sRef.Requirement >= DependencyRequirement.Runnable ) { // If the required service is already disabled, we immediately disable this plugin. if( sRef.Reference.HasError && !Disabled ) { _configDisabledReason = PluginDisabledReason.RunnableReferenceServiceIsOnError; break; } ServiceData sr = _solver.FindExistingService( sRef.Reference.ServiceFullName ); if( sr.Disabled && !Disabled ) { _configDisabledReason = PluginDisabledReason.RunnableReferenceIsDisabled; break; } } } } if( Service != null ) Service.AddPlugin( this ); if( !Disabled ) { // If the plugin is not yet disabled, we register it: // whenever the referenced service is disabled (or stopped during dynamic resolution), this // will disable (or stop) the plugin according to its ConfigSolvedImpact. foreach( var sRef in PluginInfo.ServiceReferences ) { _solver.FindExistingService( sRef.Reference.ServiceFullName ).RegisterPluginReference( this, sRef.Requirement ); } if( Service != null && ConfigOriginalStatus == ConfigurationStatus.Running ) { Service.Family.SetRunningPlugin( this ); } } }