summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2009-03-12 10:26:37 +0100
committerBenoit Foucher <benoit@zeroc.com>2009-03-12 10:26:37 +0100
commit2f8ff1f01af2416dce3cda6c6093374d95fc453d (patch)
tree9392f8267b919d2a8974eb275515e0212f74deed /cpp
parentMerge branch 'R3_3_branch' of ssh://cvs.zeroc.com/home/git/ice into R3_3_branch (diff)
downloadice-2f8ff1f01af2416dce3cda6c6093374d95fc453d.tar.bz2
ice-2f8ff1f01af2416dce3cda6c6093374d95fc453d.tar.xz
ice-2f8ff1f01af2416dce3cda6c6093374d95fc453d.zip
- Fixed potential assert when establishing connection for proxies with
different endpoint combinations - Added test for connection establishment using proxies with different endpoint combination. - Improved connection establishment to better handle failures when many AMI requests (invoked on different proxies) are queued. The failure is now reported to all pending requests.
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp356
-rw-r--r--cpp/src/Ice/ConnectionFactory.h18
-rw-r--r--cpp/src/Ice/Reference.cpp94
-rw-r--r--cpp/test/Ice/background/AllTests.cpp46
-rw-r--r--cpp/test/Ice/binding/AllTests.cpp105
-rwxr-xr-xcpp/test/Ice/gc/run.py5
6 files changed, 461 insertions, 163 deletions
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index a275f61e292..107887e6501 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -55,6 +55,12 @@ IceInternal::OutgoingConnectionFactory::ConnectorInfo::operator<(const Connector
return connector < other.connector;
}
+bool
+IceInternal::OutgoingConnectionFactory::ConnectorInfo::operator==(const ConnectorInfo& other) const
+{
+ return connector == other.connector;
+}
+
void
IceInternal::OutgoingConnectionFactory::destroy()
{
@@ -193,7 +199,8 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
// Try to establish the connection to the connectors.
//
DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
- for(vector<ConnectorInfo>::const_iterator q = connectors.begin(); q != connectors.end(); ++q)
+ vector<ConnectorInfo>::const_iterator q;
+ for(q = connectors.begin(); q != connectors.end(); ++q)
{
try
{
@@ -209,6 +216,7 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
compress = q->endpoint->compress();
}
+ connection->activate();
break;
}
catch(const Ice::CommunicatorDestroyedException& ex)
@@ -230,7 +238,14 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
// Finish creating the connection (this removes the connectors from the _pending
// list and notifies any waiting threads).
//
- finishGetConnection(connectors, 0, connection);
+ if(connection)
+ {
+ finishGetConnection(connectors, *q, connection, 0);
+ }
+ else
+ {
+ finishGetConnection(connectors, *exception.get(), 0);
+ }
if(!connection)
{
@@ -425,7 +440,7 @@ IceInternal::OutgoingConnectionFactory::findConnection(const vector<EndpointIPtr
for(vector<EndpointIPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p)
{
pair<multimap<EndpointIPtr, ConnectionIPtr>::iterator,
- multimap<EndpointIPtr, ConnectionIPtr>::iterator> pr = _connectionsByEndpoint.equal_range(*p);
+ multimap<EndpointIPtr, ConnectionIPtr>::iterator> pr = _connectionsByEndpoint.equal_range(*p);
for(multimap<EndpointIPtr, ConnectionIPtr>::iterator q = pr.first; q != pr.second; ++q)
{
@@ -454,8 +469,13 @@ IceInternal::OutgoingConnectionFactory::findConnection(const vector<ConnectorInf
DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
{
+ if(_pending.find(*p) != _pending.end())
+ {
+ continue;
+ }
+
pair<multimap<ConnectorInfo, ConnectionIPtr>::iterator,
- multimap<ConnectorInfo, ConnectionIPtr>::iterator> pr = _connections.equal_range(*p);
+ multimap<ConnectorInfo, ConnectionIPtr>::iterator> pr = _connections.equal_range(*p);
if(pr.first == pr.second)
{
@@ -520,7 +540,8 @@ IceInternal::OutgoingConnectionFactory::decPendingConnectCount()
ConnectionIPtr
IceInternal::OutgoingConnectionFactory::getConnection(const vector<ConnectorInfo>& connectors,
- const ConnectCallbackPtr& cb, bool& compress)
+ const ConnectCallbackPtr& cb,
+ bool& compress)
{
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
@@ -563,62 +584,27 @@ IceInternal::OutgoingConnectionFactory::getConnection(const vector<ConnectorInfo
// finish if one of them is currently establishing a connection to one
// of our connectors.
//
- while(!_destroyed)
+ while(true)
{
+ if(_destroyed)
+ {
+ throw Ice::CommunicatorDestroyedException(__FILE__, __LINE__);
+ }
+
//
// Search for a matching connection. If we find one, we're done.
//
Ice::ConnectionIPtr connection = findConnection(connectors, compress);
if(connection)
{
- if(cb)
- {
- //
- // This might not be the first getConnection call for the callback. We need
- // to ensure that the callback isn't registered with any other pending
- // connectors since we just found a connection and therefore don't need to
- // wait anymore for other pending connectors.
- //
- for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
- {
- map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
- if(q != _pending.end())
- {
- q->second.erase(cb);
- }
- }
- }
return connection;
}
//
- // Determine whether another thread is currently attempting to connect to one of our endpoints;
- // if so we wait until it's done.
+ // Determine whether another thread/request is currently attempting to connect to
+ // one of our endpoints; if so we wait until it's done.
//
- bool found = false;
- for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
- {
- map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
- if(q != _pending.end())
- {
- found = true;
- if(cb)
- {
- q->second.insert(cb); // Add the callback to each pending connector.
- }
- }
- }
-
- if(!found)
- {
- //
- // 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;
- }
- else
+ if(addToPending(cb, connectors))
{
//
// If a callback is not specified we wait until another thread notifies us about a
@@ -635,23 +621,14 @@ IceInternal::OutgoingConnectionFactory::getConnection(const vector<ConnectorInfo
return 0;
}
}
- }
-
- if(_destroyed)
- {
- throw Ice::CommunicatorDestroyedException(__FILE__, __LINE__);
- }
-
- //
- // No connection to any of our endpoints exists yet; we add the given connectors to
- // the _pending set to indicate that we're attempting connection establishment to
- // these connectors. We might attempt to connect to the same connector multiple times.
- //
- for(vector<ConnectorInfo>::const_iterator r = connectors.begin(); r != connectors.end(); ++r)
- {
- if(_pending.find(*r) == _pending.end())
+ else
{
- _pending.insert(pair<ConnectorInfo, set<ConnectCallbackPtr> >(*r, set<ConnectCallbackPtr>()));
+ //
+ // 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;
}
}
}
@@ -709,47 +686,179 @@ IceInternal::OutgoingConnectionFactory::createConnection(const TransceiverPtr& t
void
IceInternal::OutgoingConnectionFactory::finishGetConnection(const vector<ConnectorInfo>& connectors,
- const ConnectCallbackPtr& cb,
- const ConnectionIPtr& connection)
+ const ConnectorInfo& ci,
+ const ConnectionIPtr& connection,
+ const ConnectCallbackPtr& cb)
{
+ set<ConnectCallbackPtr> connectionCallbacks;
+ if(cb)
+ {
+ connectionCallbacks.insert(cb);
+ }
+
set<ConnectCallbackPtr> callbacks;
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
+ {
+ map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
+ if(q != _pending.end())
+ {
+ for(set<ConnectCallbackPtr>::const_iterator r = q->second.begin(); r != q->second.end(); ++r)
+ {
+ if((*r)->hasConnector(ci))
+ {
+ connectionCallbacks.insert(*r);
+ }
+ else
+ {
+ callbacks.insert(*r);
+ }
+ }
+ _pending.erase(q);
+ }
+ }
+
+ set<ConnectCallbackPtr>::iterator r;
+ for(r = connectionCallbacks.begin(); r != connectionCallbacks.end(); ++r)
+ {
+ (*r)->removeFromPending();
+ callbacks.erase(*r);
+ }
+ for(r = callbacks.begin(); r != callbacks.end(); ++r)
+ {
+ (*r)->removeFromPending();
+ }
+ notifyAll();
+ }
+ bool compress;
+ DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
+ if(defaultsAndOverrides->overrideCompress)
+ {
+ compress = defaultsAndOverrides->overrideCompressValue;
+ }
+ else
+ {
+ compress = ci.endpoint->compress();
+ }
+
+ set<ConnectCallbackPtr>::const_iterator p;
+ for(p = callbacks.begin(); p != callbacks.end(); ++p)
+ {
+ (*p)->getConnection();
+ }
+ for(p = connectionCallbacks.begin(); p != connectionCallbacks.end(); ++p)
+ {
+ (*p)->setConnection(connection, compress);
+ }
+}
+
+void
+IceInternal::OutgoingConnectionFactory::finishGetConnection(const vector<ConnectorInfo>& connectors,
+ const Ice::LocalException& ex,
+ const ConnectCallbackPtr& cb)
+{
+ set<ConnectCallbackPtr> failedCallbacks;
+ if(cb)
+ {
+ failedCallbacks.insert(cb);
+ }
+
+ set<ConnectCallbackPtr> callbacks;
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
-
- //
- // We're done trying to connect to the given connectors so we remove the
- // connectors from the pending list and notify waiting threads. We also
- // notify the pending connect callbacks (outside the synchronization).
- //
-
for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
{
map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
if(q != _pending.end())
{
- callbacks.insert(q->second.begin(), q->second.end());
+ for(set<ConnectCallbackPtr>::const_iterator r = q->second.begin(); r != q->second.end(); ++r)
+ {
+ if((*r)->removeConnectors(connectors))
+ {
+ failedCallbacks.insert(*r);
+ }
+ else
+ {
+ callbacks.insert(*r);
+ }
+ }
_pending.erase(q);
}
}
+
+ for(set<ConnectCallbackPtr>::iterator r = callbacks.begin(); r != callbacks.end(); ++r)
+ {
+ assert(failedCallbacks.find(*r) == failedCallbacks.end());
+ (*r)->removeFromPending();
+ }
notifyAll();
+ }
+
+ set<ConnectCallbackPtr>::const_iterator p;
+ for(p = callbacks.begin(); p != callbacks.end(); ++p)
+ {
+ (*p)->getConnection();
+ }
+ for(p = failedCallbacks.begin(); p != failedCallbacks.end(); ++p)
+ {
+ (*p)->setException(ex);
+ }
+}
- //
- // If the connect attempt succeeded and the communicator is not destroyed,
- // activate the connection!
- //
- if(connection && !_destroyed)
+bool
+IceInternal::OutgoingConnectionFactory::addToPending(const ConnectCallbackPtr& cb,
+ const vector<ConnectorInfo>& connectors)
+{
+ //
+ // Add the callback to each connector pending list.
+ //
+ bool found = false;
+ for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
+ {
+ map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
+ if(q != _pending.end())
{
- connection->activate();
+ found = true;
+ if(cb)
+ {
+ q->second.insert(cb);
+ }
}
}
+ if(found)
+ {
+ return true;
+ }
+
//
- // Notify any waiting callbacks.
+ // 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(set<ConnectCallbackPtr>::const_iterator p = callbacks.begin(); p != callbacks.end(); ++p)
+ for(vector<ConnectorInfo>::const_iterator r = connectors.begin(); r != connectors.end(); ++r)
{
- (*p)->getConnection();
+ if(_pending.find(*r) == _pending.end())
+ {
+ _pending.insert(pair<ConnectorInfo, set<ConnectCallbackPtr> >(*r, set<ConnectCallbackPtr>()));
+ }
+ }
+ return false;
+}
+
+void
+IceInternal::OutgoingConnectionFactory::removeFromPending(const ConnectCallbackPtr& cb,
+ const vector<ConnectorInfo>& connectors)
+{
+ for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
+ {
+ map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p);
+ if(q != _pending.end())
+ {
+ q->second.erase(cb);
+ }
}
}
@@ -790,7 +899,7 @@ IceInternal::OutgoingConnectionFactory::handleException(const LocalException& ex
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
pair<multimap<ConnectorInfo, ConnectionIPtr>::iterator,
- multimap<ConnectorInfo, ConnectionIPtr>::iterator> pr = _connections.equal_range(ci);
+ multimap<ConnectorInfo, ConnectionIPtr>::iterator> pr = _connections.equal_range(ci);
for(multimap<ConnectorInfo, ConnectionIPtr>::iterator p = pr.first; p != pr.second; ++p)
{
@@ -802,7 +911,7 @@ IceInternal::OutgoingConnectionFactory::handleException(const LocalException& ex
}
pair<multimap<EndpointIPtr, ConnectionIPtr>::iterator,
- multimap<EndpointIPtr, ConnectionIPtr>::iterator> qr = _connectionsByEndpoint.equal_range(ci.endpoint);
+ multimap<EndpointIPtr, ConnectionIPtr>::iterator> qr = _connectionsByEndpoint.equal_range(ci.endpoint);
for(multimap<EndpointIPtr, ConnectionIPtr>::iterator q = qr.first; q != qr.second; ++q)
{
@@ -864,20 +973,8 @@ IceInternal::OutgoingConnectionFactory::ConnectCallback::ConnectCallback(const O
void
IceInternal::OutgoingConnectionFactory::ConnectCallback::connectionStartCompleted(const ConnectionIPtr& connection)
{
- bool compress;
- DefaultsAndOverridesPtr defaultsAndOverrides = _factory->_instance->defaultsAndOverrides();
- if(defaultsAndOverrides->overrideCompress)
- {
- compress = defaultsAndOverrides->overrideCompressValue;
- }
- else
- {
- compress = _iter->endpoint->compress();
- }
-
- _factory->finishGetConnection(_connectors, this, connection);
- _callback->setConnection(connection, compress);
- _factory->decPendingConnectCount(); // Must be called last.
+ connection->activate();
+ _factory->finishGetConnection(_connectors, *_iter, connection, this);
}
void
@@ -889,9 +986,7 @@ IceInternal::OutgoingConnectionFactory::ConnectCallback::connectionStartFailed(c
_factory->handleException(ex, *_iter, connection, _hasMore || _iter != _connectors.end() - 1);
if(dynamic_cast<const Ice::CommunicatorDestroyedException*>(&ex)) // No need to continue.
{
- _factory->finishGetConnection(_connectors, this, 0);
- _callback->setException(ex);
- _factory->decPendingConnectCount(); // Must be called last.
+ _factory->finishGetConnection(_connectors, ex, this);
}
else if(++_iter != _connectors.end()) // Try the next connector.
{
@@ -899,9 +994,7 @@ IceInternal::OutgoingConnectionFactory::ConnectCallback::connectionStartFailed(c
}
else
{
- _factory->finishGetConnection(_connectors, this, 0);
- _callback->setException(ex);
- _factory->decPendingConnectCount(); // Must be called last.
+ _factory->finishGetConnection(_connectors, ex, this);
}
}
@@ -1016,7 +1109,7 @@ IceInternal::OutgoingConnectionFactory::ConnectCallback::getConnection()
// 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.
+ // done or that the callback already obtain the connection.
//
return;
}
@@ -1050,6 +1143,55 @@ IceInternal::OutgoingConnectionFactory::ConnectCallback::nextConnector()
}
}
+void
+IceInternal::OutgoingConnectionFactory::ConnectCallback::setConnection(const Ice::ConnectionIPtr& connection,
+ bool 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.
+}
+
+void
+IceInternal::OutgoingConnectionFactory::ConnectCallback::setException(const Ice::LocalException& ex)
+{
+ //
+ // Callback from the factory: connection establishment failed.
+ //
+ _callback->setException(ex);
+ _factory->decPendingConnectCount(); // Must be called last.
+}
+
+bool
+IceInternal::OutgoingConnectionFactory::ConnectCallback::hasConnector(const ConnectorInfo& ci)
+{
+ return find(_connectors.begin(), _connectors.end(), ci) != _connectors.end();
+}
+
+bool
+IceInternal::OutgoingConnectionFactory::ConnectCallback::removeConnectors(const vector<ConnectorInfo>& connectors)
+{
+ //
+ // Callback from the factory: connecting to the given connectors
+ // failed, we remove the connectors and return true if there's
+ // no more connectors left to try.
+ //
+ for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p)
+ {
+ _connectors.erase(remove(_connectors.begin(), _connectors.end(), *p), _connectors.end());
+ }
+ return _connectors.empty();
+}
+
+void
+IceInternal::OutgoingConnectionFactory::ConnectCallback::removeFromPending()
+{
+ _factory->removeFromPending(this, _connectors);
+}
+
bool
IceInternal::OutgoingConnectionFactory::ConnectCallback::operator<(const ConnectCallback& rhs) const
{
diff --git a/cpp/src/Ice/ConnectionFactory.h b/cpp/src/Ice/ConnectionFactory.h
index 7bd97ab70e1..89ef6bc514b 100644
--- a/cpp/src/Ice/ConnectionFactory.h
+++ b/cpp/src/Ice/ConnectionFactory.h
@@ -75,6 +75,7 @@ private:
}
bool operator<(const ConnectorInfo& other) const;
+ bool operator==(const ConnectorInfo& other) const;
ConnectorPtr connector;
EndpointIPtr endpoint;
@@ -99,8 +100,15 @@ private:
void getConnection();
void nextConnector();
+ void setConnection(const Ice::ConnectionIPtr&, bool);
+ void setException(const Ice::LocalException&);
+
+ bool hasConnector(const ConnectorInfo&);
+ bool removeConnectors(const std::vector<ConnectorInfo>&);
+ void removeFromPending();
+
bool operator<(const ConnectCallback&) const;
-
+
private:
const OutgoingConnectionFactoryPtr _factory;
@@ -120,7 +128,13 @@ private:
void incPendingConnectCount();
void decPendingConnectCount();
Ice::ConnectionIPtr getConnection(const std::vector<ConnectorInfo>&, const ConnectCallbackPtr&, bool&);
- void finishGetConnection(const std::vector<ConnectorInfo>&, const ConnectCallbackPtr&, const Ice::ConnectionIPtr&);
+ void finishGetConnection(const std::vector<ConnectorInfo>&, const ConnectorInfo&, const Ice::ConnectionIPtr&,
+ const ConnectCallbackPtr&);
+ void finishGetConnection(const std::vector<ConnectorInfo>&, const Ice::LocalException&, const ConnectCallbackPtr&);
+
+ bool addToPending(const ConnectCallbackPtr&, const std::vector<ConnectorInfo>&);
+ void removeFromPending(const ConnectCallbackPtr&, const std::vector<ConnectorInfo>&);
+
Ice::ConnectionIPtr findConnection(const std::vector<ConnectorInfo>&, bool&);
Ice::ConnectionIPtr createConnection(const TransceiverPtr&, const ConnectorInfo&);
diff --git a/cpp/src/Ice/Reference.cpp b/cpp/src/Ice/Reference.cpp
index d3cc01479d6..29c177567c0 100644
--- a/cpp/src/Ice/Reference.cpp
+++ b/cpp/src/Ice/Reference.cpp
@@ -1678,29 +1678,29 @@ IceInternal::RoutableReference::createConnection(const vector<EndpointIPtr>& all
virtual void
setConnection(const Ice::ConnectionIPtr& connection, bool compress)
+ {
+ //
+ // If we have a router, set the object adapter for this router
+ // (if any) to the new connection, so that callbacks from the
+ // router can be received over this new connection.
+ //
+ if(_routerInfo && _routerInfo->getAdapter())
{
- //
- // If we have a router, set the object adapter for this router
- // (if any) to the new connection, so that callbacks from the
- // router can be received over this new connection.
- //
- if(_routerInfo && _routerInfo->getAdapter())
- {
- connection->setAdapter(_routerInfo->getAdapter());
- }
- _callback->setConnection(connection, compress);
+ connection->setAdapter(_routerInfo->getAdapter());
}
+ _callback->setConnection(connection, compress);
+ }
virtual void
setException(const Ice::LocalException& ex)
- {
- _callback->setException(ex);
- }
-
+ {
+ _callback->setException(ex);
+ }
+
CB1(const RouterInfoPtr& routerInfo, const GetConnectionCallbackPtr& callback) :
- _routerInfo(routerInfo), _callback(callback)
- {
- }
+ _routerInfo(routerInfo), _callback(callback)
+ {
+ }
private:
@@ -1723,49 +1723,49 @@ IceInternal::RoutableReference::createConnection(const vector<EndpointIPtr>& all
virtual void
setConnection(const Ice::ConnectionIPtr& connection, bool compress)
+ {
+ //
+ // If we have a router, set the object adapter for this router
+ // (if any) to the new connection, so that callbacks from the
+ // router can be received over this new connection.
+ //
+ if(_reference->getRouterInfo() && _reference->getRouterInfo()->getAdapter())
{
- //
- // If we have a router, set the object adapter for this router
- // (if any) to the new connection, so that callbacks from the
- // router can be received over this new connection.
- //
- if(_reference->getRouterInfo() && _reference->getRouterInfo()->getAdapter())
- {
- connection->setAdapter(_reference->getRouterInfo()->getAdapter());
- }
- _callback->setConnection(connection, compress);
+ connection->setAdapter(_reference->getRouterInfo()->getAdapter());
}
+ _callback->setConnection(connection, compress);
+ }
virtual void
setException(const Ice::LocalException& ex)
+ {
+ if(!_exception.get())
{
- if(!_exception.get())
- {
- _exception.reset(dynamic_cast<Ice::LocalException*>(ex.ice_clone()));
- }
-
- if(++_i == _endpoints.size())
- {
- _callback->setException(*_exception.get());
- return;
- }
-
- const bool more = _i != _endpoints.size() - 1;
- vector<EndpointIPtr> endpoint;
- endpoint.push_back(_endpoints[_i]);
-
- OutgoingConnectionFactoryPtr factory = _reference->getInstance()->outgoingConnectionFactory();
- factory->create(endpoint, more, _reference->getEndpointSelection(), this);
+ _exception.reset(dynamic_cast<Ice::LocalException*>(ex.ice_clone()));
}
-
+
+ if(++_i == _endpoints.size())
+ {
+ _callback->setException(*_exception.get());
+ return;
+ }
+
+ const bool more = _i != _endpoints.size() - 1;
+ vector<EndpointIPtr> endpoint;
+ endpoint.push_back(_endpoints[_i]);
+
+ OutgoingConnectionFactoryPtr factory = _reference->getInstance()->outgoingConnectionFactory();
+ factory->create(endpoint, more, _reference->getEndpointSelection(), this);
+ }
+
CB2(const RoutableReferencePtr& reference, const vector<EndpointIPtr>& endpoints,
const GetConnectionCallbackPtr& callback) :
_reference(reference),
_endpoints(endpoints),
_callback(callback),
_i(0)
- {
- }
+ {
+ }
private:
diff --git a/cpp/test/Ice/background/AllTests.cpp b/cpp/test/Ice/background/AllTests.cpp
index 5da5b39ee7b..1aa19dbefa8 100644
--- a/cpp/test/Ice/background/AllTests.cpp
+++ b/cpp/test/Ice/background/AllTests.cpp
@@ -701,6 +701,11 @@ validationTests(const ConfigurationPtr& configuration,
{
configuration->readException(0);
}
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
OpExAMICallbackPtr cbEx = new OpExAMICallback();
@@ -743,6 +748,11 @@ validationTests(const ConfigurationPtr& configuration,
configuration->readException(0);
configuration->readReady(true);
}
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
configuration->readReady(false);
configuration->readException(new Ice::SocketException(__FILE__, __LINE__));
@@ -781,6 +791,11 @@ validationTests(const ConfigurationPtr& configuration,
{
ctl->writeException(false);
}
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
try
{
@@ -809,7 +824,11 @@ validationTests(const ConfigurationPtr& configuration,
ctl->writeException(false);
ctl->writeReady(true);
}
-
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
Ice::ByteSeq seq;
seq.resize(512 * 1024);
@@ -833,7 +852,15 @@ validationTests(const ConfigurationPtr& configuration,
backgroundBatchOneway->op();
backgroundBatchOneway->op();
ctl->resumeAdapter();
- backgroundBatchOneway->ice_flushBatchRequests();
+ try
+ {
+ backgroundBatchOneway->ice_flushBatchRequests();
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
//
// Send bigger requests to test with auto-flushing.
@@ -853,7 +880,15 @@ validationTests(const ConfigurationPtr& configuration,
backgroundBatchOneway->opWithPayload(seq);
backgroundBatchOneway->opWithPayload(seq);
ctl->resumeAdapter();
- backgroundBatchOneway->ice_flushBatchRequests();
+ try
+ {
+ backgroundBatchOneway->ice_flushBatchRequests();
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ cerr << ex << endl;
+ test(false);
+ }
//
// Then try the same thing with async flush.
@@ -874,7 +909,8 @@ validationTests(const ConfigurationPtr& configuration,
backgroundBatchOneway->op();
backgroundBatchOneway->op();
ctl->resumeAdapter();
- backgroundBatchOneway->ice_flushBatchRequests_async(new FlushBatchRequestsCallback());
+ FlushBatchRequestsCallbackPtr fcb = new FlushBatchRequestsCallback();
+ backgroundBatchOneway->ice_flushBatchRequests_async(fcb);
backgroundBatchOneway->ice_getConnection()->close(false);
backgroundBatchOneway->ice_getConnection()->close(false);
@@ -892,7 +928,7 @@ validationTests(const ConfigurationPtr& configuration,
backgroundBatchOneway->opWithPayload(seq);
backgroundBatchOneway->opWithPayload(seq);
ctl->resumeAdapter();
- FlushBatchRequestsCallbackPtr fcb = new FlushBatchRequestsCallback();
+ fcb = new FlushBatchRequestsCallback();
backgroundBatchOneway->ice_flushBatchRequests_async(fcb);
//
// We can't close the connection before ensuring all the batches have been sent since
diff --git a/cpp/test/Ice/binding/AllTests.cpp b/cpp/test/Ice/binding/AllTests.cpp
index eec35751912..1f9b133d7c9 100644
--- a/cpp/test/Ice/binding/AllTests.cpp
+++ b/cpp/test/Ice/binding/AllTests.cpp
@@ -62,6 +62,21 @@ private:
};
typedef IceUtil::Handle<GetAdapterNameCB> GetAdapterNameCBPtr;
+class NoOpGetAdapterNameCB : public AMI_TestIntf_getAdapterName
+{
+public:
+
+ virtual void
+ ice_response(const string&)
+ {
+ }
+
+ virtual void
+ ice_exception(const Ice::Exception&)
+ {
+ }
+};
+
string
getAdapterNameWithAMI(const TestIntfPrx& test)
{
@@ -220,6 +235,95 @@ allTests(const Ice::CommunicatorPtr& communicator)
}
cout << "ok" << endl;
+ cout << "testing binding with multiple random endpoints... " << flush;
+ {
+ vector<RemoteObjectAdapterPrx> adapters;
+ adapters.push_back(com->createObjectAdapter("AdapterRandom11", "default"));
+ adapters.push_back(com->createObjectAdapter("AdapterRandom12", "default"));
+ adapters.push_back(com->createObjectAdapter("AdapterRandom13", "default"));
+ adapters.push_back(com->createObjectAdapter("AdapterRandom14", "default"));
+ adapters.push_back(com->createObjectAdapter("AdapterRandom15", "default"));
+
+#ifdef _WIN32
+ int count = 60;
+#else
+ int count = 20;
+#endif
+ int adapterCount = adapters.size();
+ while(--count > 0)
+ {
+#ifdef _WIN32
+ if(count == 10)
+ {
+ com->deactivateObjectAdapter(adapters[4]);
+ --adapterCount;
+ }
+ vector<TestIntfPrx> proxies;
+ proxies.resize(10);
+#else
+ if(count < 60 && count % 10 == 0)
+ {
+ com->deactivateObjectAdapter(adapters[count / 10 - 1]);
+ --adapterCount;
+ }
+ vector<TestIntfPrx> proxies;
+ proxies.resize(40);
+#endif
+ unsigned int i;
+ for(i = 0; i < proxies.size(); ++i)
+ {
+ vector<RemoteObjectAdapterPrx> adpts;
+ adpts.resize(IceUtilInternal::random(static_cast<int>(adapters.size())));
+ if(adpts.empty())
+ {
+ adpts.resize(1);
+ }
+ for(vector<RemoteObjectAdapterPrx>::iterator p = adpts.begin(); p != adpts.end(); ++p)
+ {
+ *p = adapters[IceUtilInternal::random(static_cast<int>(adapters.size()))];
+ }
+ proxies[i] = createTestIntfPrx(adpts);
+ }
+
+ for(i = 0; i < proxies.size(); i++)
+ {
+ proxies[i]->getAdapterName_async(new NoOpGetAdapterNameCB());
+ }
+ for(i = 0; i < proxies.size(); i++)
+ {
+ try
+ {
+ proxies[i]->ice_ping();
+ }
+ catch(const Ice::LocalException&)
+ {
+ }
+ }
+ set<Ice::ConnectionPtr> connections;
+ for(i = 0; i < proxies.size(); i++)
+ {
+ if(proxies[i]->ice_getCachedConnection())
+ {
+ connections.insert(proxies[i]->ice_getCachedConnection());
+ }
+ }
+ test(static_cast<int>(connections.size()) <= adapterCount);
+
+ for(vector<RemoteObjectAdapterPrx>::const_iterator q = adapters.begin(); q != adapters.end(); ++q)
+ {
+ try
+ {
+ (*q)->getTestIntf()->ice_getConnection()->close(false);
+ }
+ catch(const Ice::LocalException&)
+ {
+ // Expected if adapter is down.
+ }
+ }
+ }
+ }
+ cout << "ok" << endl;
+
cout << "testing binding with multiple endpoints and AMI... " << flush;
{
vector<RemoteObjectAdapterPrx> adapters;
@@ -468,7 +572,6 @@ allTests(const Ice::CommunicatorPtr& communicator)
com->deactivateObjectAdapter(adapters[2]);
-
test(test->getAdapterName() == "Adapter52");
deactivate(com, adapters);
diff --git a/cpp/test/Ice/gc/run.py b/cpp/test/Ice/gc/run.py
index 03a703b953c..ced3120bc64 100755
--- a/cpp/test/Ice/gc/run.py
+++ b/cpp/test/Ice/gc/run.py
@@ -25,5 +25,8 @@ client = os.path.join(os.getcwd(), "client")
seedfile = os.path.join(os.getcwd(), "seed")
TestUtil.simpleTest(client, seedfile)
-TestUtil.startClient(client, seedfile)
+
+clientProc = TestUtil.startClient(client, seedfile)
+clientProc.waitTestSuccess()
+
os.remove(seedfile)