// **********************************************************************
//
// 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 OutgoingConnectionFactory
{
//
// Helper class to to multi hash map.
//
private static class MultiHashMap<K, V> extends java.util.HashMap<K, java.util.List<V>>
{
public void
put(K key, V value)
{
java.util.List<V> list = this.get(key);
if(list == null)
{
list = new java.util.LinkedList<V>();
this.put(key, list);
}
list.add(value);
}
public void
remove(K key, V value)
{
java.util.List<V> list = this.get(key);
assert(list != null);
list.remove(value);
if(list.isEmpty())
{
this.remove(key);
}
}
};
interface CreateConnectionCallback
{
void setConnection(Ice.ConnectionI connection, boolean compress);
void setException(Ice.LocalException ex);
}
public synchronized void
destroy()
{
if(_destroyed)
{
return;
}
for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
{
for(Ice.ConnectionI connection : connectionList)
{
connection.destroy(Ice.ConnectionI.CommunicatorDestroyed);
}
}
_destroyed = true;
notifyAll();
}
public void
waitUntilFinished()
{
java.util.Map<Connector, java.util.List<Ice.ConnectionI> > connections = null;
synchronized(this)
{
//
// First we wait until the factory is destroyed. We also
// wait until there are no pending connections
// anymore. Only then we can be sure the _connections
// contains all connections.
//
while(!_destroyed || !_pending.isEmpty() || _pendingConnectCount > 0)
{
try
{
wait();
}
catch(InterruptedException ex)
{
}
}
//
// We want to wait until all connections are finished outside the
// thread synchronization.
//
connections = new java.util.HashMap<Connector, java.util.List<Ice.ConnectionI> >(_connections);
}
//
// Now we wait until the destruction of each connection is finished.
//
for(java.util.List<Ice.ConnectionI> connectionList : connections.values())
{
for(Ice.ConnectionI connection : connectionList)
{
connection.waitUntilFinished();
}
}
synchronized(this)
{
// Ensure all the connections are finished and reapable at this point.
java.util.List<Ice.ConnectionI> cons = _reaper.swapConnections();
if(cons != null)
{
int size = 0;
for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
{
size += connectionList.size();
}
assert(cons.size() == size);
_connections.clear();
_connectionsByEndpoint.clear();
}
else
{
assert(_connections.isEmpty());
assert(_connectionsByEndpoint.isEmpty());
}
}
}
public Ice.ConnectionI
create(EndpointI[] endpts, boolean hasMore, Ice.EndpointSelectionType selType, Ice.BooleanHolder compress)
{
assert(endpts.length > 0);
//
// Apply the overrides.
//
java.util.List<EndpointI> endpoints = applyOverrides(endpts);
//
// Try to find a connection to one of the given endpoints.
//
Ice.ConnectionI connection = findConnectionByEndpoint(endpoints, compress);
if(connection != null)
{
return connection;
}
Ice.LocalException exception = null;
//
// If we didn't find a connection with the endpoints, we create the connectors
// for the endpoints.
//
java.util.List<ConnectorInfo> connectors = new java.util.ArrayList<ConnectorInfo>();
java.util.Iterator<EndpointI> p = endpoints.iterator();
while(p.hasNext())
{
EndpointI endpoint = p.next();
//
// Create connectors for the endpoint.
//
try
{
java.util.List<Connector> cons = endpoint.connectors();
assert(cons.size() > 0);
//
// Shuffle connectors if endpoint selection type is Random.
//
if(selType == Ice.EndpointSelectionType.Random)
{
java.util.Collections.shuffle(cons);
}
for(Connector c : cons)
{
connectors.add(new ConnectorInfo(c, endpoint));
}
}
catch(Ice.LocalException ex)
{
exception = ex;
handleException(exception, hasMore || p.hasNext());
}
}
if(connectors.isEmpty())
{
assert(exception != null);
throw exception;
}
//
// Try to get a connection to one of the connectors. A null result indicates that no
// connection was found and that we should try to establish the connection (and that
// the connectors were added to _pending to prevent other threads from establishing
// the connection).
//
connection = getConnection(connectors, null, compress);
if(connection != null)
{
return connection;
}
//
// Try to establish the connection to the connectors.
//
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
java.util.Iterator<ConnectorInfo> q = connectors.iterator();
ConnectorInfo ci = null;
while(q.hasNext())
{
ci = q.next();
try
{
connection = createConnection(ci.connector.connect(), ci);
connection.start(null);
if(defaultsAndOverrides.overrideCompress)
{
compress.value = defaultsAndOverrides.overrideCompressValue;
}
else
{
compress.value = ci.endpoint.compress();
}
connection.activate();
break;
}
catch(Ice.CommunicatorDestroyedException ex)
{
exception = ex;
handleConnectionException(exception, hasMore || p.hasNext());
connection = null;
break; // No need to continue
}
catch(Ice.LocalException ex)
{
exception = ex;
handleConnectionException(exception, hasMore || p.hasNext());
connection = null;
}
}
//
// Finish creating the connection (this removes the connectors from the _pending
// list and notifies any waiting threads).
//
if(connection != null)
{
finishGetConnection(connectors, ci, connection, null);
}
else
{
finishGetConnection(connectors, exception, null);
}
if(connection == null)
{
assert(exception != null);
throw exception;
}
return connection;
}
public void
create(EndpointI[] endpts, boolean hasMore, Ice.EndpointSelectionType selType,
CreateConnectionCallback callback)
{
assert(endpts.length > 0);
//
// Apply the overrides.
//
java.util.List<EndpointI> endpoints = applyOverrides(endpts);
//
// Try to find a connection to one of the given endpoints.
//
try
{
Ice.BooleanHolder compress = new Ice.BooleanHolder();
Ice.ConnectionI connection = findConnectionByEndpoint(endpoints, compress);
if(connection != null)
{
callback.setConnection(connection, compress.value);
return;
}
}
catch(Ice.LocalException ex)
{
callback.setException(ex);
return;
}
ConnectCallback cb = new ConnectCallback(this, endpoints, hasMore, callback, selType);
cb.getConnectors();
}
public synchronized void
setRouterInfo(IceInternal.RouterInfo routerInfo)
{
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
assert(routerInfo != null);
//
// Search for connections to the router's client proxy
// endpoints, and update the object adapter for such
// connections, so that callbacks from the router can be
// received over such connections.
//
Ice.ObjectAdapter adapter = routerInfo.getAdapter();
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
for(EndpointI endpoint : routerInfo.getClientEndpoints())
{
//
// Modify endpoints with overrides.
//
if(defaultsAndOverrides.overrideTimeout)
{
endpoint = endpoint.timeout(defaultsAndOverrides.overrideTimeoutValue);
}
//
// The Connection object does not take the compression flag of
// endpoints into account, but instead gets the information
// about whether messages should be compressed or not from
// other sources. In order to allow connection sharing for
// endpoints that differ in the value of the compression flag
// only, we always set the compression flag to false here in
// this connection factory.
//
endpoint = endpoint.compress(false);
for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
{
for(Ice.ConnectionI connection : connectionList)
{
if(connection.endpoint() == endpoint)
{
connection.setAdapter(adapter);
}
}
}
}
}
public synchronized void
removeAdapter(Ice.ObjectAdapter adapter)
{
if(_destroyed)
{
return;
}
for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
{
for(Ice.ConnectionI connection : connectionList)
{
if(connection.getAdapter() == adapter)
{
connection.setAdapter(null);
}
}
}
}
public void
flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
{
java.util.List<Ice.ConnectionI> c = new java.util.LinkedList<Ice.ConnectionI>();
synchronized(this)
{
if(!_destroyed)
{
for(java.util.List<Ice.ConnectionI> connectionList : _connections.values())
{
for(Ice.ConnectionI connection : connectionList)
{
if(connection.isActiveOrHolding())
{
c.add(connection);
}
}
}
}
}
for(Ice.ConnectionI conn : c)
{
try
{
outAsync.flushConnection(conn);
}
catch(Ice.LocalException ex)
{
// Ignore.
}
}
}
//
// Only for use by Instance.
//
OutgoingConnectionFactory(Instance instance)
{
_instance = instance;
_destroyed = false;
}
protected synchronized void
finalize()
throws Throwable
{
IceUtilInternal.Assert.FinalizerAssert(_destroyed);
//IceUtilInternal.Assert.FinalizerAssert(_connections.isEmpty());
//IceUtilInternal.Assert.FinalizerAssert(_connectionsByEndpoint.isEmpty());
IceUtilInternal.Assert.FinalizerAssert(_pendingConnectCount == 0);
IceUtilInternal.Assert.FinalizerAssert(_pending.isEmpty());
super.finalize();
}
private java.util.List<EndpointI>
applyOverrides(EndpointI[] endpts)
{
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
java.util.List<EndpointI> endpoints = new java.util.ArrayList<EndpointI>();
for(EndpointI endpoint : endpts)
{
//
// Modify endpoints with overrides.
//
if(defaultsAndOverrides.overrideTimeout)
{
endpoints.add(endpoint.timeout(defaultsAndOverrides.overrideTimeoutValue));
}
else
{
endpoints.add(endpoint);
}
}
return endpoints;
}
synchronized private Ice.ConnectionI
findConnectionByEndpoint(java.util.List<EndpointI> endpoints, Ice.BooleanHolder compress)
{
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
assert(!endpoints.isEmpty());
for(EndpointI endpoint : endpoints)
{
java.util.List<Ice.ConnectionI> connectionList = _connectionsByEndpoint.get(endpoint);
if(connectionList == null)
{
continue;
}
for(Ice.ConnectionI connection : connectionList)
{
if(connection.isActiveOrHolding()) // Don't return destroyed or un-validated connections
{
if(defaultsAndOverrides.overrideCompress)
{
compress.value = defaultsAndOverrides.overrideCompressValue;
}
else
{
compress.value = endpoint.compress();
}
return connection;
}
}
}
return null;
}
//
// Must be called while synchronized.
//
private Ice.ConnectionI
findConnection(java.util.List<ConnectorInfo> connectors, Ice.BooleanHolder compress)
{
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
for(ConnectorInfo ci : connectors)
{
if(_pending.containsKey(ci.connector))
{
continue;
}
java.util.List<Ice.ConnectionI> connectionList = _connections.get(ci.connector);
if(connectionList == null)
{
continue;
}
for(Ice.ConnectionI connection : connectionList)
{
if(connection.isActiveOrHolding()) // Don't return destroyed or un-validated connections
{
if(defaultsAndOverrides.overrideCompress)
{
compress.value = defaultsAndOverrides.overrideCompressValue;
}
else
{
compress.value = ci.endpoint.compress();
}
return connection;
}
}
}
return null;
}
synchronized private void
incPendingConnectCount()
{
//
// Keep track of the number of pending connects. The outgoing connection factory
// waitUntilFinished() method waits for all the pending connects to terminate before
// to return. This ensures that the communicator client thread pool isn't destroyed
// too soon and will still be available to execute the ice_exception() callbacks for
// the asynchronous requests waiting on a connection to be established.
//
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
++_pendingConnectCount;
}
synchronized private void
decPendingConnectCount()
{
--_pendingConnectCount;
assert(_pendingConnectCount >= 0);
if(_destroyed && _pendingConnectCount == 0)
{
notifyAll();
}
}
private Ice.ConnectionI
getConnection(java.util.List<ConnectorInfo> connectors, ConnectCallback cb, Ice.BooleanHolder compress)
{
synchronized(this)
{
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
//
// Reap closed connections
//
java.util.List<Ice.ConnectionI> cons = _reaper.swapConnections();
if(cons != null)
{
for(Ice.ConnectionI c : cons)
{
_connections.remove(c.connector(), c);
_connectionsByEndpoint.remove(c.endpoint(), c);
_connectionsByEndpoint.remove(c.endpoint().compress(true), c);
}
}
//
// Try to get the connection. We may need to wait for other threads to
// finish if one of them is currently establishing a connection to one
// of our connectors.
//
while(true)
{
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
//
// Search for a matching connection. If we find one, we're done.
//
Ice.ConnectionI connection = findConnection(connectors, compress);
if(connection != null)
{
return connection;
}
if(addToPending(cb, connectors))
{
//
// If a callback is not specified we wait until another thread notifies us about a
// change to the pending list. Otherwise, if a callback is provided we're done:
// when the pending list changes the callback will be notified and will try to
// get the connection again.
//
if(cb == null)
{
try
{
wait();
}
catch(InterruptedException ex)
{
}
}
else
{
return null;
}
}
else
{
//
// If no thread is currently establishing a connection to one of our connectors,
// we get out of this loop and start the connection establishment to one of the
// given connectors.
//
break;
}
}
}
//
// At this point, we're responsible for establishing the connection to one of
// the given connectors. If it's a non-blocking connect, calling nextConnector
// will start the connection establishment. Otherwise, we return null to get
// the caller to establish the connection.
//
if(cb != null)
{
cb.nextConnector();
}
return null;
}
private synchronized Ice.ConnectionI
createConnection(Transceiver transceiver, ConnectorInfo ci)
{
assert(_pending.containsKey(ci.connector) && transceiver != null);
//
// Create and add the connection to the connection map. Adding the connection to the map
// is necessary to support the interruption of the connection initialization and validation
// in case the communicator is destroyed.
//
Ice.ConnectionI connection = null;
try
{
if(_destroyed)
{
throw new Ice.CommunicatorDestroyedException();
}
connection = new Ice.ConnectionI(_instance, _reaper, transceiver, ci.connector,
ci.endpoint.compress(false), null);
}
catch(Ice.LocalException ex)
{
try
{
transceiver.close();
}
catch(Ice.LocalException exc)
{
// Ignore
}
throw ex;
}
_connections.put(ci.connector, connection);
_connectionsByEndpoint.put(connection.endpoint(), connection);
_connectionsByEndpoint.put(connection.endpoint().compress(true), connection);
return connection;
}
private void
finishGetConnection(java.util.List<ConnectorInfo> connectors,
ConnectorInfo ci,
Ice.ConnectionI connection,
ConnectCallback cb)
{
java.util.Set<ConnectCallback> connectionCallbacks = new java.util.HashSet<ConnectCallback>();
if(cb != null)
{
connectionCallbacks.add(cb);
}
java.util.Set<ConnectCallback> callbacks = new java.util.HashSet<ConnectCallback>();
synchronized(this)
{
for(ConnectorInfo c : connectors)
{
java.util.Set<ConnectCallback> cbs = _pending.remove(c.connector);
if(cbs != null)
{
for(ConnectCallback cc : cbs)
{
if(cc.hasConnector(ci))
{
connectionCallbacks.add(cc);
}
else
{
callbacks.add(cc);
}
}
}
}
for(ConnectCallback cc : connectionCallbacks)
{
cc.removeFromPending();
callbacks.remove(cc);
}
for(ConnectCallback cc : callbacks)
{
cc.removeFromPending();
}
notifyAll();
}
boolean compress;
DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
if(defaultsAndOverrides.overrideCompress)
{
compress = defaultsAndOverrides.overrideCompressValue;
}
else
{
compress = ci.endpoint.compress();
}
for(ConnectCallback cc : callbacks)
{
cc.getConnection();
}
for(ConnectCallback cc : connectionCallbacks)
{
cc.setConnection(connection, compress);
}
}
private void
finishGetConnection(java.util.List<ConnectorInfo> connectors, Ice.LocalException ex, ConnectCallback cb)
{
java.util.Set<ConnectCallback> failedCallbacks = new java.util.HashSet<ConnectCallback>();
if(cb != null)
{
failedCallbacks.add(cb);
}
java.util.Set<ConnectCallback> callbacks = new java.util.HashSet<ConnectCallback>();
synchronized(this)
{
for(ConnectorInfo c : connectors)
{
java.util.Set<ConnectCallback> cbs = _pending.remove(c.connector);
if(cbs != null)
{
for(ConnectCallback cc : cbs)
{
if(cc.removeConnectors(connectors))
{
failedCallbacks.add(cc);
}
else
{
callbacks.add(cc);
}
}
}
}
for(ConnectCallback cc : callbacks)
{
assert(!failedCallbacks.contains(cc));
cc.removeFromPending();
}
notifyAll();
}
for(ConnectCallback cc : callbacks)
{
cc.getConnection();
}
for(ConnectCallback cc : failedCallbacks)
{
cc.setException(ex);
}
}
private boolean
addToPending(ConnectCallback cb, java.util.List<ConnectorInfo> connectors)
{
//
// Add the callback to each connector pending list.
//
boolean found = false;
for(ConnectorInfo p : connectors)
{
java.util.Set<ConnectCallback> cbs = _pending.get(p.connector);
if(cbs != null)
{
found = true;
if(cb != null)
{
cbs.add(cb); // Add the callback to each pending connector.
}
}
}
if(found)
{
return true;
}
//
// If there's no pending connection for the given connectors, we're
// responsible for its establishment. We add empty pending lists,
// other callbacks to the same connectors will be queued.
//
for(ConnectorInfo p : connectors)
{
if(!_pending.containsKey(p.connector))
{
_pending.put(p.connector, new java.util.HashSet<ConnectCallback>());
}
}
return false;
}
private void
removeFromPending(ConnectCallback cb, java.util.List<ConnectorInfo> connectors)
{
for(ConnectorInfo p : connectors)
{
java.util.Set<ConnectCallback> cbs = _pending.get(p.connector);
if(cbs != null)
{
cbs.remove(cb);
}
}
}
private void
handleConnectionException(Ice.LocalException ex, boolean hasMore)
{
TraceLevels traceLevels = _instance.traceLevels();
if(traceLevels.retry >= 2)
{
StringBuilder s = new StringBuilder(128);
s.append("connection to endpoint failed");
if(ex instanceof Ice.CommunicatorDestroyedException)
{
s.append("\n");
}
else
{
if(hasMore)
{
s.append(", trying next endpoint\n");
}
else
{
s.append(" and no more endpoints to try\n");
}
}
s.append(ex.toString());
_instance.initializationData().logger.trace(traceLevels.retryCat, s.toString());
}
}
private void
handleException(Ice.LocalException ex, boolean hasMore)
{
TraceLevels traceLevels = _instance.traceLevels();
if(traceLevels.retry >= 2)
{
StringBuilder s = new StringBuilder(128);
s.append("couldn't resolve endpoint host");
if(ex instanceof Ice.CommunicatorDestroyedException)
{
s.append("\n");
}
else
{
if(hasMore)
{
s.append(", trying next endpoint\n");
}
else
{
s.append(" and no more endpoints to try\n");
}
}
s.append(ex.toString());
_instance.initializationData().logger.trace(traceLevels.retryCat, s.toString());
}
}
private static class ConnectorInfo
{
public ConnectorInfo(Connector c, EndpointI e)
{
connector = c;
endpoint = e;
}
public boolean
equals(Object obj)
{
ConnectorInfo r = (ConnectorInfo)obj;
return connector.equals(r.connector);
}
public int
hashCode()
{
return connector.hashCode();
}
public Connector connector;
public EndpointI endpoint;
}
private static class ConnectCallback implements Ice.ConnectionI.StartCallback, EndpointI_connectors
{
ConnectCallback(OutgoingConnectionFactory f, java.util.List<EndpointI> endpoints, boolean more,
CreateConnectionCallback cb, Ice.EndpointSelectionType selType)
{
_factory = f;
_endpoints = endpoints;
_hasMore = more;
_callback = cb;
_selType = selType;
_endpointsIter = _endpoints.iterator();
}
//
// Methods from ConnectionI.StartCallback
//
public void
connectionStartCompleted(Ice.ConnectionI connection)
{
connection.activate();
_factory.finishGetConnection(_connectors, _current, connection, this);
}
public void
connectionStartFailed(Ice.ConnectionI connection, Ice.LocalException ex)
{
assert(_current != null);
_factory.handleConnectionException(ex, _hasMore || _iter.hasNext());
if(ex instanceof Ice.CommunicatorDestroyedException) // No need to continue.
{
_factory.finishGetConnection(_connectors, ex, this);
}
else if(_iter.hasNext()) // Try the next connector.
{
nextConnector();
}
else
{
_factory.finishGetConnection(_connectors, ex, this);
}
}
//
// Methods from EndpointI_connectors
//
public void
connectors(java.util.List<Connector> cons)
{
//
// Shuffle connectors if endpoint selection type is Random.
//
if(_selType == Ice.EndpointSelectionType.Random)
{
java.util.Collections.shuffle(cons);
}
for(Connector p : cons)
{
_connectors.add(new ConnectorInfo(p, _currentEndpoint));
}
if(_endpointsIter.hasNext())
{
nextEndpoint();
}
else
{
assert(!_connectors.isEmpty());
//
// We now have all the connectors for the given endpoints. We can try to obtain the
// connection.
//
_iter = _connectors.iterator();
getConnection();
}
}
public void
exception(Ice.LocalException ex)
{
_factory.handleException(ex, _hasMore || _endpointsIter.hasNext());
if(_endpointsIter.hasNext())
{
nextEndpoint();
}
else if(!_connectors.isEmpty())
{
//
// We now have all the connectors for the given endpoints. We can try to obtain the
// connection.
//
_iter = _connectors.iterator();
getConnection();
}
else
{
_callback.setException(ex);
_factory.decPendingConnectCount(); // Must be called last.
}
}
public void
setConnection(Ice.ConnectionI connection, boolean compress)
{
//
// Callback from the factory: the connection to one of the callback
// connectors has been established.
//
_callback.setConnection(connection, compress);
_factory.decPendingConnectCount(); // Must be called last.
}
public void
setException(Ice.LocalException ex)
{
//
// Callback from the factory: connection establishment failed.
//
_callback.setException(ex);
_factory.decPendingConnectCount(); // Must be called last.
}
public boolean
hasConnector(ConnectorInfo ci)
{
return _connectors.contains(ci);
}
public boolean
removeConnectors(java.util.List<ConnectorInfo> connectors)
{
_connectors.removeAll(connectors);
_iter = _connectors.iterator();
return _connectors.isEmpty();
}
public void
removeFromPending()
{
_factory.removeFromPending(this, _connectors);
}
void
getConnectors()
{
try
{
//
// Notify the factory that there's an async connect pending. This is necessary
// to prevent the outgoing connection factory to be destroyed before all the
// pending asynchronous connects are finished.
//
_factory.incPendingConnectCount();
}
catch(Ice.LocalException ex)
{
_callback.setException(ex);
return;
}
nextEndpoint();
}
void
nextEndpoint()
{
try
{
assert(_endpointsIter.hasNext());
_currentEndpoint = _endpointsIter.next();
_currentEndpoint.connectors_async(this);
}
catch(Ice.LocalException ex)
{
exception(ex);
}
}
void
getConnection()
{
try
{
//
// If all the connectors have been created, we ask the factory to get a
// connection.
//
Ice.BooleanHolder compress = new Ice.BooleanHolder();
Ice.ConnectionI connection = _factory.getConnection(_connectors, this, compress);
if(connection == null)
{
//
// A null return value from getConnection indicates that the connection
// is being established and that everthing has been done to ensure that
// the callback will be notified when the connection establishment is
// done.
//
return;
}
_callback.setConnection(connection, compress.value);
_factory.decPendingConnectCount(); // Must be called last.
}
catch(Ice.LocalException ex)
{
_callback.setException(ex);
_factory.decPendingConnectCount(); // Must be called last.
}
}
void
nextConnector()
{
Ice.ConnectionI connection = null;
try
{
assert(_iter.hasNext());
_current = _iter.next();
connection = _factory.createConnection(_current.connector.connect(), _current);
connection.start(this);
}
catch(Ice.LocalException ex)
{
connectionStartFailed(connection, ex);
}
}
private final OutgoingConnectionFactory _factory;
private final boolean _hasMore;
private final CreateConnectionCallback _callback;
private final java.util.List<EndpointI> _endpoints;
private final Ice.EndpointSelectionType _selType;
private java.util.Iterator<EndpointI> _endpointsIter;
private EndpointI _currentEndpoint;
private java.util.List<ConnectorInfo> _connectors = new java.util.ArrayList<ConnectorInfo>();
private java.util.Iterator<ConnectorInfo> _iter;
private ConnectorInfo _current;
}
private final Instance _instance;
private final ConnectionReaper _reaper = new ConnectionReaper();
private boolean _destroyed;
private MultiHashMap<Connector, Ice.ConnectionI> _connections = new MultiHashMap<Connector, Ice.ConnectionI>();
private MultiHashMap<EndpointI, Ice.ConnectionI> _connectionsByEndpoint =
new MultiHashMap<EndpointI, Ice.ConnectionI>();
private java.util.Map<Connector, java.util.HashSet<ConnectCallback> > _pending =
new java.util.HashMap<Connector, java.util.HashSet<ConnectCallback> >();
private int _pendingConnectCount = 0;
}