diff options
Diffstat (limited to 'cpp/src/IcePack/Forward.cpp')
-rw-r--r-- | cpp/src/IcePack/Forward.cpp | 106 |
1 files changed, 101 insertions, 5 deletions
diff --git a/cpp/src/IcePack/Forward.cpp b/cpp/src/IcePack/Forward.cpp index fac3185e7f8..ed8b2178307 100644 --- a/cpp/src/IcePack/Forward.cpp +++ b/cpp/src/IcePack/Forward.cpp @@ -11,6 +11,7 @@ #include <Ice/Ice.h> #include <IcePack/Forward.h> #include <IcePack/Admin.h> +#include <sstream> using namespace std; using namespace Ice; @@ -32,15 +33,110 @@ IcePack::Forward::~Forward() ObjectPtr IcePack::Forward::locate(const ObjectAdapterPtr& adapter, const string& identity, ObjectPtr&) { + // + // Look up the server description + // ObjectPrx proxy = adapter->identityToProxy(identity); ServerDescriptionPtr desc = _admin->find(proxy); - if (desc) + + // + // If we didn't find a server description, we return null, meaning + // that the client will get an "object not exist" exception. + // + if (!desc) { - assert(desc->object); - _activator->activate(desc); - throw LocationForward(desc->object); + return 0; + } + + // + // We only try to activate if we have a path for the server + // + if (!desc->path.empty()) + { + try + { + bool doSleep = false; + int count = 0; + while (true) + { + try + { + // + // Activate the server. If the server is already + // running, this operation does nothing. + // + if (_activator->activate(desc)) + { + // + // If we just activated the server, we sleep + // below, to give the server some time to + // start up. + // + doSleep = true; + } + + if (doSleep) + { + sleep(1); // TODO: Make sleep time configurable + } + + // + // Try to ping the server, to make sure that it is + // really running. Note that even if activate() + // above returns false, i.e., if activate() + // indicates that the server was already running, + // it's still possible that the server shut down + // in the meantime, for example, because of a + // server timeout, a crash, or an explicit + // shutdown method. + // + proxy->_ping(); + + // + // Everything ok, the server is now up and + // running. The ping above also has the effect + // that the server idle timeout (if set) has been + // reset. If we wouldn't ping, there would be a + // higher chance that the server shuts down + // because of an idle timeout while we send back + // the location forward to the client. + // + break; + } + catch(const SocketException&) + { + // + // Ooops, we got a socket exception while trying + // to ping the server. Let's set the doSleep flag + // to give the server more time before we try + // again. + // + // TODO: Make number of retries configurable, + // ideally in Ice itself. + // + if (++count >= 10) + { + throw; + } + + doSleep = true; + } + } + } + catch(const LocalException& ex) + { + // + // If we get an exception, all we an do is to log it and + // to send a location forward to the client, which will + // then get a similar exception. + // + ostringstream s; + s << "exception during server activation:\n" << ex; + _communicator->getLogger()->error(s.str()); + } } - return 0; + + throw LocationForward(desc->object); } void |