< Summary

Information
Class: Ice.ObjectAdapter
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/ObjectAdapter.cs
Tag: 71_18251537082
Line coverage
87%
Covered lines: 456
Uncovered lines: 63
Coverable lines: 519
Total lines: 1495
Line coverage: 87.8%
Branch coverage
89%
Covered branches: 169
Total branches: 188
Branch coverage: 89.8%
Method coverage
94%
Covered methods: 54
Total methods: 57
Method coverage: 94.7%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)92.5%42.054089.13%
getName()100%22100%
getCommunicator()100%11100%
activate()100%10.551082.35%
hold()100%22100%
waitForHold()100%22100%
deactivate()75%8.01894.44%
waitForDeactivate()100%66100%
isDeactivated()100%11100%
destroy()83.33%121296.88%
use(...)50%2.06275%
add(...)100%11100%
addFacet(...)100%11100%
addWithUUID(...)100%11100%
addFacetWithUUID(...)100%11100%
addDefaultServant(...)100%11100%
remove(...)100%11100%
removeFacet(...)100%11100%
removeAllFacets(...)100%11100%
removeDefaultServant(...)100%11100%
find(...)100%210%
findFacet(...)100%11100%
findAllFacets(...)100%11100%
findByProxy(...)100%210%
addServantLocator(...)100%11100%
removeServantLocator(...)100%11100%
findServantLocator(...)100%210%
findDefaultServant(...)100%11100%
get_dispatchPipeline()100%11100%
createProxy(...)100%11100%
createDirectProxy(...)100%11100%
createIndirectProxy(...)100%11100%
setLocator(...)100%11100%
getLocator()100%22100%
getEndpoints()100%22100%
getPublishedEndpoints()100%11100%
setPublishedEndpoints(...)100%4.18477.78%
isLocal(...)100%88100%
flushAsyncBatchRequests(...)100%22100%
updateConnectionObservers()100%22100%
updateThreadObservers()50%22100%
incDirectCount()100%11100%
decDirectCount()100%22100%
getThreadPool()100%22100%
setAdapterOnConnection(...)100%11100%
messageSizeMax()100%11100%
checkIdentity(...)100%22100%
getServerAuthenticationOptions()100%11100%
newProxy(...)100%44100%
newDirectProxy(...)100%11100%
newIndirectProxy(...)100%11100%
checkForDeactivation()50%2.06275%
checkForDestruction()100%22100%
parseEndpoints(...)95.45%2222100%
computePublishedEndpoints()95%20.022096.3%
updateLocatorRegistry(...)70.83%1002449.09%
createDispatchPipeline()100%22100%

File(s)

/home/runner/work/ice/ice/csharp/src/Ice/ObjectAdapter.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3#nullable enable
 4
 5using Ice.Instrumentation;
 6using Ice.Internal;
 7using System.Diagnostics;
 8using System.Net;
 9using System.Net.Security;
 10using System.Text;
 11
 12namespace Ice;
 13
 14public sealed class ObjectAdapter
 15{
 16    private const int StateUninitialized = 0; // Just constructed.
 17    private const int StateHeld = 1;
 18    private const int StateActivating = 2;
 19    private const int StateActive = 3;
 20    private const int StateDeactivating = 4;
 21    private const int StateDeactivated = 5;
 22    private const int StateDestroying = 6;
 23    private const int StateDestroyed = 7;
 24
 25    private int _state = StateUninitialized;
 26    private readonly Instance _instance;
 27    private readonly Communicator _communicator;
 28    private ObjectAdapterFactory? _objectAdapterFactory;
 29    private Ice.Internal.ThreadPool? _threadPool;
 30    private readonly ServantManager _servantManager;
 31    private readonly string _name;
 32    private readonly string _id;
 33    private readonly string _replicaGroupId;
 34    private Reference? _reference;
 35    private readonly List<IncomingConnectionFactory> _incomingConnectionFactories;
 36    private RouterInfo? _routerInfo;
 37    private EndpointI[] _publishedEndpoints;
 38    private LocatorInfo? _locatorInfo;
 39    private int _directCount;  // The number of colloc proxies dispatching on this object adapter.
 40    private readonly bool _noConfig;
 41    private readonly int _messageSizeMax;
 42    private readonly SslServerAuthenticationOptions? _serverAuthenticationOptions;
 43
 44    private readonly Lazy<Object> _dispatchPipeline;
 145    private readonly Stack<Func<Object, Object>> _middlewareStack = new();
 46
 147    private readonly object _mutex = new();
 48
 49    /// <summary>
 50    /// Get the name of this object adapter.
 51    /// </summary>
 52    /// <returns>This object adapter's name.</returns>
 153    public string getName() => _noConfig ? "" : _name;
 54
 55    /// <summary>
 56    /// Get the communicator this object adapter belongs to.
 57    /// </summary>
 58    /// <returns>This object adapter's communicator.
 59    /// </returns>
 160    public Communicator getCommunicator() => _communicator;
 61
 62    /// <summary>
 63    /// Activate all endpoints that belong to this object adapter.
 64    /// After activation, the object adapter can dispatch
 65    /// requests received through its endpoints.
 66    /// </summary>
 67    public void activate()
 68    {
 169        LocatorInfo? locatorInfo = null;
 170        bool printAdapterReady = false;
 71
 172        lock (_mutex)
 73        {
 174            checkForDeactivation();
 75
 76            //
 77            // If we've previously been initialized we just need to activate the
 78            // incoming connection factories and we're done.
 79            //
 180            if (_state != StateUninitialized)
 81            {
 182                foreach (IncomingConnectionFactory icf in _incomingConnectionFactories)
 83                {
 184                    icf.activate();
 85                }
 186                _state = StateActive;
 187                Monitor.PulseAll(_mutex);
 188                return;
 89            }
 90
 91            //
 92            // One off initializations of the adapter: update the
 93            // locator registry and print the "adapter ready"
 94            // message. We set set state to StateActivating to prevent
 95            // deactivation from other threads while these one off
 96            // initializations are done.
 97            //
 198            _state = StateActivating;
 99
 1100            locatorInfo = _locatorInfo;
 1101            if (!_noConfig)
 102            {
 1103                Properties properties = _instance.initializationData().properties!;
 1104                printAdapterReady = properties.getIcePropertyAsInt("Ice.PrintAdapterReady") > 0;
 105            }
 1106        }
 107
 108        try
 109        {
 1110            var dummy = new Identity(name: "dummy", "");
 1111            updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
 1112        }
 0113        catch (LocalException)
 114        {
 115            //
 116            // If we couldn't update the locator registry, we let the
 117            // exception go through and don't activate the adapter to
 118            // allow to user code to retry activating the adapter
 119            // later.
 120            //
 0121            lock (_mutex)
 122            {
 0123                _state = StateUninitialized;
 0124                Monitor.PulseAll(_mutex);
 0125            }
 0126            throw;
 127        }
 128
 1129        if (printAdapterReady)
 130        {
 1131            Console.Out.WriteLine(_name + " ready");
 132        }
 133
 1134        lock (_mutex)
 135        {
 136            Debug.Assert(_state == StateActivating);
 137
 1138            foreach (IncomingConnectionFactory icf in _incomingConnectionFactories)
 139            {
 1140                icf.activate();
 141            }
 142
 1143            _state = StateActive;
 1144            Monitor.PulseAll(_mutex);
 1145        }
 1146    }
 147
 148    /// <summary>
 149    /// Temporarily hold receiving and dispatching requests.
 150    /// The object adapter can be reactivated with the
 151    /// activate operation. &lt;p class="Note"&gt; Holding is not immediate, i.e., after hold returns, the
 152    /// object adapter might still be active for some time. You can use waitForHold to wait until holding is
 153    /// complete.
 154    /// </summary>
 155    public void hold()
 156    {
 1157        lock (_mutex)
 158        {
 1159            checkForDeactivation();
 1160            _state = StateHeld;
 1161            foreach (IncomingConnectionFactory factory in _incomingConnectionFactories)
 162            {
 1163                factory.hold();
 164            }
 165        }
 1166    }
 167
 168    /// <summary>
 169    /// Wait until the object adapter holds requests.
 170    /// Calling hold initiates holding of requests, and
 171    /// waitForHold only returns when holding of requests has been completed.
 172    /// </summary>
 173    public void waitForHold()
 174    {
 175        List<IncomingConnectionFactory> incomingConnectionFactories;
 1176        lock (_mutex)
 177        {
 1178            checkForDeactivation();
 1179            incomingConnectionFactories = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
 1180        }
 181
 1182        foreach (IncomingConnectionFactory factory in incomingConnectionFactories)
 183        {
 1184            factory.waitUntilHolding();
 185        }
 1186    }
 187
 188    /// <summary>
 189    /// Deactivates this object adapter: stop accepting new connections from clients and close gracefully all incoming
 190    /// connections created by this object adapter once all outstanding dispatches have completed. If this object
 191    /// adapter is indirect, this method also unregisters the object adapter from the Locator.
 192    /// This method does not cancel outstanding dispatches--it lets them execute until completion. A new incoming
 193    /// request on an existing connection will be accepted and can delay the closure of the connection.
 194    /// A deactivated object adapter cannot be reactivated again; it can only be destroyed.
 195    /// </summary>
 196    public void deactivate()
 197    {
 1198        lock (_mutex)
 199        {
 200            // Wait for activation or a previous deactivation to complete.
 201            // This is necessary to avoid out of order locator updates.
 1202            while (_state == StateActivating || _state == StateDeactivating)
 203            {
 0204                Monitor.Wait(_mutex);
 205            }
 1206            if (_state > StateDeactivating)
 207            {
 1208                return;
 209            }
 1210            _state = StateDeactivating;
 1211        }
 212
 213        // NOTE: the locator infos and incoming connection factory list are immutable at this point.
 214
 215        try
 216        {
 1217            updateLocatorRegistry(_locatorInfo, null);
 1218        }
 1219        catch (LocalException)
 220        {
 221            // We can't throw exceptions in deactivate so we ignore failures to update the locator registry.
 1222        }
 223
 1224        foreach (IncomingConnectionFactory factory in _incomingConnectionFactories)
 225        {
 1226            factory.destroy();
 227        }
 228
 1229        lock (_mutex)
 230        {
 231            Debug.Assert(_state == StateDeactivating);
 1232            _state = StateDeactivated;
 1233            Monitor.PulseAll(_mutex);
 1234        }
 1235    }
 236
 237    /// <summary>
 238    /// Wait until <see cref="deactivate" /> is called on this object adapter and all connections accepted by this
 239    /// object adapter are closed. A connection is closed only after all outstanding dispatches on this connection have
 240    /// completed.
 241    /// </summary>
 242    public void waitForDeactivate()
 243    {
 1244        IncomingConnectionFactory[]? incomingConnectionFactories = null;
 1245        lock (_mutex)
 246        {
 247            // Wait for deactivation of the adapter itself.
 1248            while (_state < StateDeactivated)
 249            {
 1250                Monitor.Wait(_mutex);
 251            }
 1252            if (_state > StateDeactivated)
 253            {
 1254                return;
 255            }
 256
 1257            incomingConnectionFactories = _incomingConnectionFactories.ToArray();
 1258        }
 259
 260        //
 261        // Now we wait for until all incoming connection factories are
 262        // finished.
 263        //
 1264        foreach (IncomingConnectionFactory factory in incomingConnectionFactories)
 265        {
 1266            factory.waitUntilFinished();
 267        }
 1268    }
 269
 270    /// <summary>
 271    /// Checks if this object adapter has been deactivated.
 272    /// </summary>
 273    /// <returns><see langword="true" /> if <see cref="deactivate"/> has been called on this object adapter; otherwise,
 274    /// <see langword="false" />.
 275    /// </returns>
 276    public bool isDeactivated()
 277    {
 1278        lock (_mutex)
 279        {
 1280            return _state >= StateDeactivated;
 281        }
 1282    }
 283
 284    /// <summary>
 285    /// Destroys this object adapter and cleans up all resources held by this object adapter.
 286    /// Once this method has returned, it is possible to create another object adapter with the same name.
 287    /// </summary>
 288    public void destroy()
 289    {
 290        //
 291        // Deactivate and wait for completion.
 292        //
 1293        deactivate();
 1294        waitForDeactivate();
 295
 1296        lock (_mutex)
 297        {
 298            //
 299            // Only a single thread is allowed to destroy the object
 300            // adapter. Other threads wait for the destruction to be
 301            // completed.
 302            //
 1303            while (_state == StateDestroying)
 304            {
 0305                Monitor.Wait(_mutex);
 306            }
 1307            if (_state == StateDestroyed)
 308            {
 1309                return;
 310            }
 1311            _state = StateDestroying;
 312
 1313            while (_directCount > 0)
 314            {
 1315                Monitor.Wait(_mutex);
 316            }
 1317        }
 318
 1319        if (_routerInfo is not null)
 320        {
 321            // Remove entry from the router manager.
 1322            _instance.routerManager().erase(_routerInfo.getRouter());
 323
 324            // Clear this object adapter with the router.
 1325            _routerInfo.setAdapter(null);
 326        }
 327
 1328        _instance.outgoingConnectionFactory().removeAdapter(this);
 329
 330        //
 331        // Now it's also time to clean up our servants and servant
 332        // locators.
 333        //
 1334        _servantManager.destroy();
 335
 336        //
 337        // Destroy the thread pool.
 338        //
 1339        if (_threadPool is not null)
 340        {
 1341            _threadPool.destroy();
 1342            _threadPool.joinWithAllThreads();
 343        }
 344
 1345        _objectAdapterFactory?.removeObjectAdapter(this);
 346
 1347        lock (_mutex)
 348        {
 349            //
 350            // We're done, now we can throw away all incoming connection
 351            // factories.
 352            //
 1353            _incomingConnectionFactories.Clear();
 354
 355            //
 356            // Remove object references (some of them cyclic).
 357            //
 1358            _threadPool = null;
 1359            _routerInfo = null;
 1360            _publishedEndpoints = [];
 1361            _locatorInfo = null;
 1362            _reference = null;
 1363            _objectAdapterFactory = null;
 364
 1365            _state = StateDestroyed;
 1366            Monitor.PulseAll(_mutex);
 1367        }
 1368    }
 369
 370    /// <summary>
 371    /// Install a middleware in this object adapter.
 372    /// </summary>
 373    /// <param name="middleware">The middleware to install.</param>
 374    /// <returns>This object adapter.</returns>
 375    /// <exception cref="InvalidOperationException">Thrown if the object adapter's dispatch pipeline has already been
 376    /// created. This creation typically occurs the first time the object adapter dispatches an incoming request.
 377    /// </exception>
 378    public ObjectAdapter use(Func<Object, Object> middleware)
 379    {
 1380        if (_dispatchPipeline.IsValueCreated)
 381        {
 0382            throw new InvalidOperationException("All middleware must be installed before the first dispatch.");
 383        }
 1384        _middlewareStack.Push(middleware);
 1385        return this;
 386    }
 387
 388    /// <summary>
 389    /// Add a servant to this object adapter's Active Servant Map.
 390    /// Note that one servant can implement several Ice
 391    /// objects by registering the servant with multiple identities. Adding a servant with an identity that is in the
 392    /// map already throws AlreadyRegisteredException.
 393    /// </summary>
 394    /// <param name="servant">The servant to add.</param>
 395    /// <param name="id">The identity of the Ice object that is implemented by the servant.</param>
 396    /// <returns>A proxy that matches the given identity and this object adapter.</returns>
 1397    public ObjectPrx add(Object servant, Identity id) => addFacet(servant, id, "");
 398
 399    /// <summary>
 400    /// Like add, but with a facet.
 401    /// Calling add(servant, id) is equivalent to calling
 402    /// addFacet with an empty facet.
 403    /// </summary>
 404    /// <param name="servant">The servant to add.</param>
 405    /// <param name="identity">The identity of the Ice object that is implemented by the servant.</param>
 406    /// <param name="facet">The facet. An empty facet means the default facet.</param>
 407    /// <returns>A proxy that matches the given identity, facet, and this object adapter.</returns>
 408    public ObjectPrx addFacet(Object servant, Identity identity, string facet)
 409    {
 1410        lock (_mutex)
 411        {
 1412            checkForDestruction();
 1413            checkIdentity(identity);
 1414            ArgumentNullException.ThrowIfNull(servant);
 415
 416            // Create a copy of the Identity argument, in case the caller reuses it.
 1417            var id = new Identity(identity.name, identity.category);
 1418            _servantManager.addServant(servant, id, facet);
 419
 1420            return newProxy(id, facet);
 421        }
 1422    }
 423
 424    /// <summary>
 425    /// Add a servant to this object adapter's Active Servant Map, using an automatically generated UUID as its
 426    /// identity. Note that the generated UUID identity can be accessed using the proxy's ice_getIdentity operation.
 427    /// </summary>
 428    /// <param name="servant">The servant to add.</param>
 429    /// <returns>A proxy that matches the generated UUID identity and this object adapter.</returns>
 1430    public ObjectPrx addWithUUID(Object servant) => addFacetWithUUID(servant, "");
 431
 432    /// <summary>
 433    /// Like addWithUUID, but with a facet.
 434    /// Calling addWithUUID(servant) is equivalent to calling
 435    /// addFacetWithUUID with an empty facet.
 436    /// </summary>
 437    /// <param name="servant">The servant to add.</param>
 438    /// <param name="facet">The facet. An empty facet means the default facet.</param>
 439    /// <returns>A proxy that matches the generated UUID identity, facet, and this object adapter.</returns>
 440    public ObjectPrx addFacetWithUUID(Object servant, string facet)
 441    {
 1442        var ident = new Identity(Guid.NewGuid().ToString(), "");
 1443        return addFacet(servant, ident, facet);
 444    }
 445
 446    /// <summary>
 447    /// Add a default servant to handle requests for a specific category.
 448    /// Adding a default servant for a category for
 449    /// which a default servant is already registered throws AlreadyRegisteredException. To dispatch operation
 450    /// calls on servants, the object adapter tries to find a servant for a given Ice object identity and facet in the
 451    /// following order:
 452    ///
 453    /// The object adapter tries to find a servant for the identity and facet in the Active Servant Map.
 454    /// If no servant has been found in the Active Servant Map, the object adapter tries to find a default servant
 455    /// for the category component of the identity.
 456    /// If no servant has been found by any of the preceding steps, the object adapter tries to find a default
 457    /// servant for an empty category, regardless of the category contained in the identity.
 458    /// If no servant has been found by any of the preceding steps, the object adapter gives up and the caller
 459    /// receives ObjectNotExistException or FacetNotExistException.
 460    /// </summary>
 461    /// <param name="servant">The default servant.</param>
 462    /// <param name="category">The category for which the default servant is registered. An empty category means it
 463    /// will handle all categories.</param>
 464    public void addDefaultServant(Ice.Object servant, string category)
 465    {
 1466        ArgumentNullException.ThrowIfNull(servant);
 467
 1468        lock (_mutex)
 469        {
 1470            checkForDestruction();
 1471            _servantManager.addDefaultServant(servant, category);
 1472        }
 1473    }
 474
 475    /// <summary>
 476    /// Remove a servant (that is, the default facet) from the object adapter's Active Servant Map.
 477    /// </summary>
 478    /// <param name="id">The identity of the Ice object that is implemented by the servant. If the servant implements mu
 479    /// Ice objects, remove has to be called for all those Ice objects. Removing an identity that is not in
 480    /// the map throws NotRegisteredException.</param>
 481    /// <returns>The removed servant.</returns>
 1482    public Object remove(Identity id) => removeFacet(id, "");
 483
 484    /// <summary>
 485    /// Like remove, but with a facet.
 486    /// Calling remove(id) is equivalent to calling
 487    /// removeFacet with an empty facet.
 488    /// </summary>
 489    /// <param name="id">The identity of the Ice object that is implemented by the servant.</param>
 490    /// <param name="facet">The facet. An empty facet means the default facet.</param>
 491    /// <returns>The removed servant.</returns>
 492    public Object removeFacet(Identity id, string facet)
 493    {
 1494        lock (_mutex)
 495        {
 1496            checkForDestruction();
 1497            checkIdentity(id);
 498
 1499            return _servantManager.removeServant(id, facet);
 500        }
 1501    }
 502
 503    /// <summary>
 504    /// Remove all facets with the given identity from the Active Servant Map.
 505    /// The operation completely removes the Ice
 506    /// object, including its default facet. Removing an identity that is not in the map throws
 507    /// NotRegisteredException.
 508    /// </summary>
 509    /// <param name="id">The identity of the Ice object to be removed.</param>
 510    /// <returns>A collection containing all the facet names and servants of the removed Ice object.</returns>
 511    public Dictionary<string, Object> removeAllFacets(Identity id)
 512    {
 1513        lock (_mutex)
 514        {
 1515            checkForDestruction();
 1516            checkIdentity(id);
 517
 1518            return _servantManager.removeAllFacets(id);
 519        }
 1520    }
 521
 522    /// <summary>
 523    /// Remove the default servant for a specific category.
 524    /// Attempting to remove a default servant for a category that
 525    /// is not registered throws NotRegisteredException.
 526    /// </summary>
 527    /// <param name="category">The category of the default servant to remove.</param>
 528    /// <returns>The default servant.</returns>
 529    public Object removeDefaultServant(string category)
 530    {
 1531        lock (_mutex)
 532        {
 1533            checkForDestruction();
 1534            return _servantManager.removeDefaultServant(category);
 535        }
 1536    }
 537
 538    /// <summary>
 539    /// Look up a servant in this object adapter's Active Servant Map by the identity of the Ice object it implements.
 540    /// This operation only tries to look up a servant in the Active Servant Map. It does not attempt to find a servant
 541    /// by using any installed ServantLocator.
 542    /// </summary>
 543    /// <param name="id">The identity of the Ice object for which the servant should be returned.</param>
 544    /// <returns>The servant that implements the Ice object with the given identity, or null if no such servant has
 545    /// been found.</returns>
 0546    public Object? find(Identity id) => findFacet(id, "");
 547
 548    /// <summary>
 549    /// Like find, but with a facet.
 550    /// Calling find(id) is equivalent to calling findFacet
 551    /// with an empty facet.
 552    /// </summary>
 553    /// <param name="id">The identity of the Ice object for which the servant should be returned.</param>
 554    /// <param name="facet">The facet. An empty facet means the default facet.</param>
 555    /// <returns>The servant that implements the Ice object with the given identity and facet, or null if no such
 556    /// servant has been found.</returns>
 557    public Object? findFacet(Identity id, string facet)
 558    {
 1559        lock (_mutex)
 560        {
 1561            checkForDestruction();
 1562            checkIdentity(id);
 563
 1564            return _servantManager.findServant(id, facet);
 565        }
 1566    }
 567
 568    /// <summary>
 569    /// Find all facets with the given identity in the Active Servant Map.
 570    /// </summary>
 571    /// <param name="id">The identity of the Ice object for which the facets should be returned.</param>
 572    /// <returns>A collection containing all the facet names and servants that have been found, or an empty map if there
 573    /// is no facet for the given identity.</returns>
 574    public Dictionary<string, Object> findAllFacets(Identity id)
 575    {
 1576        lock (_mutex)
 577        {
 1578            checkForDestruction();
 1579            checkIdentity(id);
 580
 1581            return _servantManager.findAllFacets(id);
 582        }
 1583    }
 584
 585    /// <summary>
 586    /// Look up a servant in this object adapter's Active Servant Map, given a proxy.
 587    /// This operation only tries to lookup a servant in the Active Servant Map. It does not attempt to find a servant
 588    /// by using any installed ServantLocator.</summary>
 589    /// <param name="proxy">The proxy for which the servant should be returned.</param>
 590    /// <returns>The servant that matches the proxy, or null if no such servant has been found.</returns>
 591    public Object? findByProxy(ObjectPrx proxy)
 592    {
 0593        lock (_mutex)
 594        {
 0595            checkForDestruction();
 0596            Reference @ref = ((ObjectPrxHelperBase)proxy).iceReference();
 0597            return findFacet(@ref.getIdentity(), @ref.getFacet());
 598        }
 0599    }
 600
 601    /// <summary>
 602    /// Add a Servant Locator to this object adapter.
 603    ///
 604    /// Adding a servant locator for a category for which a servant locator is already registered throws
 605    /// <see cref="AlreadyRegisteredException" />. To dispatch operation calls on servants, the object adapter tries to
 606    /// find a servant for a given Ice object identity and facet in the following order:
 607    ///
 608    /// The object adapter tries to find a servant for the identity and facet in the Active Servant Map.
 609    /// If no servant has been found in the Active Servant Map, the object adapter tries to find a servant locator
 610    /// for the category component of the identity. If a locator is found, the object adapter tries to find a servant
 611    /// using this locator.
 612    /// If no servant has been found by any of the preceding steps, the object adapter tries to find a locator for
 613    /// an empty category, regardless of the category contained in the identity. If a locator is found, the object
 614    /// adapter tries to find a servant using this locator.
 615    /// If no servant has been found by any of the preceding steps, the object adapter gives up and the caller
 616    /// receives <see cref="ObjectNotExistException" /> or <see cref="FacetNotExistException" />.
 617    /// </summary>
 618    /// <param name="locator">The locator to add.</param>
 619    /// <param name="category">The category for which the Servant Locator can locate servants, or an empty string if the
 620    /// Servant Locator does not belong to any specific category.</param>
 621    public void addServantLocator(ServantLocator locator, string category)
 622    {
 1623        lock (_mutex)
 624        {
 1625            checkForDestruction();
 1626            _servantManager.addServantLocator(locator, category);
 1627        }
 1628    }
 629
 630    /// <summary>
 631    /// Remove a Servant Locator from this object adapter.
 632    /// </summary>
 633    /// <param name="category">The category for which the Servant Locator can locate servants, or an empty string if the
 634    /// servant locator does not belong to any specific category.</param>
 635    /// <returns>The Servant Locator, or throws <see cref="NotRegisteredException"/> if no Servant Locator was found
 636    /// for the given category.</returns>
 637    public ServantLocator removeServantLocator(string category)
 638    {
 1639        lock (_mutex)
 640        {
 1641            checkForDestruction();
 1642            return _servantManager.removeServantLocator(category);
 643        }
 1644    }
 645
 646    /// <summary>
 647    /// Find a Servant Locator installed with this object adapter.
 648    /// </summary>
 649    /// <param name="category">The category for which the Servant Locator can locate servants, or an empty string if the
 650    /// Servant Locator does not belong to any specific category.
 651    /// </param>
 652    /// <returns>The servant locator, or null if no servant locator was found for the given category.</returns>
 653    public ServantLocator? findServantLocator(string category)
 654    {
 0655        lock (_mutex)
 656        {
 0657            checkForDestruction();
 0658            return _servantManager.findServantLocator(category);
 659        }
 0660    }
 661
 662    /// <summary>
 663    /// Find the default servant for a specific category.
 664    /// </summary>
 665    /// <param name="category">The category of the default servant to find.</param>
 666    /// <returns>The default servant or null if no default servant was registered for the category.</returns>
 667    public Object? findDefaultServant(string category)
 668    {
 1669        lock (_mutex)
 670        {
 1671            checkForDestruction();
 1672            return _servantManager.findDefaultServant(category);
 673        }
 1674    }
 675
 676    /// <summary>
 677    /// Gets the dispatch pipeline of this object adapter.
 678    /// </summary>
 679    /// <value>The dispatch pipeline.</value>
 1680    public Object dispatchPipeline => _dispatchPipeline.Value;
 681
 682    /// <summary>
 683    /// Create a proxy for the object with the given identity.
 684    /// If this object adapter is configured with an adapter id,
 685    /// the return value is an indirect proxy that refers to the adapter id. If a replica group id is also defined, the
 686    /// return value is an indirect proxy that refers to the replica group id. Otherwise, if no adapter id is defined,
 687    /// the return value is a direct proxy containing this object adapter's published endpoints.
 688    /// </summary>
 689    /// <param name="id">The object's identity.</param>
 690    /// <returns>A proxy for the object with the given identity.</returns>
 691    public ObjectPrx createProxy(Identity id)
 692    {
 1693        lock (_mutex)
 694        {
 1695            checkForDestruction();
 1696            checkIdentity(id);
 697
 1698            return newProxy(id, "");
 699        }
 1700    }
 701
 702    /// <summary>
 703    /// Create a direct proxy for the object with the given identity.
 704    /// The returned proxy contains this object adapter's
 705    /// published endpoints.
 706    /// </summary>
 707    /// <param name="id">The object's identity.</param>
 708    /// <returns>A proxy for the object with the given identity.</returns>
 709    public ObjectPrx createDirectProxy(Identity id)
 710    {
 1711        lock (_mutex)
 712        {
 1713            checkForDestruction();
 1714            checkIdentity(id);
 715
 1716            return newDirectProxy(id, "");
 717        }
 1718    }
 719
 720    /// <summary>
 721    /// Create an indirect proxy for the object with the given identity.
 722    /// If this object adapter is configured with an
 723    /// adapter id, the return value refers to the adapter id. Otherwise, the return value contains only the object
 724    /// identity.
 725    /// </summary>
 726    /// <param name="id">The object's identity.</param>
 727    /// <returns>A proxy for the object with the given identity.</returns>
 728    public ObjectPrx createIndirectProxy(Identity id)
 729    {
 1730        lock (_mutex)
 731        {
 1732            checkForDestruction();
 1733            checkIdentity(id);
 734
 1735            return newIndirectProxy(id, "", _id);
 736        }
 1737    }
 738
 739    /// <summary>
 740    /// Set an Ice locator for this object adapter.
 741    /// By doing so, the object adapter will register itself with the
 742    /// locator registry when it is activated for the first time. Furthermore, the proxies created by this object
 743    /// adapter will contain the adapter identifier instead of its endpoints. The adapter identifier must be configured
 744    /// using the AdapterId property.
 745    /// </summary>
 746    /// <param name="locator">The locator used by this object adapter.</param>
 747    public void setLocator(LocatorPrx? locator)
 748    {
 1749        lock (_mutex)
 750        {
 1751            checkForDeactivation();
 1752            _locatorInfo = _instance.locatorManager().get(locator);
 1753        }
 1754    }
 755
 756    /// <summary>
 757    /// Get the Ice locator used by this object adapter.
 758    /// </summary>
 759    /// <returns>The locator used by this object adapter, or null if no locator is used by this object adapter.
 760    /// </returns>
 761    public LocatorPrx? getLocator()
 762    {
 1763        lock (_mutex)
 764        {
 1765            return _locatorInfo?.getLocator();
 766        }
 1767    }
 768
 769    /// <summary>
 770    /// Get the set of endpoints configured with this object adapter.
 771    /// </summary>
 772    /// <returns>The set of endpoints.</returns>
 773    public Endpoint[] getEndpoints()
 774    {
 1775        lock (_mutex)
 776        {
 1777            var endpoints = new List<Endpoint>();
 1778            foreach (IncomingConnectionFactory factory in _incomingConnectionFactories)
 779            {
 1780                endpoints.Add(factory.endpoint());
 781            }
 1782            return endpoints.ToArray();
 783        }
 1784    }
 785
 786    /// <summary>
 787    /// Get the set of endpoints that proxies created by this object adapter will contain.
 788    /// </summary>
 789    /// <returns>The set of published endpoints.
 790    /// </returns>
 791    public Endpoint[] getPublishedEndpoints()
 792    {
 1793        lock (_mutex)
 794        {
 1795            return (Endpoint[])_publishedEndpoints.Clone();
 796        }
 1797    }
 798
 799    /// <summary>
 800    /// Set of the endpoints that proxies created by this object adapter will contain.
 801    /// </summary>
 802    /// <param name="newEndpoints">The new set of endpoints that the object adapter will embed in proxies.
 803    /// </param>
 804    public void setPublishedEndpoints(Endpoint[] newEndpoints)
 805    {
 1806        LocatorInfo? locatorInfo = null;
 807        EndpointI[] oldPublishedEndpoints;
 808
 1809        lock (_mutex)
 810        {
 1811            checkForDeactivation();
 1812            if (_routerInfo is not null)
 813            {
 1814                throw new ArgumentException(
 1815                                "can't set published endpoints on object adapter associated with a router");
 816            }
 817
 1818            oldPublishedEndpoints = _publishedEndpoints;
 1819            _publishedEndpoints = Array.ConvertAll(newEndpoints, endpt => (EndpointI)endpt);
 1820            locatorInfo = _locatorInfo;
 1821        }
 822
 823        try
 824        {
 1825            var dummy = new Identity("dummy", "");
 1826            updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
 1827        }
 0828        catch (LocalException)
 829        {
 0830            lock (_mutex)
 831            {
 832                //
 833                // Restore the old published endpoints.
 834                //
 0835                _publishedEndpoints = oldPublishedEndpoints;
 0836                throw;
 837            }
 838        }
 1839    }
 840
 841    internal bool isLocal(Reference r)
 842    {
 843        //
 844        // NOTE: it's important that isLocal() doesn't perform any blocking operations as
 845        // it can be called for AMI invocations if the proxy has no delegate set yet.
 846        //
 847
 1848        if (r.isWellKnown())
 849        {
 850            //
 851            // Check the active servant map to see if the well-known
 852            // proxy is for a local object.
 853            //
 1854            return _servantManager.hasServant(r.getIdentity());
 855        }
 1856        else if (r.isIndirect())
 857        {
 858            //
 859            // Proxy is local if the reference adapter id matches this
 860            // adapter id or replica group id.
 861            //
 1862            return r.getAdapterId().Equals(_id, StringComparison.Ordinal) ||
 1863                r.getAdapterId().Equals(_replicaGroupId, StringComparison.Ordinal);
 864        }
 865        else
 866        {
 867            // Proxies which have at least one endpoint in common with the published endpoints are considered local.
 868            // This check doesn't take datagram endpoints into account; this effectively disables colloc optimization
 869            // for UDP.
 1870            lock (_mutex)
 871            {
 1872                checkForDestruction();
 1873                IEnumerable<EndpointI> endpoints = r.getEndpoints().Where(e => !e.datagram());
 1874                return _publishedEndpoints.Any(e => endpoints.Any(e.equivalent));
 875            }
 876        }
 1877    }
 878
 879    internal void flushAsyncBatchRequests(Ice.CompressBatch compressBatch, CommunicatorFlushBatchAsync outAsync)
 880    {
 881        List<IncomingConnectionFactory> f;
 1882        lock (_mutex)
 883        {
 1884            f = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
 1885        }
 886
 1887        foreach (IncomingConnectionFactory factory in f)
 888        {
 1889            factory.flushAsyncBatchRequests(compressBatch, outAsync);
 890        }
 1891    }
 892
 893    internal void updateConnectionObservers()
 894    {
 895        List<IncomingConnectionFactory> f;
 1896        lock (_mutex)
 897        {
 1898            f = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
 1899        }
 900
 1901        foreach (IncomingConnectionFactory p in f)
 902        {
 1903            p.updateConnectionObservers();
 904        }
 1905    }
 906
 907    internal void updateThreadObservers()
 908    {
 909        Ice.Internal.ThreadPool? threadPool;
 1910        lock (_mutex)
 911        {
 1912            threadPool = _threadPool;
 1913        }
 914
 1915        threadPool?.updateObservers();
 1916    }
 917
 918    internal void incDirectCount()
 919    {
 1920        lock (_mutex)
 921        {
 1922            checkForDestruction();
 923
 924            Debug.Assert(_directCount >= 0);
 1925            ++_directCount;
 1926        }
 1927    }
 928
 929    internal void decDirectCount()
 930    {
 1931        lock (_mutex)
 932        {
 933            // Not check for destruction here!
 934
 935            Debug.Assert(_instance is not null); // destroy waits for _directCount to reach 0
 936
 937            Debug.Assert(_directCount > 0);
 1938            if (--_directCount == 0)
 939            {
 1940                Monitor.PulseAll(_mutex);
 941            }
 1942        }
 1943    }
 944
 945    internal Ice.Internal.ThreadPool getThreadPool()
 946    {
 947        // No mutex lock necessary, _threadPool and _instance are
 948        // immutable after creation until they are removed in
 949        // destroy().
 950
 951        // Not check for deactivation here!
 952
 953        Debug.Assert(_instance is not null); // Must not be called after destroy().
 954
 1955        if (_threadPool is not null)
 956        {
 1957            return _threadPool;
 958        }
 959        else
 960        {
 1961            return _instance.serverThreadPool();
 962        }
 963    }
 964
 965    internal void setAdapterOnConnection(Ice.ConnectionI connection)
 966    {
 1967        lock (_mutex)
 968        {
 1969            checkForDestruction();
 1970            connection.setAdapterFromAdapter(this);
 1971        }
 1972    }
 973
 1974    internal int messageSizeMax() => _messageSizeMax;
 975
 976    //
 977    // Only for use by ObjectAdapterFactory
 978    //
 1979    internal ObjectAdapter(
 1980        Instance instance,
 1981        Communicator communicator,
 1982        ObjectAdapterFactory objectAdapterFactory,
 1983        string name,
 1984        RouterPrx? router,
 1985        bool noConfig,
 1986        SslServerAuthenticationOptions? serverAuthenticationOptions)
 987    {
 1988        _instance = instance;
 1989        _communicator = communicator;
 1990        _objectAdapterFactory = objectAdapterFactory;
 1991        _servantManager = new ServantManager(instance, name);
 992
 1993        _dispatchPipeline = new Lazy<Object>(createDispatchPipeline);
 1994        _name = name;
 1995        _incomingConnectionFactories = [];
 1996        _publishedEndpoints = [];
 1997        _routerInfo = null;
 1998        _directCount = 0;
 1999        _noConfig = noConfig;
 11000        _serverAuthenticationOptions = serverAuthenticationOptions;
 1001
 1002        // Install default middleware depending on the communicator's configuration.
 11003        if (_instance.initializationData().logger is Logger logger)
 1004        {
 11005            int warningLevel = _instance.initializationData().properties!.getIcePropertyAsInt("Ice.Warn.Dispatch");
 11006            if (_instance.traceLevels().dispatch > 0 || warningLevel > 0)
 1007            {
 11008                use(next =>
 11009                    new LoggerMiddleware(
 11010                        next,
 11011                        logger,
 11012                        _instance.traceLevels().dispatch,
 11013                        _instance.traceLevels().dispatchCat,
 11014                        warningLevel,
 11015                        _instance.toStringMode()));
 1016            }
 1017        }
 11018        if (_instance.initializationData().observer is CommunicatorObserver observer)
 1019        {
 11020            use(next => new ObserverMiddleware(next, observer));
 1021        }
 1022
 11023        if (_noConfig)
 1024        {
 11025            _id = "";
 11026            _replicaGroupId = "";
 11027            _reference = _instance.referenceFactory().create("dummy -t", "");
 11028            return;
 1029        }
 1030
 11031        Properties properties = _instance.initializationData().properties!;
 11032        Properties.validatePropertiesWithPrefix(_name, properties, PropertyNames.ObjectAdapterProps);
 1033
 1034        //
 1035        // Make sure named adapter has configuration.
 1036        //
 11037        if (router is null && properties.getPropertiesForPrefix($"{_name}.").Count == 0)
 1038        {
 1039            //
 1040            // These need to be set to prevent warnings/asserts in the destructor.
 1041            //
 11042            _state = StateDestroyed;
 11043            _incomingConnectionFactories = [];
 1044
 11045            throw new InitializationException($"Object adapter '{name}' requires configuration.");
 1046        }
 1047
 11048        _id = properties.getProperty(_name + ".AdapterId");
 11049        _replicaGroupId = properties.getProperty(_name + ".ReplicaGroupId");
 1050
 1051        //
 1052        // Setup a reference to be used to get the default proxy options
 1053        // when creating new proxies. By default, create twoway proxies.
 1054        //
 11055        string proxyOptions = properties.getPropertyWithDefault(_name + ".ProxyOptions", "-t");
 1056        try
 1057        {
 11058            _reference = _instance.referenceFactory().create("dummy " + proxyOptions, "");
 11059        }
 01060        catch (ParseException ex)
 1061        {
 01062            throw new InitializationException(
 01063                $"Invalid proxy options '{proxyOptions}' for object adapter '{_name}'.",
 01064                ex);
 1065        }
 1066
 1067        // The maximum size of an Ice protocol message in bytes. This is limited to 0x7fffffff, which corresponds to
 1068        // the maximum value of a 32-bit signed integer (int).
 1069        const int messageSizeMaxUpperLimit = int.MaxValue;
 11070        int defaultMessageSizeMax = instance.messageSizeMax() / 1024;
 11071        int messageSizeMax = properties.getPropertyAsIntWithDefault($"{_name}.MessageSizeMax", defaultMessageSizeMax);
 11072        if (messageSizeMax > messageSizeMaxUpperLimit / 1024)
 1073        {
 01074            throw new Ice.InitializationException(
 01075                $"{_name}.MessageSizeMax '{messageSizeMax}' is too large, it must be less than or equal to '{messageSize
 1076        }
 11077        else if (messageSizeMax < 1)
 1078        {
 11079            _messageSizeMax = messageSizeMaxUpperLimit;
 1080        }
 1081        else
 1082        {
 1083            // The property is specified in kibibytes (KiB); _messageSizeMax is stored in bytes.
 11084            _messageSizeMax = messageSizeMax * 1024;
 1085        }
 1086
 1087        try
 1088        {
 11089            int threadPoolSize = properties.getPropertyAsInt(_name + ".ThreadPool.Size");
 11090            int threadPoolSizeMax = properties.getPropertyAsInt(_name + ".ThreadPool.SizeMax");
 11091            if (threadPoolSize > 0 || threadPoolSizeMax > 0)
 1092            {
 11093                _threadPool = new Ice.Internal.ThreadPool(_instance, _name + ".ThreadPool", 0);
 1094            }
 1095
 11096            router ??= RouterPrxHelper.uncheckedCast(communicator.propertyToProxy(_name + ".Router"));
 11097            if (router is not null)
 1098            {
 11099                _routerInfo = _instance.routerManager().get(router);
 1100                Debug.Assert(_routerInfo is not null);
 1101
 11102                if (properties.getProperty($"{_name}.Endpoints").Length > 0)
 1103                {
 11104                    throw new InitializationException(
 11105                        "An object adapter with a router cannot accept incoming connections.");
 1106                }
 1107
 1108                //
 1109                // Make sure this router is not already registered with another adapter.
 1110                //
 11111                if (_routerInfo.getAdapter() is not null)
 1112                {
 01113                    throw new AlreadyRegisteredException(
 01114                        "object adapter with router",
 01115                        Util.identityToString(router.ice_getIdentity(), _instance.toStringMode()));
 1116                }
 1117
 1118                //
 1119                // Associate this object adapter with the router. This way,
 1120                // new outgoing connections to the router's client proxy will
 1121                // use this object adapter for callbacks.
 1122                //
 11123                _routerInfo.setAdapter(this);
 1124
 1125                //
 1126                // Also modify all existing outgoing connections to the
 1127                // router's client proxy to use this object adapter for
 1128                // callbacks.
 1129                //
 11130                _instance.outgoingConnectionFactory().setRouterInfo(_routerInfo);
 1131            }
 1132            else
 1133            {
 1134                //
 1135                // Parse the endpoints, but don't store them in the adapter. The connection
 1136                // factory might change it, for example, to fill in the real port number.
 1137                //
 11138                List<EndpointI> endpoints = parseEndpoints(properties.getProperty(_name + ".Endpoints"), true);
 11139                foreach (EndpointI endp in endpoints)
 1140                {
 11141                    foreach (EndpointI expanded in endp.expandHost())
 1142                    {
 11143                        var factory = new IncomingConnectionFactory(instance, expanded, this);
 11144                        _incomingConnectionFactories.Add(factory);
 1145                    }
 1146                }
 11147                if (endpoints.Count == 0)
 1148                {
 11149                    TraceLevels tl = _instance.traceLevels();
 11150                    if (tl.network >= 2)
 1151                    {
 11152                        _instance.initializationData().logger!.trace(
 11153                            tl.networkCat,
 11154                            $"created adapter '{_name}' without endpoints");
 1155                    }
 1156                }
 1157            }
 1158
 1159            //
 1160            // Parse published endpoints.
 1161            //
 11162            _publishedEndpoints = computePublishedEndpoints();
 1163
 11164            if (properties.getProperty(_name + ".Locator").Length > 0)
 1165            {
 01166                setLocator(LocatorPrxHelper.uncheckedCast(communicator.propertyToProxy(_name + ".Locator")));
 1167            }
 1168            else
 1169            {
 11170                setLocator(_instance.referenceFactory().getDefaultLocator());
 1171            }
 11172        }
 11173        catch (LocalException)
 1174        {
 11175            destroy();
 11176            throw;
 1177        }
 11178    }
 1179
 1180    internal static void checkIdentity(Identity ident)
 1181    {
 11182        if (ident.name.Length == 0)
 1183        {
 11184            throw new ArgumentException("The name of an Ice object identity cannot be empty.", nameof(ident));
 1185        }
 11186    }
 1187
 11188    internal SslServerAuthenticationOptions? getServerAuthenticationOptions() => _serverAuthenticationOptions;
 1189
 1190    private ObjectPrx newProxy(Identity ident, string facet)
 1191    {
 11192        if (_id.Length == 0)
 1193        {
 11194            return newDirectProxy(ident, facet);
 1195        }
 11196        else if (_replicaGroupId.Length == 0)
 1197        {
 11198            return newIndirectProxy(ident, facet, _id);
 1199        }
 1200        else
 1201        {
 11202            return newIndirectProxy(ident, facet, _replicaGroupId);
 1203        }
 1204    }
 1205
 1206    private ObjectPrx newDirectProxy(Identity ident, string facet) =>
 11207        new ObjectPrxHelper(_instance.referenceFactory().create(ident, facet, _reference, _publishedEndpoints));
 1208
 1209    private ObjectPrx newIndirectProxy(Identity ident, string facet, string id) =>
 11210        new ObjectPrxHelper(_instance.referenceFactory().create(ident, facet, _reference, id));
 1211
 1212    private void checkForDeactivation()
 1213    {
 11214        checkForDestruction();
 1215
 11216        if (_state >= StateDeactivating)
 1217        {
 01218            throw new ObjectAdapterDeactivatedException(getName());
 1219        }
 11220    }
 1221
 1222    private void checkForDestruction()
 1223    {
 11224        if (_state >= StateDestroying)
 1225        {
 11226            throw new ObjectAdapterDestroyedException(getName());
 1227        }
 11228    }
 1229
 1230    private List<EndpointI> parseEndpoints(string endpts, bool oaEndpoints)
 1231    {
 1232        int beg;
 11233        int end = 0;
 1234
 11235        string delim = " \t\n\r";
 1236
 11237        var endpoints = new List<EndpointI>();
 11238        while (end < endpts.Length)
 1239        {
 11240            beg = Ice.UtilInternal.StringUtil.findFirstNotOf(endpts, delim, end);
 11241            if (beg == -1)
 1242            {
 11243                if (endpoints.Count != 0)
 1244                {
 11245                    throw new ParseException("invalid empty object adapter endpoint");
 1246                }
 1247                break;
 1248            }
 1249
 11250            end = beg;
 11251            while (true)
 1252            {
 11253                end = endpts.IndexOf(':', end);
 11254                if (end == -1)
 1255                {
 11256                    end = endpts.Length;
 11257                    break;
 1258                }
 1259                else
 1260                {
 11261                    bool quoted = false;
 11262                    int quote = beg;
 11263                    while (true)
 1264                    {
 11265                        quote = endpts.IndexOf('\"', quote);
 11266                        if (quote == -1 || end < quote)
 1267                        {
 1268                            break;
 1269                        }
 1270                        else
 1271                        {
 11272                            quote = endpts.IndexOf('\"', ++quote);
 11273                            if (quote == -1)
 1274                            {
 1275                                break;
 1276                            }
 11277                            else if (end < quote)
 1278                            {
 11279                                quoted = true;
 11280                                break;
 1281                            }
 11282                            ++quote;
 1283                        }
 1284                    }
 11285                    if (!quoted)
 1286                    {
 1287                        break;
 1288                    }
 11289                    ++end;
 1290                }
 1291            }
 1292
 11293            if (end == beg)
 1294            {
 11295                throw new ParseException("invalid empty object adapter endpoint");
 1296            }
 1297
 11298            string s = endpts[beg..end];
 11299            EndpointI endp = _instance.endpointFactoryManager().create(s, oaEndpoints) ??
 11300                throw new ParseException($"invalid object adapter endpoint '{s}'");
 11301            endpoints.Add(endp);
 1302
 11303            ++end;
 1304        }
 1305
 11306        return endpoints;
 1307    }
 1308
 1309    private EndpointI[] computePublishedEndpoints()
 1310    {
 1311        IEnumerable<EndpointI> endpoints;
 11312        if (_routerInfo is not null)
 1313        {
 1314            // Get the router's server proxy endpoints and use them as the published endpoints.
 11315            endpoints = _routerInfo.getServerEndpoints();
 1316        }
 1317        else
 1318        {
 1319            // Parse published endpoints. If set, these are used instead of the connection factory endpoints.
 11320            endpoints = parseEndpoints(
 11321                _instance.initializationData().properties!.getProperty($"{_name}.PublishedEndpoints"),
 11322                oaEndpoints: false);
 1323
 11324            if (!endpoints.Any())
 1325            {
 1326                // If the PublishedEndpoints property isn't set, we compute the published endpoints from the factory
 1327                // endpoints.
 11328                endpoints = _incomingConnectionFactories.Select(f => f.endpoint());
 1329
 1330                // Remove all loopback/multicast endpoints.
 11331                IEnumerable<EndpointI> endpointsNoLoopback = endpoints.Where(e => !e.isLoopbackOrMulticast());
 1332
 1333                // Retrieve published host
 11334                string publishedHost = _instance.initializationData().properties!.getProperty($"{_name}.PublishedHost");
 1335
 11336                if (endpointsNoLoopback.Any())
 1337                {
 11338                    endpoints = endpointsNoLoopback;
 1339
 1340                    // For non-loopback & non-multicast endpoints, we use the fully qualified name of the local host as
 1341                    // default for publishedHost.
 11342                    if (publishedHost.Length == 0)
 1343                    {
 11344                        publishedHost = Dns.GetHostEntry("").HostName; // fully qualified name of local host
 1345                    }
 1346                }
 1347
 1348                // Replace the host in all endpoints by publishedHost (when applicable) and clear all local options.
 11349                endpoints = endpoints.Select(e => e.toPublishedEndpoint(publishedHost)).Distinct();
 1350            }
 1351        }
 1352
 11353        EndpointI[] endpointsArray = endpoints.ToArray();
 1354
 11355        if (_instance.traceLevels().network >= 1 && endpointsArray.Length > 0)
 1356        {
 11357            var s = new StringBuilder("published endpoints for object adapter '");
 11358            s.Append(_name);
 11359            s.Append("':\n");
 11360            bool first = true;
 11361            foreach (EndpointI endpoint in endpointsArray)
 1362            {
 11363                if (!first)
 1364                {
 01365                    s.Append(':');
 1366                }
 11367                s.Append(endpoint.ToString());
 11368                first = false;
 1369            }
 11370            _instance.initializationData().logger!.trace(_instance.traceLevels().networkCat, s.ToString());
 1371        }
 1372
 11373        return endpointsArray;
 1374    }
 1375
 1376    private void updateLocatorRegistry(LocatorInfo? locatorInfo, ObjectPrx? proxy)
 1377    {
 11378        if (_id.Length == 0 || locatorInfo is null)
 1379        {
 11380            return; // Nothing to update.
 1381        }
 1382
 1383        //
 1384        // Call on the locator registry outside the synchronization to
 1385        // blocking other threads that need to lock this OA.
 1386        //
 11387        LocatorRegistryPrx locatorRegistry = locatorInfo.getLocatorRegistry();
 11388        if (locatorRegistry is null)
 1389        {
 11390            return;
 1391        }
 1392
 1393        try
 1394        {
 11395            if (_replicaGroupId.Length == 0)
 1396            {
 11397                locatorRegistry.setAdapterDirectProxy(_id, proxy);
 1398            }
 1399            else
 1400            {
 11401                locatorRegistry.setReplicatedAdapterDirectProxy(_id, _replicaGroupId, proxy);
 1402            }
 11403        }
 01404        catch (AdapterNotFoundException)
 1405        {
 01406            if (_instance!.traceLevels().location >= 1)
 1407            {
 01408                var s = new StringBuilder();
 01409                s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
 01410                s.Append("the object adapter is not known to the locator registry");
 01411                _instance.initializationData().logger!.trace(_instance.traceLevels().locationCat, s.ToString());
 1412            }
 1413
 01414            throw new NotRegisteredException("object adapter", _id);
 1415        }
 01416        catch (InvalidReplicaGroupIdException)
 1417        {
 01418            if (_instance.traceLevels().location >= 1)
 1419            {
 01420                var s = new StringBuilder();
 01421                s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
 01422                s.Append("the replica group `" + _replicaGroupId + "' is not known to the locator registry");
 01423                _instance.initializationData().logger!.trace(_instance.traceLevels().locationCat, s.ToString());
 1424            }
 1425
 01426            throw new NotRegisteredException("replica group", _replicaGroupId);
 1427        }
 01428        catch (AdapterAlreadyActiveException)
 1429        {
 01430            if (_instance.traceLevels().location >= 1)
 1431            {
 01432                var s = new StringBuilder();
 01433                s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
 01434                s.Append("the object adapter endpoints are already set");
 01435                _instance.initializationData().logger!.trace(_instance.traceLevels().locationCat, s.ToString());
 1436            }
 1437
 01438            throw new ObjectAdapterIdInUseException(_id);
 1439        }
 01440        catch (ObjectAdapterDeactivatedException)
 1441        {
 1442            // Expected if collocated call and OA is deactivated, ignore.
 01443        }
 01444        catch (ObjectAdapterDestroyedException)
 1445        {
 1446            // Ignore
 01447        }
 01448        catch (CommunicatorDestroyedException)
 1449        {
 1450            // Ignore
 01451        }
 11452        catch (LocalException e)
 1453        {
 11454            if (_instance.traceLevels().location >= 1)
 1455            {
 11456                var s = new StringBuilder();
 11457                s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
 11458                s.Append(e.ToString());
 11459                _instance.initializationData().logger!.trace(_instance.traceLevels().locationCat, s.ToString());
 1460            }
 11461            throw; // TODO: Shall we raise a special exception instead of a non obvious local exception?
 1462        }
 1463
 11464        if (_instance.traceLevels().location >= 1)
 1465        {
 11466            var s = new StringBuilder();
 11467            s.Append("updated object adapter `" + _id + "' endpoints with the locator registry\n");
 11468            s.Append("endpoints = ");
 11469            if (proxy is not null)
 1470            {
 11471                Endpoint[] endpoints = proxy.ice_getEndpoints();
 11472                for (int i = 0; i < endpoints.Length; i++)
 1473                {
 11474                    s.Append(endpoints[i].ToString());
 11475                    if (i + 1 < endpoints.Length)
 1476                    {
 01477                        s.Append(':');
 1478                    }
 1479                }
 1480            }
 11481            _instance.initializationData().logger!.trace(_instance.traceLevels().locationCat, s.ToString());
 1482        }
 11483    }
 1484
 1485    private Object createDispatchPipeline()
 1486    {
 11487        Object dispatchPipeline = _servantManager; // the "final" dispatcher
 11488        foreach (Func<Object, Object> middleware in _middlewareStack)
 1489        {
 11490            dispatchPipeline = middleware(dispatchPipeline);
 1491        }
 11492        _middlewareStack.Clear(); // we no longer need these functions
 11493        return dispatchPipeline;
 1494    }
 1495}

Methods/Properties

.ctor(Ice.Internal.Instance, Ice.Communicator, Ice.Internal.ObjectAdapterFactory, string, Ice.RouterPrx, bool, System.Net.Security.SslServerAuthenticationOptions)
getName()
getCommunicator()
activate()
hold()
waitForHold()
deactivate()
waitForDeactivate()
isDeactivated()
destroy()
use(System.Func<Ice.Object, Ice.Object>)
add(Ice.Object, Ice.Identity)
addFacet(Ice.Object, Ice.Identity, string)
addWithUUID(Ice.Object)
addFacetWithUUID(Ice.Object, string)
addDefaultServant(Ice.Object, string)
remove(Ice.Identity)
removeFacet(Ice.Identity, string)
removeAllFacets(Ice.Identity)
removeDefaultServant(string)
find(Ice.Identity)
findFacet(Ice.Identity, string)
findAllFacets(Ice.Identity)
findByProxy(Ice.ObjectPrx)
addServantLocator(Ice.ServantLocator, string)
removeServantLocator(string)
findServantLocator(string)
findDefaultServant(string)
get_dispatchPipeline()
createProxy(Ice.Identity)
createDirectProxy(Ice.Identity)
createIndirectProxy(Ice.Identity)
setLocator(Ice.LocatorPrx)
getLocator()
getEndpoints()
getPublishedEndpoints()
setPublishedEndpoints(Ice.Endpoint[])
isLocal(Ice.Internal.Reference)
flushAsyncBatchRequests(Ice.CompressBatch, Ice.Internal.CommunicatorFlushBatchAsync)
updateConnectionObservers()
updateThreadObservers()
incDirectCount()
decDirectCount()
getThreadPool()
setAdapterOnConnection(Ice.ConnectionI)
messageSizeMax()
checkIdentity(Ice.Identity)
getServerAuthenticationOptions()
newProxy(Ice.Identity, string)
newDirectProxy(Ice.Identity, string)
newIndirectProxy(Ice.Identity, string, string)
checkForDeactivation()
checkForDestruction()
parseEndpoints(string, bool)
computePublishedEndpoints()
updateLocatorRegistry(Ice.Internal.LocatorInfo, Ice.ObjectPrx)
createDispatchPipeline()