< Summary

Information
Class: Ice.Internal.ServantManager
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/ServantManager.cs
Tag: 71_18251537082
Line coverage
91%
Covered lines: 126
Uncovered lines: 12
Coverable lines: 138
Total lines: 315
Line coverage: 91.3%
Branch coverage
82%
Covered branches: 51
Total branches: 62
Branch coverage: 82.2%
Method coverage
100%
Covered methods: 15
Total methods: 15
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
dispatchAsync()92.86%1414100%
addServant(...)87.5%88100%
addDefaultServant(...)50%2.02283.33%
removeServant(...)90%1010100%
removeDefaultServant(...)50%2.02283.33%
removeAllFacets(...)100%22100%
findServant(...)83.33%66100%
findDefaultServant(...)100%22100%
findAllFacets(...)50%2.02283.33%
hasServant(...)100%22100%
addServantLocator(...)100%22100%
removeServantLocator(...)50%2.21262.5%
findServantLocator(...)100%22100%
destroy()50%7.13668.42%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/Internal/ServantManager.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using System.Diagnostics;
 6
 7namespace Ice.Internal;
 8
 9internal sealed class ServantManager : Object
 10{
 11    private readonly Instance _instance;
 12    private readonly string _adapterName;
 113    private readonly Dictionary<Identity, Dictionary<string, Object>> _servantMapMap = [];
 114    private readonly Dictionary<string, Object> _defaultServantMap = [];
 115    private readonly Dictionary<string, ServantLocator> _locatorMap = [];
 16    private bool _isDestroyed;
 117    private readonly object _mutex = new();
 18
 19    public async ValueTask<OutgoingResponse> dispatchAsync(IncomingRequest request)
 20    {
 121        Current current = request.current;
 122        Object? servant = findServant(current.id, current.facet);
 23
 124        if (servant is not null)
 25        {
 26            // the simple, common path
 127            return await servant.dispatchAsync(request).ConfigureAwait(false);
 28        }
 29
 30        // Else, check servant locators
 131        ServantLocator? locator = findServantLocator(current.id.category);
 132        if (locator is null && current.id.category.Length > 0)
 33        {
 134            locator = findServantLocator("");
 35        }
 36
 137        if (locator is not null)
 38        {
 39            object? cookie;
 40
 41            try
 42            {
 143                servant = locator.locate(current, out cookie);
 144            }
 145            catch
 46            {
 47                // Skip the encapsulation. This allows the next batch requests in the same InputStream to proceed.
 148                request.inputStream.skipEncapsulation();
 149                throw;
 50            }
 51
 152            if (servant is not null)
 53            {
 54                try
 55                {
 156                    return await servant.dispatchAsync(request).ConfigureAwait(false);
 57                }
 58                finally
 59                {
 160                    locator.finished(current, servant, cookie);
 61                }
 62            }
 163        }
 64
 65        Debug.Assert(servant is null);
 66
 67        // Skip the encapsulation. This allows the next batch requests in the same InputStream to proceed.
 168        request.inputStream.skipEncapsulation();
 169        if (hasServant(current.id))
 70        {
 171            throw new FacetNotExistException();
 72        }
 73        else
 74        {
 175            throw new ObjectNotExistException();
 76        }
 177    }
 78
 79    internal void addServant(Object servant, Identity ident, string facet)
 80    {
 181        lock (_mutex)
 82        {
 183            facet ??= "";
 84
 185            if (_servantMapMap.TryGetValue(ident, out Dictionary<string, Object>? m))
 86            {
 187                if (m.ContainsKey(facet))
 88                {
 189                    string id = Ice.Util.identityToString(ident, _instance.toStringMode());
 190                    if (facet.Length > 0)
 91                    {
 192                        id += " -f " + UtilInternal.StringUtil.escapeString(facet, "", _instance.toStringMode());
 93                    }
 194                    throw new AlreadyRegisteredException("servant", id);
 95                }
 96            }
 97            else
 98            {
 199                m = new();
 1100                _servantMapMap[ident] = m;
 101            }
 102
 1103            m[facet] = servant;
 1104        }
 1105    }
 106
 107    internal void addDefaultServant(Object servant, string category)
 108    {
 1109        lock (_mutex)
 110        {
 1111            if (_defaultServantMap.TryGetValue(category, out Object? obj))
 112            {
 0113                throw new AlreadyRegisteredException("default servant", category);
 114            }
 115
 1116            _defaultServantMap[category] = servant;
 1117        }
 1118    }
 119
 120    internal Object removeServant(Identity ident, string facet)
 121    {
 1122        lock (_mutex)
 123        {
 1124            facet ??= "";
 125
 1126            _servantMapMap.TryGetValue(ident, out Dictionary<string, Object>? m);
 1127            Object? obj = null;
 1128            if (m is null || !m.TryGetValue(facet, out Object? value))
 129            {
 1130                string id = Ice.Util.identityToString(ident, _instance.toStringMode());
 1131                if (facet.Length > 0)
 132                {
 1133                    id += " -f " + UtilInternal.StringUtil.escapeString(facet, "", _instance.toStringMode());
 134                }
 1135                throw new NotRegisteredException("servant", id);
 136            }
 1137            obj = value;
 1138            m.Remove(facet);
 139
 1140            if (m.Count == 0)
 141            {
 1142                _servantMapMap.Remove(ident);
 143            }
 1144            return obj;
 145        }
 1146    }
 147
 148    internal Object removeDefaultServant(string category)
 149    {
 1150        lock (_mutex)
 151        {
 1152            if (!_defaultServantMap.TryGetValue(category, out Object? obj))
 153            {
 0154                throw new NotRegisteredException("default servant", category);
 155            }
 156
 1157            _defaultServantMap.Remove(category);
 1158            return obj;
 159        }
 1160    }
 161
 162    internal Dictionary<string, Object> removeAllFacets(Identity ident)
 163    {
 1164        lock (_mutex)
 165        {
 1166            if (!_servantMapMap.TryGetValue(ident, out Dictionary<string, Object>? m))
 167            {
 1168                throw new NotRegisteredException(
 1169                    "servant",
 1170                    Ice.Util.identityToString(ident, _instance.toStringMode()));
 171            }
 1172            _servantMapMap.Remove(ident);
 173
 1174            return m;
 175        }
 1176    }
 177
 178    internal Object? findServant(Identity ident, string facet)
 179    {
 1180        lock (_mutex)
 181        {
 1182            facet ??= "";
 183
 1184            Object? obj = null;
 1185            if (_servantMapMap.TryGetValue(ident, out Dictionary<string, Object>? m))
 186            {
 1187                m.TryGetValue(facet, out obj);
 188            }
 189            else
 190            {
 1191                _defaultServantMap.TryGetValue(ident.category, out obj);
 1192                if (obj is null)
 193                {
 1194                    _defaultServantMap.TryGetValue("", out obj);
 195                }
 196            }
 197
 1198            return obj;
 199        }
 1200    }
 201
 202    internal Object? findDefaultServant(string category)
 203    {
 1204        lock (_mutex)
 205        {
 1206            return _defaultServantMap.TryGetValue(category, out Object? obj) ? obj : null;
 207        }
 1208    }
 209
 210    internal Dictionary<string, Object> findAllFacets(Identity ident)
 211    {
 1212        lock (_mutex)
 213        {
 1214            Dictionary<string, Object>? m = _servantMapMap[ident];
 1215            if (m is not null)
 216            {
 1217                return new Dictionary<string, Object>(m);
 218            }
 219
 0220            return new Dictionary<string, Object>();
 221        }
 1222    }
 223
 224    internal bool hasServant(Identity ident)
 225    {
 1226        lock (_mutex)
 227        {
 1228            return _servantMapMap.TryGetValue(ident, out Dictionary<string, Object>? m) ? m.Count != 0 : false;
 229        }
 1230    }
 231
 232    internal void addServantLocator(ServantLocator locator, string category)
 233    {
 1234        lock (_mutex)
 235        {
 1236            if (_locatorMap.TryGetValue(category, out ServantLocator? l))
 237            {
 1238                throw new AlreadyRegisteredException(
 1239                    "servant locator",
 1240                    UtilInternal.StringUtil.escapeString(category, "", _instance.toStringMode()));
 241            }
 242
 1243            _locatorMap[category] = locator;
 1244        }
 1245    }
 246
 247    internal ServantLocator removeServantLocator(string category)
 248    {
 1249        lock (_mutex)
 250        {
 1251            if (!_locatorMap.TryGetValue(category, out ServantLocator? l))
 252            {
 0253                throw new NotRegisteredException(
 0254                    "servant locator",
 0255                    UtilInternal.StringUtil.escapeString(category, "", _instance.toStringMode()));
 256            }
 1257            _locatorMap.Remove(category);
 1258            return l;
 259        }
 1260    }
 261
 262    internal ServantLocator? findServantLocator(string category)
 263    {
 1264        lock (_mutex)
 265        {
 1266            return _locatorMap.TryGetValue(category, out ServantLocator? result) ? result : null;
 267        }
 1268    }
 269
 270    //
 271    // Only for use by ObjectAdapter.
 272    //
 1273    internal ServantManager(Instance instance, string adapterName)
 274    {
 1275        _instance = instance;
 1276        _adapterName = adapterName;
 1277    }
 278
 279    //
 280    // Only for use by ObjectAdapter.
 281    //
 282    internal void destroy()
 283    {
 284        Dictionary<string, ServantLocator> locatorMap;
 1285        lock (_mutex)
 286        {
 1287            if (_isDestroyed)
 288            {
 0289                return;
 290            }
 291
 1292            _isDestroyed = true;
 1293            _servantMapMap.Clear();
 1294            _defaultServantMap.Clear();
 295
 1296            locatorMap = new Dictionary<string, ServantLocator>(_locatorMap);
 1297            _locatorMap.Clear();
 1298        }
 299
 1300        foreach (KeyValuePair<string, ServantLocator> p in locatorMap)
 301        {
 1302            ServantLocator locator = p.Value;
 303            try
 304            {
 1305                locator.deactivate(p.Key);
 1306            }
 0307            catch (System.Exception ex)
 308            {
 0309                string s = "exception during locator deactivation:\n" + "object adapter: `"
 0310                            + _adapterName + "'\n" + "locator category: `" + p.Key + "'\n" + ex;
 0311                _instance.initializationData().logger!.error(s);
 0312            }
 313        }
 1314    }
 315}