private bool TryMatchStarMapping(StringSegment host, StringSegment hostOnly, StringSegment path, out ShellSettings result) { if (TryMatchInternal("*." + host, "*." + hostOnly, path, out result)) { return(true); } var index = -1; // Take the longest subdomain and look for a mapping while (-1 != (index = host.IndexOf('.', index + 1))) { if (TryMatchInternal("*" + host.Subsegment(index), "*" + hostOnly.Subsegment(index), path, out result)) { return(true); } } result = null; return(false); }
private bool TryMatchInternal(StringSegment host, StringSegment hostOnly, StringSegment path, out ShellSettings result) { // 1. Search for Host:Port + Prefix match if (host.Length == 0 || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, path), out result)) { // 2. Search for Host + Prefix match if (host.Length == hostOnly.Length || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(hostOnly, path), out result)) { // 3. Search for Host:Port only match if (host.Length == 0 || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, "/"), out result)) { // 4. Search for Host only match if (host.Length == hostOnly.Length || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(hostOnly, "/"), out result)) { // 5. Search for Prefix only match if (!_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix("", path), out result)) { result = null; return(false); } } } } } return(true); }
private bool TryMatchStarMapping(StringSegment host, StringSegment hostOnly, StringSegment path, out ShellSettings result) { if (this.TryMatchInternal(StringSegment.op_Implicit(string.Concat("*.", host.ToString())), StringSegment.op_Implicit(string.Concat("*.", hostOnly.ToString())), path, out result)) { return(true); } V_0 = -1; do { stackVariable21 = host.IndexOf('.', V_0 + 1); V_0 = stackVariable21; if (-1 != stackVariable21) { continue; } result = null; return(false); }while (!this.TryMatchInternal(StringSegment.op_Implicit(string.Concat("*", host.Subsegment(V_0).ToString())), StringSegment.op_Implicit(string.Concat("*", hostOnly.Subsegment(V_0).ToString())), path, out result)); return(true); }
public bool TryGetSettings(string name, out ShellSettings settings) { settings = LoadSettings().First(); return(true); }
public Task UpdateShellSettingsAsync(ShellSettings settings) { _shellSettingsManager.SaveSettings(settings); return(ReloadShellContextAsync(settings)); }
public async Task SaveSettingsAsync(ShellSettings settings) { await _semaphore.WaitAsync(); try { await EnsureConfigurationAsync(); if (settings == null) { throw new ArgumentNullException(nameof(settings)); } var configuration = new ConfigurationBuilder() .AddConfiguration(_configuration) .AddConfiguration(_configuration.GetSection(settings.Name)) .Build(); var shellSettings = new ShellSettings() { Name = settings.Name }; configuration.Bind(shellSettings); var configSettings = JObject.FromObject(shellSettings); var tenantSettings = JObject.FromObject(settings); foreach (var property in configSettings) { var tenantValue = tenantSettings.Value <string>(property.Key); var configValue = configSettings.Value <string>(property.Key); if (tenantValue != configValue) { tenantSettings[property.Key] = tenantValue; } else { tenantSettings[property.Key] = null; } } tenantSettings.Remove("Name"); await _settingsSources.SaveAsync(settings.Name, tenantSettings.ToObject <Dictionary <string, string> >()); var tenantConfig = new JObject(); var sections = settings.ShellConfiguration.GetChildren() .Where(s => !s.GetChildren().Any()) .ToArray(); foreach (var section in sections) { if (settings[section.Key] != configuration[section.Key]) { tenantConfig[section.Key] = settings[section.Key]; } else { tenantConfig[section.Key] = null; } } tenantConfig.Remove("Name"); await _tenantConfigSemaphore.WaitAsync(); try { await _tenantConfigSources.SaveAsync(settings.Name, tenantConfig.ToObject <Dictionary <string, string> >()); } finally { _tenantConfigSemaphore.Release(); } } finally { _semaphore.Release(); } }
public void UpdateShellSettings(ShellSettings settings) { _shellSettingsManager.SaveSettings(settings); ReloadShellContext(settings); }
public async Task <IServiceScope> GetScopeAsync(ShellSettings settings) { return((await GetScopeAndContextAsync(settings)).Scope); }
private bool TryMatchInternal(string host, string appRelativePath, bool fallbackToDefault, out ShellSettings result) { // We can skip some checks for port matching if we know the host doesn't contain one var hasPort = host.Contains(':'); // 1. Search for Host:Port + Prefix match if (!hasPort || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, appRelativePath, true), out result)) { // 2. Search for Host + Prefix match if (!_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, appRelativePath, false), out result)) { // 3. Search for Host:Port only match if (!hasPort || !_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, "/", true), out result)) { // 4. Search for Host only match if (!_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix(host, "/", false), out result)) { // 5. Search for Prefix only match if (!_shellsByHostAndPrefix.TryGetValue(GetHostAndPrefix("", appRelativePath, false), out result)) { result = null; return(false); } } } } } return(true); }
public Task ChangedAsync(ShellDescriptor descriptor, ShellSettings settings) { return(this.ReleaseShellContextAsync(settings)); }
private bool TryMatchStarMapping(string host, string appRelativePath, bool fallbackToDefault, out ShellSettings result) { if (TryMatchInternal("*." + host, appRelativePath, fallbackToDefault, out result)) { return(true); } var index = -1; // Take the longest subdomain and look for a mapping while (-1 != (index = host.IndexOf('.', index + 1))) { if (TryMatchInternal("*" + host.Substring(index), appRelativePath, fallbackToDefault, out result)) { return(true); } } result = null; return(false); }
public Task SaveSettingsAsync(ShellSettings shellSettings) { return(Task.get_CompletedTask()); }
public Task <IEnumerable <ShellSettings> > LoadSettingsAsync() { stackVariable1 = new ShellSettings[1]; stackVariable1[0] = this.CreateDefaultSettings(); return(Task.FromResult <IEnumerable <ShellSettings> >(stackVariable1.AsEnumerable <ShellSettings>())); }
public async Task UpdateShellSettingsAsync(ShellSettings settings) { await _shellSettingsManager.SaveSettingsAsync(settings); await ReloadShellContextAsync(settings); }
public Task SaveSettingsAsync(ShellSettings shellSettings) => Task.CompletedTask;
public void SaveSettings(ShellSettings shellSettings) { }
/// <summary> /// A feature is enabled / disabled, the tenant needs to be released so that a new shell will be built. /// </summary> public Task ChangedAsync(ShellDescriptor descriptor, ShellSettings settings) => ReleaseShellContextAsync(settings);
public async Task <(IServiceScope Scope, ShellContext ShellContext)> GetScopeAndContextAsync(ShellSettings settings) { IServiceScope scope = null; ShellContext shellContext = null; while (scope == null) { if (!_shellContexts.TryGetValue(settings.Name, out shellContext)) { shellContext = await GetOrCreateShellContextAsync(settings); } // We create a scope before checking if the shell has been released. scope = shellContext.CreateScope(); // If CreateScope() returned null, the shell is released. We then remove it and // retry with the hope to get one that won't be released before we create a scope. if (scope == null) { // If the context is released, it is removed from the dictionary so that // a new call on 'GetScope' will recreate a new shell context. _shellContexts.TryRemove(settings.Name, out var value); } } return(scope, shellContext); }
/// <summary> /// Reloads the settings and releases the shell so that a new one will be /// built for subsequent requests, while existing requests get flushed. /// </summary> /// <param name="settings">The <see cref="ShellSettings"/> to reload.</param> /// <param name="eventSource"> /// Whether the related <see cref="ShellEvent"/> is invoked. /// </param> public async Task ReloadShellContextAsync(ShellSettings settings, bool eventSource = true) { if (ReloadingAsync != null && eventSource && settings.State != TenantState.Initializing) { foreach (var d in ReloadingAsync.GetInvocationList()) { await((ShellEvent)d)(settings.Name); } } // A disabled shell still in use will be released by its last scope. if (!CanReleaseShell(settings)) { _runningShellTable.Remove(settings); return; } if (settings.State != TenantState.Initializing) { settings = await _shellSettingsManager.LoadSettingsAsync(settings.Name); } var count = 0; while (count < ReloadShellMaxRetriesCount) { count++; if (_shellContexts.TryRemove(settings.Name, out var context)) { _runningShellTable.Remove(settings); context.Release(); } // Add a 'PlaceHolder' allowing to retrieve the settings until the shell will be rebuilt. if (!_shellContexts.TryAdd(settings.Name, new ShellContext.PlaceHolder { Settings = settings })) { // Atomicity: We may have been the last to load the settings but unable to add the shell. continue; } _shellSettings[settings.Name] = settings; if (CanRegisterShell(settings)) { _runningShellTable.Add(settings); } if (settings.State == TenantState.Initializing) { return; } var currentVersionId = settings.VersionId; settings = await _shellSettingsManager.LoadSettingsAsync(settings.Name); // Consistency: We may have been the last to add the shell but not with the last settings. if (settings.VersionId == currentVersionId) { return; } } throw new ShellHostReloadException( $"Unable to reload the tenant '{settings.Name}' as too many concurrent processes are trying to do so."); }
public ShellSettings(ShellSettings settings) { _settings = new ShellConfiguration(settings._settings); _configuration = new ShellConfiguration(settings.Name, settings._configuration); Name = settings.Name; }
/// <summary> /// Tries to retrieve the shell settings associated with the specified tenant. /// </summary> public bool TryGetSettings(string name, out ShellSettings settings) => _shellSettings.TryGetValue(name, out settings);
private bool TryMatchInternal(StringSegment host, StringSegment hostOnly, StringSegment path, out ShellSettings result) { if (host.get_Length() != 0 && this._shellsByHostAndPrefix.TryGetValue(this.GetHostAndPrefix(host, path), out result) || host.get_Length() != hostOnly.get_Length() && this._shellsByHostAndPrefix.TryGetValue(this.GetHostAndPrefix(hostOnly, path), out result) || host.get_Length() != 0 && this._shellsByHostAndPrefix.TryGetValue(this.GetHostAndPrefix(host, StringSegment.op_Implicit("/")), out result) || host.get_Length() != hostOnly.get_Length() && this._shellsByHostAndPrefix.TryGetValue(this.GetHostAndPrefix(hostOnly, StringSegment.op_Implicit("/")), out result) || this._shellsByHostAndPrefix.TryGetValue(this.GetHostAndPrefix(StringSegment.op_Implicit(""), path), out result)) { return(true); } result = null; return(false); }
/// <summary> /// Whether or not a shell can be released and removed from the list, false if disabled and still in use. /// Note: A disabled shell still in use will be released by its last scope, and keeping it in the list /// prevents a consumer from creating a new one that would have a null service provider. /// </summary> private bool CanReleaseShell(ShellSettings settings) { return(settings.State != TenantState.Disabled || _shellContexts.TryGetValue(settings.Name, out var value) && value.ActiveScopes == 0); }
async Task IShellDescriptorManagerEventHandler.ChangedAsync(ShellDescriptor descriptor, ShellSettings settings) { // deduce and apply state changes involved var shellState = await _stateManager.GetShellStateAsync(); foreach (var feature in descriptor.Features) { var featureId = feature.Id; var featureState = shellState.Features.SingleOrDefault(f => f.Id == featureId); if (featureState == null) { featureState = new ShellFeatureState { Id = featureId }; } if (!featureState.IsInstalled) { await _stateManager.UpdateInstalledStateAsync(featureState, ShellFeatureState.State.Rising); } if (!featureState.IsEnabled) { await _stateManager.UpdateEnabledStateAsync(featureState, ShellFeatureState.State.Rising); } } foreach (var featureState in shellState.Features) { var featureId = featureState.Id; if (descriptor.Features.Any(f => f.Id == featureId)) { continue; } if (!featureState.IsDisabled) { await _stateManager.UpdateEnabledStateAsync(featureState, ShellFeatureState.State.Falling); } } FireApplyChangesIfNeeded(); }
public ShellSettingsWithTenants(ShellSettings shellSettings) : base(shellSettings.Configuration) { Features = shellSettings .Configuration .Where(x => x.Key.StartsWith("Features") && x.Value != null).Select(x => x.Value).ToArray(); }