summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/demo/Glacier2/callback/Client.cpp118
-rwxr-xr-xcpp/demo/Glacier2/callback/expect.py4
-rw-r--r--cpp/include/Glacier2/Application.h222
-rw-r--r--cpp/include/Ice/Application.h36
-rw-r--r--cpp/src/Glacier2/Application.cpp426
-rw-r--r--cpp/src/Glacier2/Makefile3
-rw-r--r--cpp/src/Glacier2/Makefile.mak5
-rw-r--r--cpp/src/Ice/Application.cpp194
8 files changed, 820 insertions, 188 deletions
diff --git a/cpp/demo/Glacier2/callback/Client.cpp b/cpp/demo/Glacier2/callback/Client.cpp
index 4c1416db640..4c744819014 100644
--- a/cpp/demo/Glacier2/callback/Client.cpp
+++ b/cpp/demo/Glacier2/callback/Client.cpp
@@ -10,44 +10,20 @@
#include <IceUtil/IceUtil.h>
#include <Ice/Ice.h>
#include <Glacier2/Router.h>
+#include <Glacier2/Application.h>
#include <CallbackI.h>
using namespace std;
using namespace Demo;
-class PingTask : public IceUtil::TimerTask
-{
-public:
-
- PingTask(const Glacier2::RouterPrx& router) :
- _router(router)
- {
- }
-
- virtual void runTimerTask()
- {
- try
- {
- _router->refreshSession();
- }
- catch(const Ice::Exception&)
- {
- // Ignore
- }
- }
-
-private:
-
- const Glacier2::RouterPrx _router;
-};
-
-class CallbackClient : public Ice::Application
+class CallbackClient : public Glacier2::Application
{
public:
CallbackClient();
-
- virtual int run(int, char*[]);
+
+ virtual int runWithSession(int, char**);
+ virtual Glacier2::SessionPrx createSession();
};
int
@@ -78,34 +54,15 @@ CallbackClient::CallbackClient() :
// Since this is an interactive demo we don't want any signal
// handling.
//
- Ice::Application(Ice::NoSignalHandling)
+ Glacier2::Application(Ice::NoSignalHandling)
{
}
-int
-CallbackClient::run(int argc, char* argv[])
+Glacier2::SessionPrx
+CallbackClient::createSession()
{
- if(argc > 1)
- {
- cerr << appName() << ": too many arguments" << endl;
- return EXIT_FAILURE;
- }
-
- Ice::RouterPrx defaultRouter = communicator()->getDefaultRouter();
- if(!defaultRouter)
- {
- cerr << argv[0] << ": no default router set" << endl;
- return EXIT_FAILURE;
- }
-
- Glacier2::RouterPrx router = Glacier2::RouterPrx::checkedCast(defaultRouter);
- if(!router)
- {
- cerr << argv[0] << ": configured router is not a Glacier2 router" << endl;
- return EXIT_FAILURE;
- }
-
- while(true)
+ Glacier2::SessionPrx session;
+ while(true)
{
cout << "This demo accepts any user-id / password combination.\n";
@@ -122,21 +79,32 @@ CallbackClient::run(int argc, char* argv[])
#if defined(__BCPLUSPLUS__) && (__BCPLUSPLUS__ >= 0x0600)
IceUtil::DummyBCC dummy;
#endif
- router->createSession(id, pw);
+ router()->createSession(id, pw);
break;
}
catch(const Glacier2::PermissionDeniedException& ex)
{
cout << "permission denied:\n" << ex.reason << endl;
}
+ catch(const Glacier2::CannotCreateSessionException ex)
+ {
+ cout << "cannot create session:\n" << ex.reason << endl;
+ }
}
+ return session;
+}
- IceUtil::TimerPtr timer = new IceUtil::Timer();
- timer->scheduleRepeated(new PingTask(router), IceUtil::Time::milliSeconds(router->getSessionTimeout() * 500));
+int
+CallbackClient::runWithSession(int argc, char* argv[])
+{
+ if(argc > 1)
+ {
+ cerr << appName() << ": too many arguments" << endl;
+ return EXIT_FAILURE;
+ }
- Ice::Identity callbackReceiverIdent;
- callbackReceiverIdent.name = "callbackReceiver";
- callbackReceiverIdent.category = router->getCategoryForClient();
+ Ice::Identity callbackReceiverIdent = createCallbackIdentity("callbackReceiver");
+
Ice::Identity callbackReceiverFakeIdent;
callbackReceiverFakeIdent.name = "callbackReceiver";
callbackReceiverFakeIdent.category = "fake";
@@ -146,12 +114,13 @@ CallbackClient::run(int argc, char* argv[])
CallbackPrx oneway = CallbackPrx::uncheckedCast(twoway->ice_oneway());
CallbackPrx batchOneway = CallbackPrx::uncheckedCast(twoway->ice_batchOneway());
- Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapterWithRouter("Callback.Client", defaultRouter);
- adapter->add(new CallbackReceiverI, callbackReceiverIdent);
- adapter->add(new CallbackReceiverI, callbackReceiverFakeIdent); // Should never be called for the fake identity.
- adapter->activate();
+ objectAdapter()->add(new CallbackReceiverI, callbackReceiverIdent);
+
+ // Should never be called for the fake identity.
+ objectAdapter()->add(new CallbackReceiverI, callbackReceiverFakeIdent);
- CallbackReceiverPrx twowayR = CallbackReceiverPrx::uncheckedCast(adapter->createProxy(callbackReceiverIdent));
+ CallbackReceiverPrx twowayR = CallbackReceiverPrx::uncheckedCast(
+ objectAdapter()->createProxy(callbackReceiverIdent));
CallbackReceiverPrx onewayR = CallbackReceiverPrx::uncheckedCast(twowayR->ice_oneway());
string override;
@@ -256,27 +225,6 @@ CallbackClient::run(int argc, char* argv[])
}
while(cin.good() && c != 'x');
- //
- // Destroy the timer before the router session is destroyed,
- // otherwise it might get a spurious ObjectNotExistException.
- //
- timer->destroy();
-
- try
- {
- router->destroySession();
- }
- catch(const Glacier2::SessionNotExistException& ex)
- {
- cerr << ex << endl;
- }
- catch(const Ice::ConnectionLostException&)
- {
- //
- // Expected: the router closed the connection.
- //
- }
-
return EXIT_SUCCESS;
}
diff --git a/cpp/demo/Glacier2/callback/expect.py b/cpp/demo/Glacier2/callback/expect.py
index 7085c18ada9..bebd86b2115 100755
--- a/cpp/demo/Glacier2/callback/expect.py
+++ b/cpp/demo/Glacier2/callback/expect.py
@@ -24,8 +24,6 @@ from demoscript.Glacier2 import callback
server = Util.spawn('./server --Ice.PrintAdapterReady')
server.expect('.* ready')
-sessionserver = Util.spawn('./sessionserver --Ice.PrintAdapterReady')
-sessionserver.expect('.* ready')
glacier2 = Util.spawn('glacier2router --Ice.Config=config.glacier2 --Ice.PrintAdapterReady --Glacier2.SessionTimeout=5')
glacier2.expect('Glacier2.Client ready')
@@ -33,4 +31,4 @@ glacier2.expect('Glacier2.Server ready')
client = Util.spawn('./client')
-callback.run(client, server, sessionserver, glacier2)
+callback.run(client, server, glacier2)
diff --git a/cpp/include/Glacier2/Application.h b/cpp/include/Glacier2/Application.h
new file mode 100644
index 00000000000..6519ce7cc88
--- /dev/null
+++ b/cpp/include/Glacier2/Application.h
@@ -0,0 +1,222 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 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.
+//
+// **********************************************************************
+
+#include <exception>
+
+#include <Ice/Application.h>
+
+#include <Glacier2/Session.h>
+#include <Glacier2/Router.h>
+
+namespace Glacier2
+{
+
+/**
+ *
+ * This exception is raised if the session should be restarted.
+ *
+ **/
+class GLACIER2_API RestartSessionException : public IceUtil::Exception
+{
+public:
+
+ virtual std::string ice_name() const;
+ virtual Exception* ice_clone() const;
+ virtual void ice_throw() const;
+};
+
+/**
+ * An extension of Ice.Application that makes it easy to write
+ * Glacier2 applications.
+ *
+ * <p> Applications must create a derived class that implements the
+ * {@link #createSession} and {@link #runWithSession} methods.<p>
+ *
+ * The base class invokes {@link #createSession} to create a new
+ * Glacier2 session and then invokes {@link #runWithSession} in
+ * which the subclass performs its application logic. The base class
+ * automatically destroys the session when {@link #runWithSession}
+ * returns.
+ *
+ * If {@link #runWithSession} calls {@link #restart} or raises any of
+ * the exceptions Ice.ConnectionRefusedException,
+ * Ice.ConnectionLostException, Ice.UnknownLocalException,
+ * Ice.RequestFailedException, or Ice.TimeoutException, the base
+ * class destroys the current session and restarts the application
+ * with another call to {@link #createSession} followed by
+ * {@link #runWithSession}.
+ *
+ * The application can optionally override the {@link #sessionDestroyed}
+ * callback method if it needs to take action when connectivity with
+ * the Glacier2 router is lost.
+ *
+ * A program can contain only one instance of this class.
+ *
+ * @see Ice.Application
+ * @see Glacier2.Router
+ * @see Glacier2.Session
+ * @see Ice.Communicator
+ * @see Ice.Logger
+ * @see #runWithSession
+ **/
+
+class GLACIER2_API Application : public Ice::Application
+{
+ /**
+ * Initializes an instance that calls {@link Communicator#shutdown} if
+ * a signal is received.
+ **/
+public:
+
+ Application()
+ {
+ }
+
+ /**
+ * Initializes an instance that handles signals according to the signal
+ * policy.
+ *
+ * @param signalPolicy Determines how to respond to signals.
+ *
+ * @see SignalPolicy
+ **/
+ Application(Ice::SignalPolicy signalPolicy) : Ice::Application(signalPolicy)
+ {
+ }
+
+
+ /**
+ * Called once the communicator has been initialized and the Glacier2 session
+ * has been established. A derived class must implement <code>runWithSession</code>,
+ * which is the application's starting method.
+ *
+ * @param argc The number of elements in argv.
+ *
+ * @param argv The argument vector for the application. <code>Application</code>
+ * scans the argument vector passed to <code>main</code> for options that are
+ * specific to the Ice run time and removes them; therefore, the vector passed
+ * to <code>run</code> is free from Ice-related options and contains only options
+ * and arguments that are application-specific.
+ *
+ * @return The <code>runWithSession</code> method should return zero for successful
+ * termination, and non-zero otherwise. <code>Application.main</code> returns the
+ * value returned by <code>runWithSession</code>.
+ **/
+ virtual int runWithSession(int argc, char* argv[]) = 0;
+
+
+ /**
+ * Creates a new Glacier2 session. A call to
+ * <code>createSession</code> always precedes a call to
+ * <code>runWithSession</code>. If <code>Ice.LocalException</code>
+ * is thrown from this method, the application is terminated.
+
+ * @return The Glacier2 session.
+ **/
+ virtual Glacier2::SessionPrx createSession() = 0;
+
+ /**
+ * Called to restart the application's Glacier2 session. This
+ * method never returns.
+ *
+ * @throws RestartSessionException This exception is always thrown.
+ **/
+ void restart()
+ {
+ RestartSessionException ex;
+ throw ex;
+ }
+
+ /**
+ * Called when the base class detects that the session has been destroyed.
+ * A subclass can override this method to take action after the loss of
+ * connectivity with the Glacier2 router.
+ **/
+ virtual void sessionDestroyed()
+ {
+ }
+
+ /**
+ * Returns the Glacier2 router proxy
+ * @return The router proxy.
+ **/
+ static Glacier2::RouterPrx router()
+ {
+ return _router;
+ }
+
+ /**
+ * Returns the Glacier2 session proxy
+ * @return The session proxy.
+ **/
+ static Glacier2::SessionPrx session()
+ {
+ return _session;
+ }
+
+ /**
+ * Returns the category to be used in the identities of all of the client's
+ * callback objects. Clients must use this category for the router to
+ * forward callback requests to the intended client.
+ * @return The category.
+ * @throws SessionNotExistException No session exists.
+ **/
+ std::string categoryForClient();
+
+
+ /**
+ * Create a new Ice identity for callback objects with the given
+ * identity name field.
+ * @return The identity.
+ **/
+ Ice::Identity createCallbackIdentity(const std::string&);
+
+ /**
+ * Adds a servant to the callback object adapter's Active Servant Map with a UUID.
+ * @param servant The servant to add.
+ * @return The proxy for the servant.
+ **/
+ Ice::ObjectPrx addWithUUID(const Ice::ObjectPtr& servant);
+
+ /**
+ * Creates an object adapter for callback objects.
+ * @return The object adapter.
+ */
+ Ice::ObjectAdapterPtr objectAdapter();
+
+protected:
+
+ virtual int
+ doMain(int, char*[], const Ice::InitializationData& initData);
+
+private:
+
+ bool
+ doMain(Ice::StringSeq&, const Ice::InitializationData&, int&);
+
+ /**
+ * Run should not be overridden for Glacier2.Application. Instead
+ * <code>runWithSession</code> should be used.
+ */
+ int run(int, char**)
+ {
+ // This shouldn't be called.
+ assert(false);
+ return 0;
+ }
+
+
+ static Ice::ObjectAdapterPtr _adapter;
+ static Glacier2::RouterPrx _router;
+ static Glacier2::SessionPrx _session;
+ static bool _createdSession;
+};
+
+}
+
diff --git a/cpp/include/Ice/Application.h b/cpp/include/Ice/Application.h
index 1ffc86572e4..f8ac4ebae9b 100644
--- a/cpp/include/Ice/Application.h
+++ b/cpp/include/Ice/Application.h
@@ -12,10 +12,40 @@
#include <Ice/Ice.h>
+#include <IceUtil/Mutex.h>
+
+
namespace Ice
{
+ enum SignalPolicy { HandleSignals, NoSignalHandling } ;
+ class Application;
+}
-enum SignalPolicy { HandleSignals, NoSignalHandling } ;
+namespace IceInternal
+{
+ extern ICE_API IceUtil::Mutex* mutex;
+ extern ICE_API std::auto_ptr<IceUtil::Cond> _condVar;
+
+ //
+ // Variables than can change while run() and communicator->destroy() are running!
+ //
+ extern ICE_API bool _callbackInProgress;
+ extern ICE_API bool _destroyed;
+ extern ICE_API bool _interrupted;
+
+ //
+ // Variables that are immutable during run() and until communicator->destroy() has returned;
+ // before and after run(), and once communicator->destroy() has returned, we assume that
+ // only the main thread and CtrlCHandler threads are running.
+ //
+ extern ICE_API std::string _appName;
+ extern ICE_API Ice::CommunicatorPtr _communicator;
+ extern ICE_API Ice::SignalPolicy _signalPolicy;
+ extern ICE_API Ice::Application* _application;
+}
+
+namespace Ice
+{
class ICE_API Application : private IceUtil::noncopyable
{
@@ -96,9 +126,9 @@ public:
//
static bool interrupted();
-private:
+protected:
- int mainInternal(int, char*[], const Ice::InitializationData&);
+ virtual int doMain(int, char*[], const Ice::InitializationData&);
#if defined(__SUNPRO_CC)
//
diff --git a/cpp/src/Glacier2/Application.cpp b/cpp/src/Glacier2/Application.cpp
new file mode 100644
index 00000000000..ac5b1dd9f8a
--- /dev/null
+++ b/cpp/src/Glacier2/Application.cpp
@@ -0,0 +1,426 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2009 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.
+//
+// **********************************************************************
+
+#include <Glacier2/Application.h>
+#include <IceUtil/IceUtil.h>
+#include <IceUtil/ArgVector.h>
+
+using namespace std;
+using namespace Ice;
+
+Ice::ObjectAdapterPtr Glacier2::Application::_adapter;
+Glacier2::RouterPrx Glacier2::Application::_router;
+Glacier2::SessionPrx Glacier2::Application::_session;
+bool Glacier2::Application::_createdSession = false;
+
+namespace
+{
+
+class SessionPingThread : virtual public IceUtil::Shared
+{
+
+public:
+
+ virtual void done() = 0;
+};
+typedef IceUtil::Handle<SessionPingThread> SessionPingThreadPtr;
+
+class AMI_Router_refreshSessionI : public Glacier2::AMI_Router_refreshSession
+{
+
+public:
+
+ AMI_Router_refreshSessionI(Glacier2::Application* app, const SessionPingThreadPtr& pinger) :
+ _app(app),
+ _pinger(pinger)
+ {
+ }
+
+ void
+ ice_response()
+ {
+ }
+
+ void
+ ice_exception(const Ice::Exception& ex)
+ {
+ // Here the session has gone. The thread
+ // terminates, and we notify the
+ // application that the session has been
+ // destroyed.
+ _pinger->done();
+ _app->sessionDestroyed();
+ }
+
+private:
+
+ Glacier2::Application* _app;
+ SessionPingThreadPtr _pinger;
+};
+
+class SessionPingThreadI : virtual public IceUtil::Thread, virtual public SessionPingThread
+{
+
+public:
+
+ SessionPingThreadI(Glacier2::Application* app, const Glacier2::RouterPrx& router, long period) :
+ _app(app),
+ _router(router),
+ _period(period),
+ _done(false)
+ {
+ }
+
+ void
+ run()
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_monitor);
+ while(true)
+ {
+ _router->refreshSession_async(new AMI_Router_refreshSessionI(_app, this));
+
+ if(!_done)
+ {
+ _monitor.timedWait(IceUtil::Time::seconds((int)_period));
+ }
+ if(_done)
+ {
+ break;
+ }
+ }
+ }
+
+ void
+ done()
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock lock(_monitor);
+ if(!_done)
+ {
+ _done = true;
+ _monitor.notify();
+ }
+ }
+
+private:
+
+ Glacier2::Application* _app;
+ Glacier2::RouterPrx _router;
+ long _period;
+ bool _done;
+ IceUtil::Monitor<IceUtil::Mutex> _monitor;
+};
+typedef IceUtil::Handle<SessionPingThreadI> SessionPingThreadIPtr;
+
+}
+
+string
+Glacier2::RestartSessionException::ice_name() const
+{
+ return "RestartSessionException";
+}
+
+Exception*
+Glacier2::RestartSessionException::ice_clone() const
+{
+ return new RestartSessionException(*this);
+}
+
+void
+Glacier2::RestartSessionException::ice_throw() const
+{
+ throw *this;
+}
+
+Ice::ObjectAdapterPtr
+Glacier2::Application::objectAdapter()
+{
+ if(!_adapter)
+ {
+ // TODO: Depending on the resolution of
+ // http://bugzilla/bugzilla/show_bug.cgi?id=4264 the OA
+ // name could be an empty string.
+ _adapter = communicator()->createObjectAdapterWithRouter(IceUtil::generateUUID(), router());
+ _adapter->activate();
+ }
+ return _adapter;
+}
+
+Ice::ObjectPrx
+Glacier2::Application::addWithUUID(const Ice::ObjectPtr& servant)
+{
+ return objectAdapter()->add(servant, createCallbackIdentity(IceUtil::generateUUID()));
+}
+
+Ice::Identity
+Glacier2::Application::createCallbackIdentity(const string& name)
+{
+ Ice::Identity id;
+ id.name = name;
+ id.category = categoryForClient();
+ return id;
+}
+
+std::string
+Glacier2::Application::categoryForClient()
+{
+ if(!_router)
+ {
+ SessionNotExistException ex;
+ throw ex;
+ }
+ return router()->getCategoryForClient();
+}
+
+int
+Glacier2::Application::doMain(int argc, char* argv[], const Ice::InitializationData& initData)
+{
+ // Set the default properties for all Glacier2 applications.
+ initData.properties->setProperty("Ice.ACM.Client", "0");
+ initData.properties->setProperty("Ice.RetryIntervals", "-1");
+
+ bool restart;
+ int ret = 0;
+ do
+ {
+ // A copy of the initialization data and the string seq
+ // needs to be passed to doMainInternal, as these can be
+ // changed by the application.
+ Ice::InitializationData id(initData);
+ id.properties = id.properties->clone();
+ Ice::StringSeq args = Ice::argsToStringSeq(argc, argv);
+
+ restart = doMain(args, id, ret);
+ }
+ while(restart);
+ return ret;
+}
+
+bool
+Glacier2::Application::doMain(Ice::StringSeq& args, const Ice::InitializationData& initData, int& status)
+{
+ // Reset internal state variables from Ice.Application. The
+ // remainder are reset at the end of this method.
+ IceInternal::_callbackInProgress = false;
+ IceInternal::_destroyed = false;
+ IceInternal::_interrupted = false;
+
+ bool restart = false;
+ status = 0;
+
+ SessionPingThreadIPtr ping;
+ try
+ {
+ IceInternal::_communicator = Ice::initialize(args, initData);
+ _router = Glacier2::RouterPrx::uncheckedCast(communicator()->getDefaultRouter());
+
+ if(!_router)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": no glacier2 router configured";
+ status = 1;
+ }
+ else
+ {
+ //
+ // The default is to destroy when a signal is received.
+ //
+ if(IceInternal::_signalPolicy == Ice::HandleSignals)
+ {
+ destroyOnInterrupt();
+ }
+
+ // If createSession throws, we're done.
+ try
+ {
+ _session = createSession();
+ _createdSession = true;
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ status = 1;
+ }
+
+ if(_createdSession)
+ {
+ ping = new SessionPingThreadI(this, _router, (long)_router->getSessionTimeout() / 2);
+ ping->start();
+ IceUtilInternal::ArgVector a(args);
+ status = runWithSession(a.argc, a.argv);
+ }
+ }
+ }
+ // We want to restart on those exceptions which indicate a
+ // break down in communications, but not those exceptions that
+ // indicate a programming logic error (ie: marshal, protocol
+ // failure, etc).
+ catch(const RestartSessionException&)
+ {
+ restart = true;
+ }
+ catch(const Ice::ConnectionRefusedException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ restart = true;
+ }
+ catch(const Ice::ConnectionLostException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ restart = true;
+ }
+ catch(const Ice::UnknownLocalException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ restart = true;
+ }
+ catch(const Ice::RequestFailedException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ restart = true;
+ }
+ catch(const Ice::TimeoutException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ restart = true;
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ status = 1;
+ }
+ catch(const std::exception& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": std::exception " << ex;
+ status = 1;
+ }
+ catch(const std::string& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": c++ exception " << ex;
+ status = 1;
+ }
+ catch(const char* ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": char* exception " << ex;
+ status = 1;
+ }
+ catch(...)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": unknow exception ";
+ status = 1;
+ }
+
+ //
+ // Don't want any new interrupt and at this point (post-run),
+ // it would not make sense to release a held signal to run
+ // shutdown or destroy.
+ //
+ if(IceInternal::_signalPolicy == HandleSignals)
+ {
+ ignoreInterrupt();
+ }
+
+ {
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ while(IceInternal::_callbackInProgress)
+ {
+ IceInternal::_condVar->wait(lock);
+ }
+ if(IceInternal::_destroyed)
+ {
+ IceInternal::_communicator = 0;
+ }
+ else
+ {
+ IceInternal::_destroyed = true;
+ //
+ // And _communicator != 0, meaning will be destroyed
+ // next, _destroyed = true also ensures that any
+ // remaining callback won't do anything
+ //
+ }
+ IceInternal::_application = 0;
+ }
+
+ if(!ping)
+ {
+ ping->done();
+ while(true)
+ {
+ ping->getThreadControl().join();
+ break;
+ }
+ ping = 0;
+ }
+
+ if(_createdSession && _router)
+ {
+ try
+ {
+ _router->destroySession();
+ }
+ catch(const Ice::ConnectionLostException&)
+ {
+ // Expected: the router closed the connection.
+ }
+ catch(const Glacier2::SessionNotExistException&)
+ {
+ // This can also occur.
+ }
+ catch(const exception& ex)
+ {
+ // Not expected.
+ Error out(getProcessLogger());
+ out << "unexpected exception when destroying the session " << ex;
+ }
+ _router = 0;
+ }
+
+ if(IceInternal::_communicator)
+ {
+ try
+ {
+ IceInternal::_communicator->destroy();
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ Error out(getProcessLogger());
+ out << IceInternal::_appName << ": " << ex;
+ status = 1;
+ }
+ catch(const exception& ex)
+ {
+ Error out(getProcessLogger());
+ out << "unknown exception " << ex;
+ status = 1;
+ }
+ IceInternal::_communicator = 0;
+ }
+
+
+ // Reset internal state. We cannot reset the Application state
+ // here, since _destroyed must remain true until we re-run
+ // this method.
+ _adapter = 0;
+ _router = 0;
+ _session = 0;
+ _createdSession = false;
+
+ return restart;
+}
diff --git a/cpp/src/Glacier2/Makefile b/cpp/src/Glacier2/Makefile
index f936fc95556..db08d6d3dda 100644
--- a/cpp/src/Glacier2/Makefile
+++ b/cpp/src/Glacier2/Makefile
@@ -21,7 +21,8 @@ TARGETS = $(LIBTARGETS) $(ROUTER)
OBJS = PermissionsVerifier.o \
Router.o \
SSLInfo.o \
- Session.o
+ Session.o \
+ Application.o
ROBJS = Blobject.o \
ClientBlobject.o \
diff --git a/cpp/src/Glacier2/Makefile.mak b/cpp/src/Glacier2/Makefile.mak
index 4d6b204ed0b..1243667d97a 100644
--- a/cpp/src/Glacier2/Makefile.mak
+++ b/cpp/src/Glacier2/Makefile.mak
@@ -19,7 +19,8 @@ TARGETS = $(LIBNAME) $(DLLNAME) $(ROUTER)
OBJS = PermissionsVerifier.obj \
Router.obj \
SSLInfo.obj \
- Session.obj
+ Session.obj \
+ Application.obj
ROBJS = Blobject.obj \
ClientBlobject.obj \
@@ -43,7 +44,7 @@ SDIR = $(slicedir)\Glacier2
!include $(top_srcdir)\config\Make.rules.mak
-CPPFLAGS = -I.. $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+CPPFLAGS = -I.. $(CPPFLAGS) -DGLACIER2_API_EXPORTS -DWIN32_LEAN_AND_MEAN
LINKWITH = $(LIBS) $(OPENSSL_LIBS) glacier2$(LIBSUFFIX).lib icessl$(LIBSUFFIX).lib
!if "$(BCPLUSPLUS)" != "yes"
LINKWITH = $(LINKWITH) ws2_32.lib
diff --git a/cpp/src/Ice/Application.cpp b/cpp/src/Ice/Application.cpp
index bf256c66f27..c7e41882fee 100644
--- a/cpp/src/Ice/Application.cpp
+++ b/cpp/src/Ice/Application.cpp
@@ -21,6 +21,21 @@ using namespace Ice;
using namespace IceUtil;
using namespace IceUtilInternal;
+
+//
+// static initializations.
+//
+Mutex* IceInternal::mutex = 0;
+
+bool IceInternal::_callbackInProgress = false;
+bool IceInternal::_destroyed = false;
+bool IceInternal::_interrupted = false;
+
+string IceInternal::_appName;
+CommunicatorPtr IceInternal::_communicator;
+SignalPolicy IceInternal::_signalPolicy = HandleSignals;
+auto_ptr<Cond> IceInternal::_condVar;
+Ice::Application* IceInternal::_application;
//
// _mutex and _condVar are used to synchronize the main thread and
// the CtrlCHandler thread
@@ -29,34 +44,29 @@ using namespace IceUtilInternal;
namespace
{
-Mutex* mutex = 0;
-
class Init
{
public:
Init()
{
- mutex = new IceUtil::Mutex;
+ IceInternal::mutex = new IceUtil::Mutex;
}
~Init()
{
- delete mutex;
- mutex = 0;
+ delete IceInternal::mutex;
+ IceInternal::mutex = 0;
}
};
Init init;
-auto_ptr<Cond> _condVar;
+
//
// Variables than can change while run() and communicator->destroy() are running!
//
-bool _callbackInProgress = false;
-bool _destroyed = false;
-bool _interrupted = false;
bool _released = false;
CtrlCHandlerCallback _previousCallback = 0;
@@ -65,12 +75,8 @@ CtrlCHandlerCallback _previousCallback = 0;
// before and after run(), and once communicator->destroy() has returned, we assume that
// only the main thread and CtrlCHandler threads are running.
//
-string _appName;
-Application* _application;
-CommunicatorPtr _communicator;
CtrlCHandler* _ctrlCHandler = 0;
bool _nohup = false;
-SignalPolicy _signalPolicy = HandleSignals;
}
@@ -97,13 +103,13 @@ holdInterruptCallback(int signal)
{
CtrlCHandlerCallback callback = 0;
{
- IceUtil::Mutex::Lock lock(*mutex);
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
while(!_released)
{
- _condVar->wait(lock);
+ IceInternal::_condVar->wait(lock);
}
- if(_destroyed)
+ if(IceInternal::_destroyed)
{
//
// Being destroyed by main thread
@@ -124,8 +130,8 @@ static void
destroyOnInterruptCallback(int signal)
{
{
- IceUtil::Mutex::Lock lock(*mutex);
- if(_destroyed)
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ if(IceInternal::_destroyed)
{
//
// Being destroyed by main thread
@@ -137,16 +143,16 @@ destroyOnInterruptCallback(int signal)
return;
}
- assert(!_callbackInProgress);
- _callbackInProgress = true;
- _interrupted = true;
- _destroyed = true;
+ assert(!IceInternal::_callbackInProgress);
+ IceInternal::_callbackInProgress = true;
+ IceInternal::_interrupted = true;
+ IceInternal::_destroyed = true;
}
try
{
- assert(_communicator != 0);
- _communicator->destroy();
+ assert(IceInternal::_communicator != 0);
+ IceInternal::_communicator->destroy();
}
catch(const std::exception& ex)
{
@@ -170,18 +176,18 @@ destroyOnInterruptCallback(int signal)
}
{
- IceUtil::Mutex::Lock lock(*mutex);
- _callbackInProgress = false;
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ IceInternal::_callbackInProgress = false;
}
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
static void
shutdownOnInterruptCallback(int signal)
{
{
- IceUtil::Mutex::Lock lock(*mutex);
- if(_destroyed)
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ if(IceInternal::_destroyed)
{
//
// Being destroyed by main thread
@@ -193,15 +199,15 @@ shutdownOnInterruptCallback(int signal)
return;
}
- assert(!_callbackInProgress);
- _callbackInProgress = true;
- _interrupted = true;
+ assert(!IceInternal::_callbackInProgress);
+ IceInternal::_callbackInProgress = true;
+ IceInternal::_interrupted = true;
}
try
{
- assert(_communicator != 0);
- _communicator->shutdown();
+ assert(IceInternal::_communicator != 0);
+ IceInternal::_communicator->shutdown();
}
catch(const std::exception& ex)
{
@@ -225,18 +231,18 @@ shutdownOnInterruptCallback(int signal)
}
{
- IceUtil::Mutex::Lock lock(*mutex);
- _callbackInProgress = false;
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ IceInternal::_callbackInProgress = false;
}
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
static void
callbackOnInterruptCallback(int signal)
{
{
- IceUtil::Mutex::Lock lock(*mutex);
- if(_destroyed)
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ if(IceInternal::_destroyed)
{
//
// Being destroyed by main thread
@@ -245,15 +251,15 @@ callbackOnInterruptCallback(int signal)
}
// For SIGHUP the user callback is always called. It can
// decide what to do.
- assert(!_callbackInProgress);
- _callbackInProgress = true;
- _interrupted = true;
+ assert(!IceInternal::_callbackInProgress);
+ IceInternal::_callbackInProgress = true;
+ IceInternal::_interrupted = true;
}
try
{
- assert(_application != 0);
- _application->interruptCallback(signal);
+ assert(IceInternal::_application != 0);
+ IceInternal::_application->interruptCallback(signal);
}
catch(const std::exception& ex)
{
@@ -277,15 +283,15 @@ callbackOnInterruptCallback(int signal)
}
{
- IceUtil::Mutex::Lock lock(*mutex);
- _callbackInProgress = false;
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ IceInternal::_callbackInProgress = false;
}
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
Ice::Application::Application(SignalPolicy signalPolicy)
{
- _signalPolicy = signalPolicy;
+ IceInternal::_signalPolicy = signalPolicy;
}
Ice::Application::~Application()
@@ -342,7 +348,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
setProcessLogger(new LoggerI(argv[0], ""));
}
- if(_communicator != 0)
+ if(IceInternal::_communicator != 0)
{
Error out(getProcessLogger());
out << "only one instance of the Application class can be used";
@@ -350,7 +356,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
}
int status;
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
try
{
@@ -361,7 +367,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
CtrlCHandler ctrCHandler;
_ctrlCHandler = &ctrCHandler;
- status = mainInternal(argc, argv, initData);
+ status = doMain(argc, argv, initData);
//
// Set _ctrlCHandler to 0 only once communicator->destroy() has completed.
@@ -377,7 +383,7 @@ Ice::Application::main(int argc, char* argv[], const InitializationData& initDat
}
else
{
- status = mainInternal(argc, argv, initData);
+ status = doMain(argc, argv, initData);
}
return status;
@@ -412,27 +418,27 @@ Ice::Application::interruptCallback(int)
const char*
Ice::Application::appName()
{
- return _appName.c_str();
+ return IceInternal::_appName.c_str();
}
CommunicatorPtr
Ice::Application::communicator()
{
- return _communicator;
+ return IceInternal::_communicator;
}
void
Ice::Application::destroyOnInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
_released = true;
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
_ctrlCHandler->setCallback(destroyOnInterruptCallback);
}
@@ -447,15 +453,15 @@ Ice::Application::destroyOnInterrupt()
void
Ice::Application::shutdownOnInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
_released = true;
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
_ctrlCHandler->setCallback(shutdownOnInterruptCallback);
}
@@ -470,15 +476,15 @@ Ice::Application::shutdownOnInterrupt()
void
Ice::Application::ignoreInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
_released = true;
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
_ctrlCHandler->setCallback(0);
}
@@ -493,15 +499,15 @@ Ice::Application::ignoreInterrupt()
void
Ice::Application::callbackOnInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
_released = true;
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
_ctrlCHandler->setCallback(callbackOnInterruptCallback);
}
@@ -516,11 +522,11 @@ Ice::Application::callbackOnInterrupt()
void
Ice::Application::holdInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() != holdInterruptCallback)
{
_previousCallback = _ctrlCHandler->getCallback();
@@ -540,11 +546,11 @@ Ice::Application::holdInterrupt()
void
Ice::Application::releaseInterrupt()
{
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
if(_ctrlCHandler != 0)
{
- IceUtil::Mutex::Lock lock(*mutex); // we serialize all the interrupt-setting
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex); // we serialize all the interrupt-setting
if(_ctrlCHandler->getCallback() == holdInterruptCallback)
{
//
@@ -556,7 +562,7 @@ Ice::Application::releaseInterrupt()
_released = true;
_ctrlCHandler->setCallback(_previousCallback);
- _condVar->signal();
+ IceInternal::_condVar->signal();
}
// Else nothing to release.
}
@@ -571,24 +577,24 @@ Ice::Application::releaseInterrupt()
bool
Ice::Application::interrupted()
{
- IceUtil::Mutex::Lock lock(*mutex);
- return _interrupted;
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ return IceInternal::_interrupted;
}
int
-Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& initializationData)
+Ice::Application::doMain(int argc, char* argv[], const InitializationData& initializationData)
{
int status;
try
{
- if(_condVar.get() == 0)
+ if(IceInternal::_condVar.get() == 0)
{
- _condVar.reset(new Cond);
+ IceInternal::_condVar.reset(new Cond);
}
- _interrupted = false;
- _appName = argv[0] ? argv[0] : "";
+ IceInternal::_interrupted = false;
+ IceInternal::_appName = argv[0] ? argv[0] : "";
//
// We parse the properties here to extract Ice.ProgramName.
@@ -605,19 +611,19 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData&
setProcessLogger(new LoggerI(initData.properties->getProperty("Ice.ProgramName"), ""));
}
- _application = this;
- _communicator = initialize(argc, argv, initData);
- _destroyed = false;
+ IceInternal::_application = this;
+ IceInternal::_communicator = initialize(argc, argv, initData);
+ IceInternal::_destroyed = false;
//
// Used by destroyOnInterruptCallback and shutdownOnInterruptCallback.
//
- _nohup = (_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0);
+ _nohup = (IceInternal::_communicator->getProperties()->getPropertyAsInt("Ice.Nohup") > 0);
//
// The default is to destroy when a signal is received.
//
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
destroyOnInterrupt();
}
@@ -654,38 +660,38 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData&
// it would not make sense to release a held signal to run
// shutdown or destroy.
//
- if(_signalPolicy == HandleSignals)
+ if(IceInternal::_signalPolicy == HandleSignals)
{
ignoreInterrupt();
}
{
- IceUtil::Mutex::Lock lock(*mutex);
- while(_callbackInProgress)
+ IceUtil::Mutex::Lock lock(*IceInternal::mutex);
+ while(IceInternal::_callbackInProgress)
{
- _condVar->wait(lock);
+ IceInternal::_condVar->wait(lock);
}
- if(_destroyed)
+ if(IceInternal::_destroyed)
{
- _communicator = 0;
+ IceInternal::_communicator = 0;
}
else
{
- _destroyed = true;
+ IceInternal::_destroyed = true;
//
// And _communicator != 0, meaning will be destroyed
// next, _destroyed = true also ensures that any
// remaining callback won't do anything
//
}
- _application = 0;
+ IceInternal::_application = 0;
}
- if(_communicator != 0)
+ if(IceInternal::_communicator != 0)
{
try
{
- _communicator->destroy();
+ IceInternal::_communicator->destroy();
}
catch(const std::exception& ex)
{
@@ -699,7 +705,7 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData&
out << "unknown exception";
status = EXIT_FAILURE;
}
- _communicator = 0;
+ IceInternal::_communicator = 0;
}
return status;