< Summary

Information
Class: Ice.Internal.RouterInfo
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/RouterInfo.cs
Tag: 71_18251537082
Line coverage
82%
Covered lines: 80
Uncovered lines: 17
Coverable lines: 97
Total lines: 294
Line coverage: 82.4%
Branch coverage
73%
Covered branches: 19
Total branches: 26
Branch coverage: 73%
Method coverage
84%
Covered methods: 16
Total methods: 19
Method coverage: 84.2%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
destroy()100%11100%
op_Equality(...)100%22100%
op_Inequality(...)100%11100%
Equals(...)100%44100%
Equals(...)100%210%
GetHashCode()100%210%
getRouter()100%11100%
getClientEndpoints()100%22100%
getClientEndpoints(...)100%22100%
performGetClientProxyAsync()100%1.01177.78%
getServerEndpoints()50%22100%
addProxy(...)75%4.02490%
performAddProxiesAsync()100%1.09154.55%
setAdapter(...)100%11100%
getAdapter()100%11100%
clearCache(...)100%210%
setClientEndpoints(...)75%44100%
addAndEvictProxies(...)33.33%6.97670%

File(s)

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

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4
 5namespace Ice.Internal;
 6
 7public sealed class RouterInfo : IEquatable<RouterInfo>
 8{
 9    public interface GetClientEndpointsCallback
 10    {
 11        void setEndpoints(EndpointI[] endpoints);
 12
 13        void setException(Ice.LocalException ex);
 14    }
 15
 16    public interface AddProxyCallback
 17    {
 18        void addedProxy();
 19
 20        void setException(Ice.LocalException ex);
 21    }
 22
 123    internal RouterInfo(Ice.RouterPrx router)
 24    {
 125        _router = router;
 26
 27        Debug.Assert(_router != null);
 128    }
 29
 30    public void destroy()
 31    {
 132        lock (_mutex)
 33        {
 134            _clientEndpoints = [];
 135            _adapter = null;
 136            _identities.Clear();
 137        }
 138    }
 39
 140    public static bool operator ==(RouterInfo lhs, RouterInfo rhs) => lhs is not null ? lhs.Equals(rhs) : rhs is null;
 41
 142    public static bool operator !=(RouterInfo lhs, RouterInfo rhs) => !(lhs == rhs);
 43
 44    public bool Equals(RouterInfo other) =>
 145        ReferenceEquals(this, other) || (other is not null && _router.Equals(other._router));
 46
 047    public override bool Equals(object obj) => Equals(obj as RouterInfo);
 48
 049    public override int GetHashCode() => _router.GetHashCode();
 50
 51    public Ice.RouterPrx getRouter() =>
 52        //
 53        // No mutex lock necessary, _router is immutable.
 54        //
 155        _router;
 56
 57    public EndpointI[] getClientEndpoints()
 58    {
 159        lock (_mutex)
 60        {
 161            if (_clientEndpoints != null) // Lazy initialization.
 62            {
 163                return _clientEndpoints;
 64            }
 165        }
 66
 167        ObjectPrx proxy = _router.getClientProxy(out bool? hasRoutingTable);
 168        return setClientEndpoints(proxy, hasRoutingTable ?? true);
 169    }
 70
 71    public void getClientEndpoints(GetClientEndpointsCallback callback)
 72    {
 173        EndpointI[] clientEndpoints = null;
 174        lock (_mutex)
 75        {
 176            clientEndpoints = _clientEndpoints;
 177        }
 78
 179        if (clientEndpoints != null) // Lazy initialization.
 80        {
 181            callback.setEndpoints(clientEndpoints);
 182            return;
 83        }
 184        _ = performGetClientProxyAsync(_router);
 85
 86        async Task performGetClientProxyAsync(RouterPrx router)
 87        {
 88            try
 89            {
 190                Router_GetClientProxyResult r = await router.getClientProxyAsync().ConfigureAwait(false);
 191                callback.setEndpoints(setClientEndpoints(r.returnValue, r.hasRoutingTable ?? true));
 192            }
 193            catch (Ice.LocalException ex)
 94            {
 195                callback.setException(ex);
 196            }
 097            catch (System.Exception ex)
 98            {
 99                Debug.Fail($"unexpected exception: {ex}");
 0100                throw;
 101            }
 1102        }
 1103    }
 104
 105    public EndpointI[] getServerEndpoints()
 106    {
 1107        Ice.ObjectPrx serverProxy = _router.getServerProxy() ??
 1108            throw new NoEndpointException("Router::getServerProxy returned a null proxy.");
 1109        serverProxy = serverProxy.ice_router(null); // The server proxy cannot be routed.
 1110        return ((Ice.ObjectPrxHelperBase)serverProxy).iceReference().getEndpoints();
 111    }
 112
 113    public bool addProxy(Reference reference, AddProxyCallback callback)
 114    {
 1115        Identity identity = reference.getIdentity();
 116
 1117        lock (_mutex)
 118        {
 1119            if (!_hasRoutingTable)
 120            {
 0121                return true; // The router implementation doesn't maintain a routing table.
 122            }
 1123            if (_identities.Contains(identity))
 124            {
 125                //
 126                // Only add the proxy to the router if it's not already in our local map.
 127                //
 1128                return true;
 129            }
 1130        }
 1131        _ = performAddProxiesAsync(_router, reference);
 1132        return false;
 133
 134        async Task performAddProxiesAsync(RouterPrx router, Reference reference)
 135        {
 136            try
 137            {
 1138                ObjectPrx[] evictedProxies =
 1139                    await router.addProxiesAsync([new ObjectPrxHelper(reference)]).ConfigureAwait(false);
 1140                addAndEvictProxies(identity, evictedProxies);
 1141                callback.addedProxy();
 1142            }
 0143            catch (Ice.LocalException ex)
 144            {
 0145                callback.setException(ex);
 0146            }
 0147            catch (System.Exception ex)
 148            {
 149                Debug.Fail($"unexpected exception: {ex}");
 0150                throw;
 151            }
 1152        }
 1153    }
 154
 155    public void setAdapter(Ice.ObjectAdapter adapter)
 156    {
 1157        lock (_mutex)
 158        {
 1159            _adapter = adapter;
 1160        }
 1161    }
 162
 163    public Ice.ObjectAdapter getAdapter()
 164    {
 1165        lock (_mutex)
 166        {
 1167            return _adapter;
 168        }
 1169    }
 170
 171    public void clearCache(Reference @ref)
 172    {
 0173        lock (_mutex)
 174        {
 0175            _identities.Remove(@ref.getIdentity());
 0176        }
 0177    }
 178
 179    private EndpointI[] setClientEndpoints(Ice.ObjectPrx clientProxy, bool hasRoutingTable)
 180    {
 1181        lock (_mutex)
 182        {
 1183            if (_clientEndpoints is null)
 184            {
 1185                _hasRoutingTable = hasRoutingTable;
 1186                _clientEndpoints = clientProxy is null ?
 1187                    ((ObjectPrxHelperBase)_router).iceReference().getEndpoints() :
 1188                    ((ObjectPrxHelperBase)clientProxy).iceReference().getEndpoints();
 189            }
 1190            return _clientEndpoints;
 191        }
 1192    }
 193
 194    private void addAndEvictProxies(Identity identity, Ice.ObjectPrx[] evictedProxies)
 195    {
 1196        lock (_mutex)
 197        {
 198            //
 199            // Check if the proxy hasn't already been evicted by a
 200            // concurrent addProxies call. If it's the case, don't
 201            // add it to our local map.
 202            //
 1203            int index = _evictedIdentities.IndexOf(identity);
 1204            if (index >= 0)
 205            {
 0206                _evictedIdentities.RemoveAt(index);
 207            }
 208            else
 209            {
 210                //
 211                // If we successfully added the proxy to the router,
 212                // we add it to our local map.
 213                //
 1214                _identities.Add(identity);
 215            }
 216
 217            //
 218            // We also must remove whatever proxies the router evicted.
 219            //
 1220            for (int i = 0; i < evictedProxies.Length; ++i)
 221            {
 0222                if (!_identities.Remove(evictedProxies[i].ice_getIdentity()))
 223                {
 224                    //
 225                    // It's possible for the proxy to not have been
 226                    // added yet in the local map if two threads
 227                    // concurrently call addProxies.
 228                    //
 0229                    _evictedIdentities.Add(evictedProxies[i].ice_getIdentity());
 230                }
 231            }
 1232        }
 1233    }
 234
 235    private readonly Ice.RouterPrx _router;
 236    private EndpointI[] _clientEndpoints;
 237    private Ice.ObjectAdapter _adapter;
 1238    private readonly HashSet<Ice.Identity> _identities = new HashSet<Ice.Identity>();
 1239    private readonly List<Ice.Identity> _evictedIdentities = new List<Ice.Identity>();
 240    private bool _hasRoutingTable;
 1241    private readonly object _mutex = new();
 242}
 243
 244public sealed class RouterManager
 245{
 246    internal RouterManager() => _table = new Dictionary<Ice.RouterPrx, RouterInfo>();
 247
 248    internal void destroy()
 249    {
 250        lock (_mutex)
 251        {
 252            foreach (RouterInfo i in _table.Values)
 253            {
 254                i.destroy();
 255            }
 256            _table.Clear();
 257        }
 258    }
 259
 260    // Returns router info for a given router. Automatically creates the router info if it doesn't exist yet.
 261    internal RouterInfo get(Ice.RouterPrx router)
 262    {
 263        if (router is null)
 264        {
 265            return null;
 266        }
 267
 268        // Make sure router is not routed.
 269        router = RouterPrxHelper.uncheckedCast(router.ice_router(null));
 270
 271        lock (_mutex)
 272        {
 273            if (!_table.TryGetValue(router, out RouterInfo info))
 274            {
 275                info = new RouterInfo(router);
 276                _table.Add(router, info);
 277            }
 278
 279            return info;
 280        }
 281    }
 282
 283    internal void erase(RouterPrx router)
 284    {
 285        Debug.Assert(router.ice_getRouter() is null); // The router proxy cannot be routed.
 286        lock (_mutex)
 287        {
 288            _table.Remove(router);
 289        }
 290    }
 291
 292    private readonly Dictionary<Ice.RouterPrx, RouterInfo> _table;
 293    private readonly object _mutex = new();
 294}