// ********************************************************************** // // Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** package IceInternal; public final class RouterInfo { interface GetClientEndpointsCallback { void setEndpoints(EndpointI[] endpoints); void setException(Ice.LocalException ex); } interface AddProxyCallback { void addedProxy(); void setException(Ice.LocalException ex); } RouterInfo(Ice.RouterPrx router) { _router = router; assert(_router != null); } synchronized public void destroy() { _clientEndpoints = new EndpointI[0]; _serverEndpoints = new EndpointI[0]; _adapter = null; _identities.clear(); } public boolean equals(java.lang.Object obj) { if(this == obj) { return true; } if(obj instanceof RouterInfo) { return _router.equals(((RouterInfo)obj)._router); } return false; } public int hashCode() { return _router.hashCode(); } public Ice.RouterPrx getRouter() { // // No mutex lock necessary, _router is immutable. // return _router; } public EndpointI[] getClientEndpoints() { synchronized(this) { if(_clientEndpoints != null) // Lazy initialization. { return _clientEndpoints; } } return setClientEndpoints(_router.getClientProxy()); } public void getClientEndpoints(final GetClientEndpointsCallback callback) { EndpointI[] clientEndpoints = null; synchronized(this) { clientEndpoints = _clientEndpoints; } if(clientEndpoints != null) { callback.setEndpoints(clientEndpoints); return; } _router.getClientProxy_async(new Ice.AMI_Router_getClientProxy() { public void ice_response(Ice.ObjectPrx clientProxy) { callback.setEndpoints(setClientEndpoints(clientProxy)); } public void ice_exception(Ice.LocalException ex) { if(ex instanceof Ice.CollocationOptimizationException) { try { callback.setEndpoints(getClientEndpoints()); } catch(Ice.LocalException e) { callback.setException(e); } } else { callback.setException(ex); } } }); } public EndpointI[] getServerEndpoints() { synchronized(this) { if(_serverEndpoints != null) // Lazy initialization. { return _serverEndpoints; } } return setServerEndpoints(_router.getServerProxy()); } public void addProxy(Ice.ObjectPrx proxy) { assert(proxy != null); synchronized(this) { if(_identities.contains(proxy.ice_getIdentity())) { // // Only add the proxy to the router if it's not already in our local map. // return; } } addAndEvictProxies(proxy, _router.addProxies(new Ice.ObjectPrx[] { proxy })); } public boolean addProxy(final Ice.ObjectPrx proxy, final AddProxyCallback callback) { assert(proxy != null); synchronized(this) { if(_identities.contains(proxy.ice_getIdentity())) { // // Only add the proxy to the router if it's not already in our local map. // return true; } } _router.addProxies_async(new Ice.AMI_Router_addProxies() { public void ice_response(Ice.ObjectPrx[] evictedProxies) { addAndEvictProxies(proxy, evictedProxies); callback.addedProxy(); } public void ice_exception(Ice.LocalException ex) { if(ex instanceof Ice.CollocationOptimizationException) { try { addProxy(proxy); callback.addedProxy(); } catch(Ice.LocalException e) { callback.setException(ex); } } else { callback.setException(ex); } } }, new Ice.ObjectPrx[] { proxy }); return false; } public synchronized void setAdapter(Ice.ObjectAdapter adapter) { _adapter = adapter; } public synchronized Ice.ObjectAdapter getAdapter() { return _adapter; } private synchronized EndpointI[] setClientEndpoints(Ice.ObjectPrx clientProxy) { if(_clientEndpoints == null) { if(clientProxy == null) { // // If getClientProxy() return nil, use router endpoints. // _clientEndpoints = ((Ice.ObjectPrxHelperBase)_router).__reference().getEndpoints(); } else { clientProxy = clientProxy.ice_router(null); // The client proxy cannot be routed. // // In order to avoid creating a new connection to the // router, we must use the same timeout as the already // existing connection. // try { clientProxy = clientProxy.ice_timeout(_router.ice_getConnection().timeout()); } catch(Ice.CollocationOptimizationException ex) { // Ignore - collocated router. } _clientEndpoints = ((Ice.ObjectPrxHelperBase)clientProxy).__reference().getEndpoints(); } } return _clientEndpoints; } private synchronized EndpointI[] setServerEndpoints(Ice.ObjectPrx serverProxy) { if(serverProxy == null) { throw new Ice.NoEndpointException(); } serverProxy = serverProxy.ice_router(null); // The server proxy cannot be routed. _serverEndpoints = ((Ice.ObjectPrxHelperBase)serverProxy).__reference().getEndpoints(); return _serverEndpoints; } private synchronized void addAndEvictProxies(Ice.ObjectPrx proxy, Ice.ObjectPrx[] evictedProxies) { // // Check if the proxy hasn't already been evicted by a // concurrent addProxies call. If it's the case, don't // add it to our local map. // int index = _evictedIdentities.indexOf(proxy.ice_getIdentity()); if(index >= 0) { _evictedIdentities.remove(index); } else { // // If we successfully added the proxy to the router, // we add it to our local map. // _identities.add(proxy.ice_getIdentity()); } // // We also must remove whatever proxies the router evicted. // for(Ice.ObjectPrx p : evictedProxies) { if(!_identities.remove(p.ice_getIdentity())) { // // It's possible for the proxy to not have been // added yet in the local map if two threads // concurrently call addProxies. // _evictedIdentities.add(p.ice_getIdentity()); } } } private final Ice.RouterPrx _router; private EndpointI[] _clientEndpoints; private EndpointI[] _serverEndpoints; private Ice.ObjectAdapter _adapter; private java.util.Set<Ice.Identity> _identities = new java.util.HashSet<Ice.Identity>(); private java.util.List<Ice.Identity> _evictedIdentities = new java.util.ArrayList<Ice.Identity>(); }