summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorDwayne Boone <dwayne@zeroc.com>2007-05-18 13:34:39 +0000
committerDwayne Boone <dwayne@zeroc.com>2007-05-18 13:34:39 +0000
commitbdcafea81addb5e3905c6ed5f4db093ec8ec0d15 (patch)
tree7cea0017b188b25abf1caac607476e21d63a8a7e /cpp/src
parentFixed comments (diff)
downloadice-bdcafea81addb5e3905c6ed5f4db093ec8ec0d15.tar.bz2
ice-bdcafea81addb5e3905c6ed5f4db093ec8ec0d15.tar.xz
ice-bdcafea81addb5e3905c6ed5f4db093ec8ec0d15.zip
Multi-home host support
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp103
-rw-r--r--cpp/src/Ice/ConnectionFactory.h3
-rw-r--r--cpp/src/Ice/EndpointI.h12
-rw-r--r--cpp/src/Ice/Network.cpp32
-rw-r--r--cpp/src/Ice/Network.h1
-rw-r--r--cpp/src/Ice/Reference.cpp5
-rw-r--r--cpp/src/Ice/TcpEndpointI.cpp26
-rw-r--r--cpp/src/Ice/TcpEndpointI.h4
-rw-r--r--cpp/src/Ice/UdpEndpointI.cpp26
-rw-r--r--cpp/src/Ice/UdpEndpointI.h4
-rw-r--r--cpp/src/Ice/UnknownEndpointI.cpp14
-rw-r--r--cpp/src/Ice/UnknownEndpointI.h4
-rw-r--r--cpp/src/IceSSL/EndpointI.cpp26
-rw-r--r--cpp/src/IceSSL/EndpointI.h4
14 files changed, 200 insertions, 64 deletions
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index 785d6264508..6bcc4c9ca20 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -24,6 +24,7 @@
#include <Ice/RouterInfo.h>
#include <Ice/LocalException.h>
#include <Ice/Functional.h>
+#include <IceUtil/Random.h>
#ifdef __BCPLUSPLUS__
# include <iterator>
#endif
@@ -35,6 +36,17 @@ using namespace IceInternal;
IceUtil::Shared* IceInternal::upCast(OutgoingConnectionFactory* p) { return p; }
IceUtil::Shared* IceInternal::upCast(IncomingConnectionFactory* p) { return p; }
+namespace
+{
+struct RandomNumberGenerator : public std::unary_function<ptrdiff_t, ptrdiff_t>
+{
+ ptrdiff_t operator()(ptrdiff_t d)
+ {
+ return IceUtil::random(static_cast<int>(d));
+ }
+};
+}
+
void
IceInternal::OutgoingConnectionFactory::destroy()
{
@@ -91,7 +103,8 @@ IceInternal::OutgoingConnectionFactory::waitUntilFinished()
ConnectionIPtr
IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpts, bool moreEndpts,
- bool threadPerConnection, bool& compress)
+ bool threadPerConnection, Ice::EndpointSelectionType selType,
+ bool& compress)
{
assert(!endpts.empty());
vector<EndpointIPtr> endpoints = endpts;
@@ -267,13 +280,23 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
try
{
- TransceiverPtr transceiver = endpoint->clientTransceiver();
- if(!transceiver)
+ vector<ConnectorPtr> connectors;
+ unsigned int size;
+ Int timeout;
+
+ vector<TransceiverPtr> transceivers = endpoint->clientTransceivers();
+ if(transceivers.size() == 0)
{
- ConnectorPtr connector = endpoint->connector();
- assert(connector);
+ connectors = endpoint->connectors();
+ size = connectors.size();
+ assert(size > 0);
+
+ if(selType == Random)
+ {
+ RandomNumberGenerator rng;
+ random_shuffle(connectors.begin(), connectors.end(), rng);
+ }
- Int timeout;
if(_instance->defaultsAndOverrides()->overrideConnectTimeout)
{
timeout = _instance->defaultsAndOverrides()->overrideConnectTimeoutValue;
@@ -285,14 +308,58 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
{
timeout = endpoint->timeout();
}
-
- transceiver = connector->connect(timeout);
- assert(transceiver);
}
- connection = new ConnectionI(_instance, transceiver, endpoint, 0, threadPerConnection,
- _instance->threadPerConnectionStackSize());
- connection->start();
- connection->validate();
+ else
+ {
+ size = transceivers.size();
+ if(selType == Random)
+ {
+ RandomNumberGenerator rng;
+ random_shuffle(transceivers.begin(), transceivers.end(), rng);
+ }
+ }
+
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ try
+ {
+ TransceiverPtr transceiver;
+ if(transceivers.size() == size)
+ {
+ transceiver = transceivers[i];
+ }
+ else
+ {
+ transceiver = connectors[i]->connect(timeout);
+ assert(transceiver);
+ }
+
+ connection = new ConnectionI(_instance, transceiver, endpoint, 0, threadPerConnection,
+ _instance->threadPerConnectionStackSize());
+ connection->start();
+ connection->validate();
+ }
+ catch(const LocalException& ex)
+ {
+ //
+ // If a connection object was constructed, then validate()
+ // must have raised the exception.
+ //
+ if(connection)
+ {
+ connection->waitUntilFinished(); // We must call waitUntilFinished() for cleanup.
+ connection = 0;
+ }
+
+ //
+ // Throw exception if this is last transceiver in list.
+ //
+ if(i == size - 1)
+ {
+ ex.ice_throw();
+ }
+ }
+ }
if(_instance->defaultsAndOverrides()->overrideCompress)
{
@@ -307,16 +374,6 @@ IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpt
catch(const LocalException& ex)
{
exception.reset(dynamic_cast<LocalException*>(ex.ice_clone()));
-
- //
- // If a connection object was constructed, then validate()
- // must have raised the exception.
- //
- if(connection)
- {
- connection->waitUntilFinished(); // We must call waitUntilFinished() for cleanup.
- connection = 0;
- }
}
TraceLevelsPtr traceLevels = _instance->traceLevels();
diff --git a/cpp/src/Ice/ConnectionFactory.h b/cpp/src/Ice/ConnectionFactory.h
index 7758e675b8d..0f517008f09 100644
--- a/cpp/src/Ice/ConnectionFactory.h
+++ b/cpp/src/Ice/ConnectionFactory.h
@@ -18,6 +18,7 @@
#include <Ice/InstanceF.h>
#include <Ice/ObjectAdapterF.h>
#include <Ice/EndpointIF.h>
+#include <Ice/Endpoint.h>
#include <Ice/AcceptorF.h>
#include <Ice/TransceiverF.h>
#include <Ice/RouterInfoF.h>
@@ -44,7 +45,7 @@ public:
void waitUntilFinished();
- Ice::ConnectionIPtr create(const std::vector<EndpointIPtr>&, bool, bool, bool&);
+ Ice::ConnectionIPtr create(const std::vector<EndpointIPtr>&, bool, bool, Ice::EndpointSelectionType, bool&);
void setRouterInfo(const RouterInfoPtr&);
void removeAdapter(const Ice::ObjectAdapterPtr&);
void flushBatchRequests();
diff --git a/cpp/src/Ice/EndpointI.h b/cpp/src/Ice/EndpointI.h
index 5d6362ecd93..d6f86782d0b 100644
--- a/cpp/src/Ice/EndpointI.h
+++ b/cpp/src/Ice/EndpointI.h
@@ -84,10 +84,10 @@ public:
virtual bool unknown() const = 0;
//
- // Return a client side transceiver for this endpoint, or null if a
- // transceiver can only be created by a connector.
+ // Return client side transceivers for this endpoint, or empty
+ // vector if a transceiver can only be created by a connector.
//
- virtual TransceiverPtr clientTransceiver() const = 0;
+ virtual std::vector<TransceiverPtr> clientTransceivers() const = 0;
//
// Return a server side transceiver for this endpoint, or null if a
@@ -99,10 +99,10 @@ public:
virtual TransceiverPtr serverTransceiver(EndpointIPtr&) const = 0;
//
- // Return a connector for this endpoint, or null if no connector
- // is available.
+ // Return connectors for this endpoint, or empty vector if no
+ // connector is available.
//
- virtual ConnectorPtr connector() const = 0;
+ virtual std::vector<ConnectorPtr> connectors() const = 0;
//
// Return an acceptor for this endpoint, or null if no acceptors
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp
index 33bfec5739f..6e907c4bdbe 100644
--- a/cpp/src/Ice/Network.cpp
+++ b/cpp/src/Ice/Network.cpp
@@ -1260,6 +1260,38 @@ IceInternal::addrToString(const struct sockaddr_in& addr)
}
vector<string>
+IceInternal::getHosts(const string& host)
+{
+ vector<string> result;
+ struct hostent* he = 0;
+ int retry = 5;
+
+ do
+ {
+ he = gethostbyname(host.c_str());
+ }
+ while(he == 0 && h_errno == TRY_AGAIN && --retry >= 0);
+
+ if(he == 0)
+ {
+ DNSException ex(__FILE__, __LINE__);
+ ex.error = h_errno;
+ ex.host = host;
+ throw ex;
+ }
+
+ char** ptr = he->h_addr_list;
+ while(*ptr)
+ {
+ struct in_addr* addr = reinterpret_cast<in_addr*>(*ptr);
+ result.push_back(inet_ntoa(*addr));
+ ptr++;
+ }
+
+ return result;
+}
+
+vector<string>
IceInternal::getLocalHosts()
{
vector<string> result;
diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h
index 6ee6c80d72f..f03836965c6 100644
--- a/cpp/src/Ice/Network.h
+++ b/cpp/src/Ice/Network.h
@@ -107,6 +107,7 @@ ICE_API void fdToLocalAddress(SOCKET, struct sockaddr_in&);
ICE_API bool fdToRemoteAddress(SOCKET, struct sockaddr_in&);
ICE_API std::string addrToString(const struct sockaddr_in&);
+ICE_API std::vector<std::string> getHosts(const std::string&);
ICE_API std::vector<std::string> getLocalHosts();
#ifdef _WIN32
ICE_API std::vector<struct sockaddr_in> getLocalAddresses();
diff --git a/cpp/src/Ice/Reference.cpp b/cpp/src/Ice/Reference.cpp
index 52ec2031ec7..b9e1d534836 100644
--- a/cpp/src/Ice/Reference.cpp
+++ b/cpp/src/Ice/Reference.cpp
@@ -1242,7 +1242,7 @@ IceInternal::RoutableReference::createConnection(const vector<EndpointIPtr>& all
// Get an existing connection or create one if there's no
// existing connection to one of the given endpoints.
//
- return factory->create(endpoints, false, _threadPerConnection, comp);
+ return factory->create(endpoints, false, _threadPerConnection, getEndpointSelection(), comp);
}
else
{
@@ -1263,7 +1263,8 @@ IceInternal::RoutableReference::createConnection(const vector<EndpointIPtr>& all
try
{
endpoint.back() = *p;
- return factory->create(endpoint, p + 1 == endpoints.end(), _threadPerConnection, comp);
+ return factory->create(endpoint, p + 1 == endpoints.end(), _threadPerConnection,
+ getEndpointSelection(), comp);
}
catch(const LocalException& ex)
{
diff --git a/cpp/src/Ice/TcpEndpointI.cpp b/cpp/src/Ice/TcpEndpointI.cpp
index 6cf54872826..6b0b7a5c4b5 100644
--- a/cpp/src/Ice/TcpEndpointI.cpp
+++ b/cpp/src/Ice/TcpEndpointI.cpp
@@ -265,10 +265,11 @@ IceInternal::TcpEndpointI::unknown() const
return false;
}
-TransceiverPtr
-IceInternal::TcpEndpointI::clientTransceiver() const
+vector<TransceiverPtr>
+IceInternal::TcpEndpointI::clientTransceivers() const
{
- return 0;
+ vector<TransceiverPtr> ret;
+ return ret;
}
TransceiverPtr
@@ -278,10 +279,23 @@ IceInternal::TcpEndpointI::serverTransceiver(EndpointIPtr& endp) const
return 0;
}
-ConnectorPtr
-IceInternal::TcpEndpointI::connector() const
+vector<ConnectorPtr>
+IceInternal::TcpEndpointI::connectors() const
{
- return new TcpConnector(_instance, _host, _port);
+ vector<ConnectorPtr> connectors;
+ vector<string> hosts = getHosts(_host);
+ if(hosts.size() > 1)
+ {
+ for(unsigned int i = 0; i < hosts.size(); ++i)
+ {
+ connectors.push_back(new TcpConnector(_instance, hosts[i], _port));
+ }
+ }
+ else
+ {
+ connectors.push_back(new TcpConnector(_instance, _host, _port));
+ }
+ return connectors;
}
AcceptorPtr
diff --git a/cpp/src/Ice/TcpEndpointI.h b/cpp/src/Ice/TcpEndpointI.h
index b3e542b09bd..0e003a179ef 100644
--- a/cpp/src/Ice/TcpEndpointI.h
+++ b/cpp/src/Ice/TcpEndpointI.h
@@ -37,9 +37,9 @@ public:
virtual bool datagram() const;
virtual bool secure() const;
virtual bool unknown() const;
- virtual TransceiverPtr clientTransceiver() const;
+ virtual std::vector<TransceiverPtr> clientTransceivers() const;
virtual TransceiverPtr serverTransceiver(EndpointIPtr&) const;
- virtual ConnectorPtr connector() const;
+ virtual std::vector<ConnectorPtr> connectors() const;
virtual AcceptorPtr acceptor(EndpointIPtr&, const std::string&) const;
virtual std::vector<EndpointIPtr> expand(bool) const;
virtual bool publish() const;
diff --git a/cpp/src/Ice/UdpEndpointI.cpp b/cpp/src/Ice/UdpEndpointI.cpp
index 6681e8becbf..e6bfffa3818 100644
--- a/cpp/src/Ice/UdpEndpointI.cpp
+++ b/cpp/src/Ice/UdpEndpointI.cpp
@@ -430,10 +430,23 @@ IceInternal::UdpEndpointI::unknown() const
return false;
}
-TransceiverPtr
-IceInternal::UdpEndpointI::clientTransceiver() const
+vector<TransceiverPtr>
+IceInternal::UdpEndpointI::clientTransceivers() const
{
- return new UdpTransceiver(_instance, _host, _port);
+ vector<TransceiverPtr> transceivers;
+ vector<string> hosts = getHosts(_host);
+ if(hosts.size() > 1)
+ {
+ for(unsigned int i = 0; i < hosts.size(); ++i)
+ {
+ transceivers.push_back(new UdpTransceiver(_instance, hosts[i], _port));
+ }
+ }
+ else
+ {
+ transceivers.push_back(new UdpTransceiver(_instance, _host, _port));
+ }
+ return transceivers;
}
TransceiverPtr
@@ -444,10 +457,11 @@ IceInternal::UdpEndpointI::serverTransceiver(EndpointIPtr& endp) const
return p;
}
-ConnectorPtr
-IceInternal::UdpEndpointI::connector() const
+vector<ConnectorPtr>
+IceInternal::UdpEndpointI::connectors() const
{
- return 0;
+ vector<ConnectorPtr> ret;
+ return ret;
}
AcceptorPtr
diff --git a/cpp/src/Ice/UdpEndpointI.h b/cpp/src/Ice/UdpEndpointI.h
index a19e1cbd295..7e5b5a87175 100644
--- a/cpp/src/Ice/UdpEndpointI.h
+++ b/cpp/src/Ice/UdpEndpointI.h
@@ -37,9 +37,9 @@ public:
virtual bool datagram() const;
virtual bool secure() const;
virtual bool unknown() const;
- virtual TransceiverPtr clientTransceiver() const;
+ virtual std::vector<TransceiverPtr> clientTransceivers() const;
virtual TransceiverPtr serverTransceiver(EndpointIPtr&) const;
- virtual ConnectorPtr connector() const;
+ virtual std::vector<ConnectorPtr> connectors() const;
virtual AcceptorPtr acceptor(EndpointIPtr&, const std::string&) const;
virtual std::vector<EndpointIPtr> expand(bool) const;
virtual bool publish() const;
diff --git a/cpp/src/Ice/UnknownEndpointI.cpp b/cpp/src/Ice/UnknownEndpointI.cpp
index cb6526221c7..a50699e29c7 100644
--- a/cpp/src/Ice/UnknownEndpointI.cpp
+++ b/cpp/src/Ice/UnknownEndpointI.cpp
@@ -199,10 +199,11 @@ IceInternal::UnknownEndpointI::unknown() const
return true;
}
-TransceiverPtr
-IceInternal::UnknownEndpointI::clientTransceiver() const
+vector<TransceiverPtr>
+IceInternal::UnknownEndpointI::clientTransceivers() const
{
- return 0;
+ vector<TransceiverPtr> ret;
+ return ret;
}
TransceiverPtr
@@ -212,10 +213,11 @@ IceInternal::UnknownEndpointI::serverTransceiver(EndpointIPtr& endp) const
return 0;
}
-ConnectorPtr
-IceInternal::UnknownEndpointI::connector() const
+vector<ConnectorPtr>
+IceInternal::UnknownEndpointI::connectors() const
{
- return 0;
+ vector<ConnectorPtr> ret;
+ return ret;
}
AcceptorPtr
diff --git a/cpp/src/Ice/UnknownEndpointI.h b/cpp/src/Ice/UnknownEndpointI.h
index c3036018eeb..2247c0485a2 100644
--- a/cpp/src/Ice/UnknownEndpointI.h
+++ b/cpp/src/Ice/UnknownEndpointI.h
@@ -34,9 +34,9 @@ public:
virtual bool datagram() const;
virtual bool secure() const;
virtual bool unknown() const;
- virtual TransceiverPtr clientTransceiver() const;
+ virtual std::vector<TransceiverPtr> clientTransceivers() const;
virtual TransceiverPtr serverTransceiver(EndpointIPtr&) const;
- virtual ConnectorPtr connector() const;
+ virtual std::vector<ConnectorPtr> connectors() const;
virtual AcceptorPtr acceptor(EndpointIPtr&, const std::string&) const;
virtual std::vector<EndpointIPtr> expand(bool) const;
virtual bool publish() const;
diff --git a/cpp/src/IceSSL/EndpointI.cpp b/cpp/src/IceSSL/EndpointI.cpp
index 69866544132..a657b027874 100644
--- a/cpp/src/IceSSL/EndpointI.cpp
+++ b/cpp/src/IceSSL/EndpointI.cpp
@@ -265,10 +265,11 @@ IceSSL::EndpointI::unknown() const
return false;
}
-IceInternal::TransceiverPtr
-IceSSL::EndpointI::clientTransceiver() const
+vector<IceInternal::TransceiverPtr>
+IceSSL::EndpointI::clientTransceivers() const
{
- return 0;
+ vector<IceInternal::TransceiverPtr> ret;
+ return ret;
}
IceInternal::TransceiverPtr
@@ -278,10 +279,23 @@ IceSSL::EndpointI::serverTransceiver(IceInternal::EndpointIPtr& endp) const
return 0;
}
-IceInternal::ConnectorPtr
-IceSSL::EndpointI::connector() const
+vector<IceInternal::ConnectorPtr>
+IceSSL::EndpointI::connectors() const
{
- return new ConnectorI(_instance, _host, _port);
+ vector<IceInternal::ConnectorPtr> connectors;
+ vector<string> hosts = IceInternal::getHosts(_host);
+ if(hosts.size() > 1)
+ {
+ for(unsigned int i = 0; i < hosts.size(); ++i)
+ {
+ connectors.push_back(new ConnectorI(_instance, hosts[i], _port));
+ }
+ }
+ else
+ {
+ connectors.push_back(new ConnectorI(_instance, _host, _port));
+ }
+ return connectors;
}
IceInternal::AcceptorPtr
diff --git a/cpp/src/IceSSL/EndpointI.h b/cpp/src/IceSSL/EndpointI.h
index 3aea7133ae8..1d842f2e345 100644
--- a/cpp/src/IceSSL/EndpointI.h
+++ b/cpp/src/IceSSL/EndpointI.h
@@ -38,9 +38,9 @@ public:
virtual bool datagram() const;
virtual bool secure() const;
virtual bool unknown() const;
- virtual IceInternal::TransceiverPtr clientTransceiver() const;
+ virtual std::vector<IceInternal::TransceiverPtr> clientTransceivers() const;
virtual IceInternal::TransceiverPtr serverTransceiver(IceInternal::EndpointIPtr&) const;
- virtual IceInternal::ConnectorPtr connector() const;
+ virtual std::vector<IceInternal::ConnectorPtr> connectors() const;
virtual IceInternal::AcceptorPtr acceptor(IceInternal::EndpointIPtr&, const std::string&) const;
virtual std::vector<IceInternal::EndpointIPtr> expand(bool) const;
virtual bool publish() const;