< Summary

Information
Class: Ice.NativePropertiesAdmin
Assembly: Ice
File(s): /_/csharp/src/Ice/NativePropertiesAdmin.cs
Tag: 91_21789722663
Line coverage
59%
Covered lines: 46
Uncovered lines: 31
Coverable lines: 77
Total lines: 202
Line coverage: 59.7%
Branch coverage
52%
Covered branches: 26
Total branches: 50
Branch coverage: 52%
Method coverage
83%
Covered methods: 5
Total methods: 6
Method coverage: 83.3%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
getProperty(...)100%11100%
getPropertiesForPrefix(...)100%11100%
setProperties(...)52%266.765055.74%
addUpdateCallback(...)100%11100%
removeUpdateCallback(...)100%210%

File(s)

/_/csharp/src/Ice/NativePropertiesAdmin.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5namespace Ice;
 6
 7/// <summary>
 8/// The default implementation of the "Properties" admin facet.
 9/// </summary>
 10public sealed class NativePropertiesAdmin : PropertiesAdminDisp_
 11{
 12    private readonly Properties _properties;
 13    private readonly Logger _logger;
 114    private readonly List<Action<Dictionary<string, string>>> _updateCallbacks = new();
 115    private readonly object _mutex = new();
 16    private const string _traceCategory = "Admin.Properties";
 17
 118    public override string getProperty(string key, Current current) => _properties.getProperty(key);
 19
 20    public override Dictionary<string, string> getPropertiesForPrefix(string prefix, Current current) =>
 121        _properties.getPropertiesForPrefix(prefix);
 22
 23    public override void setProperties(Dictionary<string, string> newProperties, Current current)
 24    {
 125        lock (_mutex)
 26        {
 127            Dictionary<string, string> old = _properties.getPropertiesForPrefix("");
 128            int traceLevel = _properties.getIcePropertyAsInt("Ice.Trace.Admin.Properties");
 29
 30            // Compute the difference between the new property set and the existing property set:
 31            //
 32            // 1) Any properties in the new set that were not defined in the existing set.
 33            //
 34            // 2) Any properties that appear in both sets but with different values.
 35            //
 36            // 3) Any properties not present in the new set but present in the existing set.
 37            //    In other words, the property has been removed.
 38
 139            var added = new Dictionary<string, string>();
 140            var changed = new Dictionary<string, string>();
 141            var removed = new Dictionary<string, string>();
 142            foreach (KeyValuePair<string, string> e in newProperties)
 43            {
 144                string key = e.Key;
 145                string value = e.Value;
 146                if (!old.ContainsKey(key))
 47                {
 148                    if (value.Length > 0)
 49                    {
 50                        //
 51                        // This property is new.
 52                        //
 153                        added.Add(key, value);
 54                    }
 55                }
 56                else
 57                {
 158                    if (!old.TryGetValue(key, out string? v) || !value.Equals(v, StringComparison.Ordinal))
 59                    {
 160                        if (value.Length == 0)
 61                        {
 62                            //
 63                            // This property was removed.
 64                            //
 165                            removed.Add(key, value);
 66                        }
 67                        else
 68                        {
 69                            //
 70                            // This property has changed.
 71                            //
 172                            changed.Add(key, value);
 73                        }
 74                    }
 75
 176                    old.Remove(key);
 77                }
 78            }
 79
 180            if (traceLevel > 0 && (added.Count > 0 || changed.Count > 0 || removed.Count > 0))
 81            {
 082                var message = new System.Text.StringBuilder("Summary of property changes");
 83
 084                if (added.Count > 0)
 85                {
 086                    message.Append("\nNew properties:");
 087                    foreach (KeyValuePair<string, string> e in added)
 88                    {
 089                        message.Append("\n  ");
 090                        message.Append(e.Key);
 091                        if (traceLevel > 1)
 92                        {
 093                            message.Append(" = ");
 094                            message.Append(e.Value);
 95                        }
 96                    }
 97                }
 98
 099                if (changed.Count > 0)
 100                {
 0101                    message.Append("\nChanged properties:");
 0102                    foreach (KeyValuePair<string, string> e in changed)
 103                    {
 0104                        message.Append("\n  ");
 0105                        message.Append(e.Key);
 0106                        if (traceLevel > 1)
 107                        {
 0108                            message.Append(" = ");
 0109                            message.Append(e.Value);
 0110                            message.Append(" (old value = ");
 0111                            message.Append(_properties.getProperty(e.Key));
 0112                            message.Append(')');
 113                        }
 114                    }
 115                }
 116
 0117                if (removed.Count > 0)
 118                {
 0119                    message.Append("\nRemoved properties:");
 0120                    foreach (KeyValuePair<string, string> e in removed)
 121                    {
 0122                        message.Append("\n  ");
 0123                        message.Append(e.Key);
 124                    }
 125                }
 126
 0127                _logger.trace(_traceCategory, message.ToString());
 128            }
 129
 130            //
 131            // Update the property set.
 132            //
 133
 1134            foreach (KeyValuePair<string, string> e in added)
 135            {
 1136                _properties.setProperty(e.Key, e.Value);
 137            }
 138
 1139            foreach (KeyValuePair<string, string> e in changed)
 140            {
 1141                _properties.setProperty(e.Key, e.Value);
 142            }
 143
 1144            foreach (KeyValuePair<string, string> e in removed)
 145            {
 1146                _properties.setProperty(e.Key, "");
 147            }
 148
 1149            if (_updateCallbacks.Count > 0)
 150            {
 1151                var changes = new Dictionary<string, string>(added);
 1152                foreach (KeyValuePair<string, string> e in changed)
 153                {
 1154                    changes.Add(e.Key, e.Value);
 155                }
 1156                foreach (KeyValuePair<string, string> e in removed)
 157                {
 1158                    changes.Add(e.Key, e.Value);
 159                }
 160
 161                // Copy callbacks to allow callbacks to update callbacks
 162                foreach (
 1163                    Action<Dictionary<string, string>> callback in
 1164                    new List<System.Action<Dictionary<string, string>>>(_updateCallbacks))
 165                {
 166                    // The callback should not throw any exception.
 1167                    callback(changes);
 168                }
 169            }
 0170        }
 1171    }
 172
 173    /// <summary>
 174    /// Registers an update callback that will be invoked when a property update occurs.
 175    /// </summary>
 176    /// <param name="cb">The callback.</param>
 177    public void addUpdateCallback(System.Action<Dictionary<string, string>> cb)
 178    {
 1179        lock (_mutex)
 180        {
 1181            _updateCallbacks.Add(cb);
 1182        }
 1183    }
 184
 185    /// <summary>
 186    /// Unregisters an update callback previously registered with <see cref="addUpdateCallback" /> .
 187    /// </summary>
 188    /// <param name="cb">The callback.</param>
 189    public void removeUpdateCallback(System.Action<Dictionary<string, string>> cb)
 190    {
 0191        lock (_mutex)
 192        {
 0193            _updateCallbacks.Remove(cb);
 0194        }
 0195    }
 196
 1197    internal NativePropertiesAdmin(Internal.Instance instance)
 198    {
 1199        _properties = instance.initializationData().properties!;
 1200        _logger = instance.initializationData().logger!;
 1201    }
 202}