Exemple #1
0
            // 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);
 }
Exemple #3
0
 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);
            }
Exemple #5
0
 public SettingsUpdates DetachSettingsUpdate()
 {
     lock (_updateLock)
     {
         SettingsUpdates returnValue = _settingsUpdate;
         _settingsUpdate = null;
         return(returnValue);
     }
 }
Exemple #6
0
            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);
            }
Exemple #11
0
            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);
            }
Exemple #12
0
        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
            }
        }
Exemple #13
0
        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;
                    }
                }
            }
        }