summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/Reference.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2006-02-10 16:41:42 +0000
committerBenoit Foucher <benoit@zeroc.com>2006-02-10 16:41:42 +0000
commit5d0005ecc2e7b0b468ef49297a02cf5ec8fd31fe (patch)
tree09583bad00eb87888e2881d4abd58b2d05ac2344 /cpp/src/Ice/Reference.cpp
parentChanged Ice-E version to 1.1.0 (diff)
downloadice-5d0005ecc2e7b0b468ef49297a02cf5ec8fd31fe.tar.bz2
ice-5d0005ecc2e7b0b468ef49297a02cf5ec8fd31fe.tar.xz
ice-5d0005ecc2e7b0b468ef49297a02cf5ec8fd31fe.zip
- Added ice_cacheConnection, ice_endpointSelection proxy methods.
- Added binding test.
Diffstat (limited to 'cpp/src/Ice/Reference.cpp')
-rw-r--r--cpp/src/Ice/Reference.cpp420
1 files changed, 263 insertions, 157 deletions
diff --git a/cpp/src/Ice/Reference.cpp b/cpp/src/Ice/Reference.cpp
index b0bcdb05d78..6ebe481ea3f 100644
--- a/cpp/src/Ice/Reference.cpp
+++ b/cpp/src/Ice/Reference.cpp
@@ -33,10 +33,10 @@ using namespace IceInternal;
void IceInternal::incRef(IceInternal::Reference* p) { p->__incRef(); }
void IceInternal::decRef(IceInternal::Reference* p) { p->__decRef(); }
-const Context&
-IceInternal::Reference::getContext() const
+CommunicatorPtr
+IceInternal::Reference::getCommunicator() const
{
- return _context;
+ return _communicator;
}
ReferencePtr
@@ -47,12 +47,6 @@ IceInternal::Reference::defaultContext() const
return r;
}
-CommunicatorPtr
-IceInternal::Reference::getCommunicator() const
-{
- return _communicator;
-}
-
ReferencePtr
IceInternal::Reference::changeContext(const Context& newContext) const
{
@@ -97,6 +91,30 @@ IceInternal::Reference::changeFacet(const string& newFacet) const
return r;
}
+ReferencePtr
+IceInternal::Reference::changeCacheConnection(bool newCache) const
+{
+ if(newCache == _cacheConnection)
+ {
+ return ReferencePtr(const_cast<Reference*>(this));
+ }
+ ReferencePtr r = _instance->referenceFactory()->copy(this);
+ r->_cacheConnection = newCache;
+ return r;
+}
+
+ReferencePtr
+IceInternal::Reference::changeEndpointSelection(EndpointSelectionType newType) const
+{
+ if(newType == _endpointSelection)
+ {
+ return ReferencePtr(const_cast<Reference*>(this));
+ }
+ ReferencePtr r = _instance->referenceFactory()->copy(this);
+ r->_endpointSelection = newType;
+ return r;
+}
+
Int
Reference::hash() const
{
@@ -284,6 +302,16 @@ IceInternal::Reference::operator==(const Reference& r) const
return false;
}
+ if(_cacheConnection != r._cacheConnection)
+ {
+ return false;
+ }
+
+ if(_endpointSelection != r._endpointSelection)
+ {
+ return false;
+ }
+
return true;
}
@@ -335,7 +363,25 @@ IceInternal::Reference::operator<(const Reference& r) const
{
return false;
}
-
+
+ if(!_cacheConnection && r._cacheConnection)
+ {
+ return true;
+ }
+ else if(r._cacheConnection < _cacheConnection)
+ {
+ return false;
+ }
+
+ if(_endpointSelection < r._endpointSelection)
+ {
+ return true;
+ }
+ else if(r._endpointSelection < _endpointSelection)
+ {
+ return false;
+ }
+
return false;
}
@@ -369,6 +415,8 @@ IceInternal::Reference::Reference(const InstancePtr& inst, const CommunicatorPtr
_identity(ident),
_context(ctx),
_facet(fs),
+ _cacheConnection(true),
+ _endpointSelection(Random),
_hashInitialized(false)
{
}
@@ -380,6 +428,8 @@ IceInternal::Reference::Reference(const Reference& r)
_identity(r._identity),
_context(r._context),
_facet(r._facet),
+ _cacheConnection(r._cacheConnection),
+ _endpointSelection(r._endpointSelection),
_hashInitialized(false)
{
}
@@ -512,7 +562,7 @@ IceInternal::FixedReference::toString() const
ConnectionIPtr
IceInternal::FixedReference::getConnection(bool& compress) const
{
- vector<ConnectionIPtr> filteredConns = filterConnections(_fixedConnections, getMode(), getSecure());
+ vector<ConnectionIPtr> filteredConns = filterConnections(_fixedConnections);
if(filteredConns.empty())
{
NoEndpointException ex(__FILE__, __LINE__);
@@ -582,6 +632,66 @@ IceInternal::FixedReference::FixedReference(const FixedReference& r)
{
}
+vector<ConnectionIPtr>
+IceInternal::FixedReference::filterConnections(const vector<ConnectionIPtr>& allConnections) const
+{
+ vector<ConnectionIPtr> connections = allConnections;
+
+ switch(getMode())
+ {
+ case Reference::ModeTwoway:
+ case Reference::ModeOneway:
+ case Reference::ModeBatchOneway:
+ {
+ //
+ // Filter out datagram connections.
+ //
+ connections.erase(remove_if(connections.begin(), connections.end(), ConnectionIsDatagram()),
+ connections.end());
+ break;
+ }
+
+ case Reference::ModeDatagram:
+ case Reference::ModeBatchDatagram:
+ {
+ //
+ // Filter out non-datagram connections.
+ //
+ connections.erase(remove_if(connections.begin(), connections.end(), not1(ConnectionIsDatagram())),
+ connections.end());
+ break;
+ }
+ }
+
+ //
+ // Randomize the order of connections.
+ //
+ random_shuffle(connections.begin(), connections.end());
+
+ //
+ // If a secure connection is requested, remove all non-secure
+ // connections. Otherwise make non-secure connections preferred over
+ // secure connections by partitioning the connection vector, so that
+ // non-secure connections come first.
+ //
+ if(getSecure())
+ {
+ connections.erase(remove_if(connections.begin(), connections.end(), not1(ConnectionIsSecure())),
+ connections.end());
+ }
+ else
+ {
+ //
+ // We must use stable_partition() instead of just simply
+ // partition(), because otherwise some STL implementations
+ // order our now randomized connections.
+ //
+ stable_partition(connections.begin(), connections.end(), not1(ConnectionIsSecure()));
+ }
+
+ return connections;
+}
+
void IceInternal::incRef(IceInternal::RoutableReference* p) { p->__incRef(); }
void IceInternal::decRef(IceInternal::RoutableReference* p) { p->__decRef(); }
@@ -734,6 +844,142 @@ IceInternal::RoutableReference::RoutableReference(const RoutableReference& r)
{
}
+ConnectionIPtr
+IceInternal::RoutableReference::createConnection(const vector<EndpointIPtr>& allEndpoints, bool& comp) const
+{
+ vector<EndpointIPtr> endpoints = allEndpoints;
+
+ //
+ // Filter out unknown endpoints.
+ //
+ endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), Ice::constMemFun(&EndpointI::unknown)),
+ endpoints.end());
+
+ //
+ // Filter out endpoints according to the mode of the reference.
+ //
+ switch(getMode())
+ {
+ case Reference::ModeTwoway:
+ case Reference::ModeOneway:
+ case Reference::ModeBatchOneway:
+ {
+ //
+ // Filter out datagram endpoints.
+ //
+ endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), Ice::constMemFun(&EndpointI::datagram)),
+ endpoints.end());
+ break;
+ }
+
+ case Reference::ModeDatagram:
+ case Reference::ModeBatchDatagram:
+ {
+ //
+ // Filter out non-datagram endpoints.
+ //
+ endpoints.erase(remove_if(endpoints.begin(), endpoints.end(),
+ not1(Ice::constMemFun(&EndpointI::datagram))),
+ endpoints.end());
+ break;
+ }
+ }
+
+ //
+ // Sort the endpoints according to the endpoint selection type.
+ //
+ switch(getEndpointSelection())
+ {
+ case Random:
+ {
+ random_shuffle(endpoints.begin(), endpoints.end());
+ break;
+ }
+ case Ordered:
+ {
+ // Nothing to do.
+ break;
+ }
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+
+ //
+ // If a secure connection is requested, remove all non-secure
+ // endpoints. Otherwise make non-secure endpoints preferred over
+ // secure endpoints by partitioning the endpoint vector, so that
+ // non-secure endpoints come first.
+ //
+ if(getSecure())
+ {
+ endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), not1(Ice::constMemFun(&EndpointI::secure))),
+ endpoints.end());
+ }
+ else
+ {
+ //
+ // We must use stable_partition() instead of just simply
+ // partition(), because otherwise some STL implementations
+ // order our now randomized endpoints.
+ //
+ stable_partition(endpoints.begin(), endpoints.end(), not1(Ice::constMemFun(&EndpointI::secure)));
+ }
+
+ if(endpoints.empty())
+ {
+ NoEndpointException ex(__FILE__, __LINE__);
+ ex.proxy = toString();
+ throw ex;
+ }
+
+ //
+ // Finally, create the connection.
+ //
+ OutgoingConnectionFactoryPtr factory = getInstance()->outgoingConnectionFactory();
+ if(getCacheConnection() || endpoints.size() == 1)
+ {
+ //
+ // Get an existing connection or create one if there's no
+ // existing connection to one of the given endpoints.
+ //
+ return factory->create(endpoints, false, comp);
+ }
+ else
+ {
+ //
+ // Go through the list of endpoints and try to create the
+ // connection until it succeeds. This is different from just
+ // calling create() with the given endpoints since this might
+ // create a new connection even if there's an existing
+ // connection for one of the endpoints.
+ //
+
+ auto_ptr<LocalException> exception;
+ vector<EndpointIPtr> endpoint;
+ endpoint.push_back(0);
+
+ for(vector<EndpointIPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p)
+ {
+ try
+ {
+ endpoint.back() = *p;
+ return factory->create(endpoint, p + 1 == endpoints.end(), comp);
+ }
+ catch(const LocalException& ex)
+ {
+ exception.reset(dynamic_cast<LocalException*>(ex.ice_clone()));
+ }
+ }
+
+ assert(exception.get());
+ exception->ice_throw();
+ return 0; // Keeps the compiler happy.
+ }
+}
+
void IceInternal::incRef(IceInternal::DirectReference* p) { p->__incRef(); }
void IceInternal::decRef(IceInternal::DirectReference* p) { p->__decRef(); }
@@ -905,17 +1151,8 @@ IceInternal::DirectReference::getConnection(bool& comp) const
{
endpts = _endpoints;
}
- vector<EndpointIPtr> filteredEndpoints = filterEndpoints(endpts, getMode(), getSecure());
- if(filteredEndpoints.empty())
- {
- NoEndpointException ex(__FILE__, __LINE__);
- ex.proxy = toString();
- throw ex;
- }
- OutgoingConnectionFactoryPtr factory = getInstance()->outgoingConnectionFactory();
- ConnectionIPtr connection = factory->create(filteredEndpoints, comp);
- assert(connection);
+ ConnectionIPtr connection = createConnection(endpts, comp);
//
// If we have a router, set the object adapter for this router
@@ -986,7 +1223,6 @@ IceInternal::DirectReference::DirectReference(const DirectReference& r)
{
}
-
void IceInternal::incRef(IceInternal::IndirectReference* p) { p->__incRef(); }
void IceInternal::decRef(IceInternal::IndirectReference* p) { p->__decRef(); }
@@ -1181,20 +1417,16 @@ IceInternal::IndirectReference::getConnection(bool& comp) const
{
*p = (*p)->connectionId(_connectionId);
}
- vector<EndpointIPtr> filteredEndpoints = filterEndpoints(endpts, getMode(), getSecure());
- if(filteredEndpoints.empty())
- {
- NoEndpointException ex(__FILE__, __LINE__);
- ex.proxy = toString();
- throw ex;
- }
try
{
- OutgoingConnectionFactoryPtr factory = getInstance()->outgoingConnectionFactory();
- connection = factory->create(filteredEndpoints, comp);
+ connection = createConnection(endpts, comp);
assert(connection);
}
+ catch(const NoEndpointException& ex)
+ {
+ throw ex; // No need to retry if there's no endpoints.
+ }
catch(const LocalException& ex)
{
if(!getRouterInfo())
@@ -1324,129 +1556,3 @@ IceInternal::IndirectReference::IndirectReference(const IndirectReference& r)
{
}
-vector<EndpointIPtr>
-IceInternal::filterEndpoints(const vector<EndpointIPtr>& allEndpoints, Reference::Mode m, bool sec)
-{
- vector<EndpointIPtr> endpoints = allEndpoints;
-
- //
- // Filter out unknown endpoints.
- //
- endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), Ice::constMemFun(&EndpointI::unknown)),
- endpoints.end());
-
- switch(m)
- {
- case Reference::ModeTwoway:
- case Reference::ModeOneway:
- case Reference::ModeBatchOneway:
- {
- //
- // Filter out datagram endpoints.
- //
- endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), Ice::constMemFun(&EndpointI::datagram)),
- endpoints.end());
- break;
- }
-
- case Reference::ModeDatagram:
- case Reference::ModeBatchDatagram:
- {
- //
- // Filter out non-datagram endpoints.
- //
- endpoints.erase(remove_if(endpoints.begin(), endpoints.end(),
- not1(Ice::constMemFun(&EndpointI::datagram))),
- endpoints.end());
- break;
- }
- }
-
- //
- // Randomize the order of endpoints.
- //
- random_shuffle(endpoints.begin(), endpoints.end());
-
- //
- // If a secure connection is requested, remove all non-secure
- // endpoints. Otherwise make non-secure endpoints preferred over
- // secure endpoints by partitioning the endpoint vector, so that
- // non-secure endpoints come first.
- //
- if(sec)
- {
- endpoints.erase(remove_if(endpoints.begin(), endpoints.end(), not1(Ice::constMemFun(&EndpointI::secure))),
- endpoints.end());
- }
- else
- {
- //
- // We must use stable_partition() instead of just simply
- // partition(), because otherwise some STL implementations
- // order our now randomized endpoints.
- //
- stable_partition(endpoints.begin(), endpoints.end(), not1(Ice::constMemFun(&EndpointI::secure)));
- }
-
- return endpoints;
-}
-
-vector<ConnectionIPtr>
-IceInternal::filterConnections(const vector<ConnectionIPtr>& allConnections, Reference::Mode m, bool secure)
-{
- vector<ConnectionIPtr> connections = allConnections;
-
- switch(m)
- {
- case Reference::ModeTwoway:
- case Reference::ModeOneway:
- case Reference::ModeBatchOneway:
- {
- //
- // Filter out datagram connections.
- //
- connections.erase(remove_if(connections.begin(), connections.end(), ConnectionIsDatagram()),
- connections.end());
- break;
- }
-
- case Reference::ModeDatagram:
- case Reference::ModeBatchDatagram:
- {
- //
- // Filter out non-datagram connections.
- //
- connections.erase(remove_if(connections.begin(), connections.end(), not1(ConnectionIsDatagram())),
- connections.end());
- break;
- }
- }
-
- //
- // Randomize the order of connections.
- //
- random_shuffle(connections.begin(), connections.end());
-
- //
- // If a secure connection is requested, remove all non-secure
- // connections. Otherwise make non-secure connections preferred over
- // secure connections by partitioning the connection vector, so that
- // non-secure connections come first.
- //
- if(secure)
- {
- connections.erase(remove_if(connections.begin(), connections.end(), not1(ConnectionIsSecure())),
- connections.end());
- }
- else
- {
- //
- // We must use stable_partition() instead of just simply
- // partition(), because otherwise some STL implementations
- // order our now randomized connections.
- //
- stable_partition(connections.begin(), connections.end(), not1(ConnectionIsSecure()));
- }
-
- return connections;
-}