// VS CODE TODO: RegistryKey should be replaced with some sort of generic configuration store, and it should NOT be // optional. public ExceptionCategorySettings(ExceptionManager parent, /*OPTIONAL*/ RegistryKey categoryKey) { _parent = parent; if (categoryKey != null) { this.CategoryName = categoryKey.GetSubKeyNames().Single(); this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary <string, ExceptionBreakpointState> exceptionSettings = new Dictionary <string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) { continue; } ExceptionBreakpointState value = RegistryToExceptionBreakpointState(categoryKey.GetValue(valueName)); if (value == this.DefaultCategoryState) { Debug.Fail("Redundant exception trigger found in the registry."); continue; } exceptionSettings.Add(valueName, value); } this.DefaultRules = new ReadOnlyDictionary <string, ExceptionBreakpointState>(exceptionSettings); } else { this.CategoryName = string.Empty; this.DefaultCategoryState = ExceptionBreakpointState.None; this.DefaultRules = new ReadOnlyDictionary <string, ExceptionBreakpointState>(new Dictionary <string, ExceptionBreakpointState>(0)); } this._settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
public SettingsUpdateHolder(SettingsUpdates value, ExceptionManager parent, object updateLock) { this.Value = value; this._parent = parent; this._updateLock = updateLock; Monitor.Enter(this._updateLock); }
public SettingsUpdateHolder(SettingsUpdates value, ExceptionManager parent, object updateLock) { this.Value = value; this._parent = parent; this._updateLock = updateLock; Monitor.Enter(this._updateLock); }
public ExceptionCategorySettings(ExceptionManager parent, HostConfigurationSection categoryKey, string categoryName) { _parent = parent; this.CategoryName = categoryName; this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary <string, ExceptionBreakpointState> exceptionSettings = new Dictionary <string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) { continue; } ExceptionBreakpointState value = RegistryToExceptionBreakpointState(categoryKey.GetValue(valueName)); if (value == this.DefaultCategoryState) { Debug.Fail("Redundant exception trigger found in the registry."); continue; } exceptionSettings.Add(valueName, value); } this.DefaultRules = new ReadOnlyDictionary <string, ExceptionBreakpointState>(exceptionSettings); _settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
public SettingsUpdates DetachSettingsUpdate() { lock (_updateLock) { SettingsUpdates returnValue = _settingsUpdate; _settingsUpdate = null; return(returnValue); } }
public SettingsUpdateHolder GetSettingsUpdate() { lock (_updateLock) { if (_settingsUpdate == null) { _settingsUpdate = new SettingsUpdates(null, null); } return(new SettingsUpdateHolder(_settingsUpdate, _parent, _updateLock)); } }
private async Task UpdateCatagory(Guid categoryId, ExceptionCategorySettings categorySettings, SettingsUpdates updates) { // Update the category if (updates.NewCategoryState.HasValue && ( updates.NewCategoryState.Value != ExceptionBreakpointState.None || // send down a rule if the category isn't in the default state categorySettings.CurrentRules.Count != 0)) // Or if we have other rules for the category that we need to blow away { ExceptionBreakpointState newCategoryState = updates.NewCategoryState.Value; categorySettings.CategoryState = newCategoryState; categorySettings.CurrentRules.Clear(); IEnumerable<ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, null, newCategoryState); if (newCategoryState != ExceptionBreakpointState.None) { ulong breakpointId = breakpointIds.Single(); categorySettings.CurrentRules.Add("*", breakpointId); } } // Process any removes if (updates.RulesToRemove.Count > 0) { // Detach these exceptions from 'CurrentRules' List<ulong> breakpointsToRemove = new List<ulong>(); foreach (string exceptionToRemove in updates.RulesToRemove) { ulong breakpointId; if (!categorySettings.CurrentRules.TryGetValue(exceptionToRemove, out breakpointId)) continue; categorySettings.CurrentRules.Remove(exceptionToRemove); breakpointsToRemove.Add(breakpointId); } if (breakpointsToRemove.Count > 0) { await _commandFactory.RemoveExceptionBreakpoint(categoryId, breakpointsToRemove); } } // process any adds foreach (IGrouping<ExceptionBreakpointState, string> grouping in updates.RulesToAdd.GroupBy((pair) => pair.Value, (pair) => pair.Key)) { IEnumerable<string> exceptionNames = grouping; if (grouping.Key == categorySettings.CategoryState) { // A request to set an exception to the same state as the category is redundant unless we have previously changed the state of that exception to something else exceptionNames = exceptionNames.Intersect(categorySettings.CurrentRules.Keys); if (!exceptionNames.Any()) { continue; // no exceptions left, so ignore this group } } IEnumerable<ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, exceptionNames, grouping.Key); int count = exceptionNames.Zip(breakpointIds, (exceptionName, breakpointId) => { categorySettings.CurrentRules[exceptionName] = breakpointId; return 1; }).Sum(); #if DEBUG Debug.Assert(count == exceptionNames.Count()); #endif } }
public SettingsUpdates DetachSettingsUpdate() { lock (_updateLock) { SettingsUpdates returnValue = _settingsUpdate; _settingsUpdate = null; return returnValue; } }
public SettingsUpdateHolder GetSettingsUpdate() { lock (_updateLock) { if (_settingsUpdate == null) { _settingsUpdate = new SettingsUpdates(null, null); } return new SettingsUpdateHolder(_settingsUpdate, _parent, _updateLock); } }
// VS CODE TODO: RegistryKey should be replaced with some sort of generic configuration store, and it should NOT be // optional. public ExceptionCategorySettings(ExceptionManager parent, /*OPTIONAL*/ RegistryKey categoryKey) { _parent = parent; if (categoryKey != null) { this.CategoryName = categoryKey.GetSubKeyNames().Single(); this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary<string, ExceptionBreakpointState> exceptionSettings = new Dictionary<string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) continue; ExceptionBreakpointState value = RegistryToExceptionBreakpointState(categoryKey.GetValue(valueName)); if (value == this.DefaultCategoryState) { Debug.Fail("Redundant exception trigger found in the registry."); continue; } exceptionSettings.Add(valueName, value); } this.DefaultRules = new ReadOnlyDictionary<string, ExceptionBreakpointState>(exceptionSettings); } else { this.CategoryName = string.Empty; this.DefaultCategoryState = ExceptionBreakpointState.None; this.DefaultRules = new ReadOnlyDictionary<string, ExceptionBreakpointState>(new Dictionary<string, ExceptionBreakpointState>(0)); } this._settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
public ExceptionCategorySettings(ExceptionManager parent, HostConfigurationSection categoryKey, string categoryName) { _parent = parent; this.CategoryName = categoryName; this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary<string, ExceptionBreakpointState> exceptionSettings = new Dictionary<string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) continue; ExceptionBreakpointState value = RegistryToExceptionBreakpointState(categoryKey.GetValue(valueName)); if (value == this.DefaultCategoryState) { Debug.Fail("Redundant exception trigger found in the registry."); continue; } exceptionSettings.Add(valueName, value); } this.DefaultRules = new ReadOnlyDictionary<string, ExceptionBreakpointState>(exceptionSettings); _settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
private async Task UpdateCatagory(Guid categoryId, ExceptionCategorySettings categorySettings, SettingsUpdates updates) { // Update the category if (updates.NewCategoryState.HasValue && ( updates.NewCategoryState.Value != ExceptionBreakpointState.None || // send down a rule if the category isn't in the default state categorySettings.CurrentRules.Count != 0)) // Or if we have other rules for the category that we need to blow away { ExceptionBreakpointState newCategoryState = updates.NewCategoryState.Value; categorySettings.CategoryState = newCategoryState; categorySettings.CurrentRules.Clear(); IEnumerable <ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, null, newCategoryState); if (newCategoryState != ExceptionBreakpointState.None) { ulong breakpointId = breakpointIds.Single(); categorySettings.CurrentRules.Add("*", breakpointId); } } // Process any removes if (updates.RulesToRemove.Count > 0) { // Detach these exceptions from 'CurrentRules' List <ulong> breakpointsToRemove = new List <ulong>(); foreach (string exceptionToRemove in updates.RulesToRemove) { ulong breakpointId; if (!categorySettings.CurrentRules.TryGetValue(exceptionToRemove, out breakpointId)) { continue; } categorySettings.CurrentRules.Remove(exceptionToRemove); breakpointsToRemove.Add(breakpointId); } if (breakpointsToRemove.Count > 0) { await _commandFactory.RemoveExceptionBreakpoint(categoryId, breakpointsToRemove); } } // process any adds foreach (IGrouping <ExceptionBreakpointState, string> grouping in updates.RulesToAdd.GroupBy((pair) => pair.Value, (pair) => pair.Key)) { IEnumerable <string> exceptionNames = grouping; if (grouping.Key == categorySettings.CategoryState) { // A request to set an exception to the same state as the category is redundant unless we have previously changed the state of that exception to something else exceptionNames = exceptionNames.Intersect(categorySettings.CurrentRules.Keys); if (!exceptionNames.Any()) { continue; // no exceptions left, so ignore this group } } IEnumerable <ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, exceptionNames, grouping.Key); int count = exceptionNames.Zip(breakpointIds, (exceptionName, breakpointId) => { categorySettings.CurrentRules[exceptionName] = breakpointId; return(1); }).Sum(); #if DEBUG Debug.Assert(count == exceptionNames.Count()); #endif } }
private async Task FlushSettingsUpdates() { while (true) { // Delay sending updates until it has been ~50 ms since we have seen an update try { while (!_updateDelayCancelSource.IsCancellationRequested) { await Task.Delay(50, _updateDelayCancelSource.Token); lock (_updateLock) { if (_lastUpdateTime.HasValue) { uint millisecondsSinceLastUpdate = unchecked ((uint)(Environment.TickCount - _lastUpdateTime.Value)); // Clear this so that we don't think there is an unprocessed update at the end _lastUpdateTime = null; // Pick a number slightly less than the ms that we pass to Task.Delay as the resolution on Environment.TickCount is not great // and anyway we aren't trying to be precise as to how long we wait. if (millisecondsSinceLastUpdate >= 45) { break; } } else { break; } } } } catch (TaskCanceledException) { // Calls to EnsureSettingsUpdated cancel the delay } // Now send updates try { foreach (var categoryPair in _categoryMap) { ExceptionCategorySettings categorySettings = categoryPair.Value; SettingsUpdates settingsUpdate = categorySettings.DetachSettingsUpdate(); if (settingsUpdate == null) { continue; } await UpdateCatagory(categoryPair.Key, categorySettings, settingsUpdate); } } catch (MIException e) { _callback.OnError(string.Format(CultureInfo.CurrentUICulture, ResourceStrings.ExceptionSettingsError, e.Message)); } lock (_updateLock) { if (_lastUpdateTime == null) { // No more updates have been posted since the start of this iteration of the loop, we are done. _updateTask = null; _updateDelayCancelSource = null; break; } else { // An update may have been posted since our last trip arround the category loop, go again _lastUpdateTime = null; continue; } } } }