diff options
-rw-r--r-- | cpp/include/Glacier2/SessionHelper.h | 4 | ||||
-rw-r--r-- | cpp/src/Glacier2Lib/Application.cpp | 66 | ||||
-rw-r--r-- | cpp/src/Glacier2Lib/SessionHelper.cpp | 121 | ||||
-rw-r--r-- | cs/src/Glacier2/Application.cs | 63 | ||||
-rw-r--r-- | cs/src/Glacier2/SessionFactoryHelper.cs | 35 | ||||
-rw-r--r-- | cs/src/Glacier2/SessionHelper.cs | 91 | ||||
-rw-r--r-- | distribution/src/windows/docs/thirdparty/README.txt | 2 | ||||
-rw-r--r-- | java/src/Glacier2/src/main/java/Glacier2/Application.java | 60 | ||||
-rw-r--r-- | java/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java | 29 | ||||
-rw-r--r-- | java/src/Glacier2/src/main/java/Glacier2/SessionHelper.java | 83 | ||||
-rw-r--r-- | py/python/Glacier2.py | 55 |
11 files changed, 210 insertions, 399 deletions
diff --git a/cpp/include/Glacier2/SessionHelper.h b/cpp/include/Glacier2/SessionHelper.h index 077801194b4..eeea0f53d5c 100644 --- a/cpp/include/Glacier2/SessionHelper.h +++ b/cpp/include/Glacier2/SessionHelper.h @@ -96,6 +96,9 @@ public: void setConnectContext(std::map<std::string, std::string> context); + void setUseCallbacks(bool); + bool getUseCallbacks() const; + SessionHelperPtr connect(); SessionHelperPtr connect(const std::string&, const std::string&); @@ -116,6 +119,7 @@ private: Ice::InitializationData _initData; SessionCallbackPtr _callback; std::map< std::string, std::string> _context; + bool _useCallbacks; }; typedef IceUtil::Handle<SessionFactoryHelper> SessionFactoryHelperPtr; diff --git a/cpp/src/Glacier2Lib/Application.cpp b/cpp/src/Glacier2Lib/Application.cpp index 637032959ea..2d6d28e4474 100644 --- a/cpp/src/Glacier2Lib/Application.cpp +++ b/cpp/src/Glacier2Lib/Application.cpp @@ -23,50 +23,6 @@ string Glacier2::Application::_category; namespace { -class SessionRefreshTask : public IceUtil::TimerTask -{ - -public: - - SessionRefreshTask(Glacier2::Application* app, const Glacier2::RouterPrx& router) : - _app(app), - _router(router) - { - _callback = Glacier2::newCallback_Router_refreshSession(this, &SessionRefreshTask::exception); - } - - void - exception(const Ice::Exception&) - { - // - // Here the session has been destroyed. Notify the application that the - // session has been destroyed. - // - _app->sessionDestroyed(); - } - - virtual void - runTimerTask() - { - try - { - _router->begin_refreshSession(_callback); - } - catch(const Ice::CommunicatorDestroyedException&) - { - // - // AMI requests can raise CommunicatorDestroyedException directly. - // - } - } - -private: - - Glacier2::Application* _app; - Glacier2::RouterPrx _router; - Glacier2::Callback_Router_refreshSessionPtr _callback; -}; - class ConnectionCallbackI : public Ice::ConnectionCallback { public: @@ -230,7 +186,7 @@ Glacier2::Application::doMain(Ice::StringSeq& args, const Ice::InitializationDat if(_createdSession) { - int acmTimeout = 0; + Ice::Int acmTimeout = 0; try { acmTimeout = _router->getACMTimeout(); @@ -238,6 +194,11 @@ Glacier2::Application::doMain(Ice::StringSeq& args, const Ice::InitializationDat catch(const Ice::OperationNotExistException&) { } + if(acmTimeout <= 0) + { + acmTimeout = static_cast<Ice::Int>(_router->getSessionTimeout()); + } + if(acmTimeout > 0) { Ice::ConnectionPtr connection = _router->ice_getCachedConnection(); @@ -245,21 +206,6 @@ Glacier2::Application::doMain(Ice::StringSeq& args, const Ice::InitializationDat connection->setACM(acmTimeout, IceUtil::None, Ice::HeartbeatAlways); connection->setCallback(new ConnectionCallbackI(this)); } - else - { - IceUtil::Int64 sessionTimeout = _router->getSessionTimeout(); - if(sessionTimeout > 0) - { - // - // Create a ping timer task. The task itself doesn't - // need to be canceled as the communicator is destroyed - // at the end. - // - IceUtil::TimerPtr timer = IceInternal::getInstanceTimer(communicator()); - timer->scheduleRepeated(new SessionRefreshTask(this, _router), - IceUtil::Time::seconds(sessionTimeout/2)); - } - } _category = _router->getCategoryForClient(); IceUtilInternal::ArgVector a(args); diff --git a/cpp/src/Glacier2Lib/SessionHelper.cpp b/cpp/src/Glacier2Lib/SessionHelper.cpp index efbb681194e..dbfb72afba5 100644 --- a/cpp/src/Glacier2Lib/SessionHelper.cpp +++ b/cpp/src/Glacier2Lib/SessionHelper.cpp @@ -59,7 +59,7 @@ class SessionHelperI : public Glacier2::SessionHelper public: - SessionHelperI(const Glacier2::SessionCallbackPtr&, const Ice::InitializationData&, const string&); + SessionHelperI(const Glacier2::SessionCallbackPtr&, const Ice::InitializationData&, const string&, bool); void destroy(); Ice::CommunicatorPtr communicator() const; std::string categoryForClient() const; @@ -100,48 +100,10 @@ private: const Ice::InitializationData _initData; const Glacier2::SessionCallbackPtr _callback; const string _finder; + const bool _useCallbacks; }; typedef IceUtil::Handle<SessionHelperI> SessionHelperIPtr; -class SessionRefreshTask : public IceUtil::TimerTask -{ -public: - - SessionRefreshTask(const Glacier2::SessionHelperPtr& session, const Glacier2::RouterPrx& router) : - _session(session), - _router(router), - _callback(Glacier2::newCallback_Router_refreshSession(this, &SessionRefreshTask::exception)) - { - } - - virtual void - runTimerTask() - { - try - { - _router->begin_refreshSession(_callback); - } - catch(const Ice::CommunicatorDestroyedException&) - { - // - // AMI requests can raise CommunicatorDestroyedException directly. - // - } - } - - void - exception(const Ice::Exception&) - { - _session->destroy(); - } - -private: - - const Glacier2::SessionHelperPtr _session; - const Glacier2::RouterPrx _router; - const Glacier2::Callback_Router_refreshSessionPtr _callback; -}; - class DestroyInternal : public IceUtil::Thread { @@ -168,12 +130,14 @@ private: SessionHelperI::SessionHelperI(const Glacier2::SessionCallbackPtr& callback, const Ice::InitializationData& initData, - const string& finderStr) : + const string& finderStr, + bool useCallbacks) : _connected(false), _destroy(false), _initData(initData), _callback(callback), - _finder(finderStr) + _finder(finderStr), + _useCallbacks(useCallbacks) { } @@ -207,8 +171,7 @@ SessionHelperI::destroy(const IceUtil::ThreadPtr& destroyInternal) _connected = false; // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // destroyInternal->start().detach(); } @@ -289,10 +252,10 @@ SessionHelperI::internalObjectAdapter() { throw Glacier2::SessionNotExistException(); } - if(!_adapter) + if(!_useCallbacks) { - _adapter = _communicator->createObjectAdapterWithRouter("", _router); - _adapter->activate(); + throw Ice::InitializationException(__FILE__, __LINE__, + "Object adapter not available, call SessionFactoryHelper.setUseCallbacks(true)"); } return _adapter; } @@ -677,13 +640,12 @@ void SessionHelperI::connected(const Glacier2::RouterPrx& router, const Glacier2::SessionPrx& session) { // - // Remote invocation should be done without acquire a mutex lock. + // Remote invocation should be done without acquiring a mutex lock. // assert(router); Ice::ConnectionPtr conn = router->ice_getCachedConnection(); string category = router->getCategoryForClient(); - Ice::Long sessionTimeout = router->getSessionTimeout(); - int acmTimeout = 0; + Ice::Int acmTimeout = 0; try { acmTimeout = router->getACMTimeout(); @@ -692,6 +654,23 @@ SessionHelperI::connected(const Glacier2::RouterPrx& router, const Glacier2::Ses { } + if(acmTimeout <= 0) + { + acmTimeout = static_cast<Ice::Int>(router->getSessionTimeout()); + } + + // + // We create the callback object adapter here because createObjectAdapter internally + // makes synchronous RPCs to the router. We can't create the OA on-demand when the + // client calls objectAdapter() or addWithUUID() because they can be called from the + // GUI thread. + // + if(_useCallbacks) + { + _adapter = _communicator->createObjectAdapterWithRouter("", router); + _adapter->activate(); + } + { IceUtil::Mutex::Lock sync(_mutex); _router = router; @@ -699,8 +678,7 @@ SessionHelperI::connected(const Glacier2::RouterPrx& router, const Glacier2::Ses if(_destroy) { // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // IceUtil::ThreadPtr thread = new DestroyInternal(this, _callback); thread->start().detach(); @@ -725,16 +703,6 @@ SessionHelperI::connected(const Glacier2::RouterPrx& router, const Glacier2::Ses connection->setACM(acmTimeout, IceUtil::None, Ice::HeartbeatAlways); connection->setCallback(new ConnectionCallbackI(this)); } - else if(sessionTimeout > 0) - { - // - // Create a ping timer task. The task itself doesn't need to be - // canceled as the communicator is destroyed at the end. - // - IceUtil::TimerPtr timer = IceInternal::getInstanceTimer(communicator()); - timer->scheduleRepeated(new SessionRefreshTask(this, _router), - IceUtil::Time::seconds(sessionTimeout/2)); - } } dispatchCallback(new Connected(_callback, this), conn); } @@ -802,7 +770,8 @@ Glacier2::SessionFactoryHelper::SessionFactoryHelper(const SessionCallbackPtr& c _protocol("ssl"), _port(0), _timeout(10000), - _callback(callback) + _callback(callback), + _useCallbacks(true) { _initData.properties = Ice::createProperties(); setDefaultProperties(); @@ -815,7 +784,8 @@ Glacier2::SessionFactoryHelper::SessionFactoryHelper(const Ice::InitializationDa _port(0), _timeout(10000), _initData(initData), - _callback(callback) + _callback(callback), + _useCallbacks(true) { if(!initData.properties) { @@ -830,7 +800,8 @@ Glacier2::SessionFactoryHelper::SessionFactoryHelper(const Ice::PropertiesPtr& p _protocol("ssl"), _port(0), _timeout(10000), - _callback(callback) + _callback(callback), + _useCallbacks(true) { if(!properties) { @@ -890,7 +861,7 @@ Glacier2::SessionFactoryHelper::setProtocol(const string& protocol) protocol != "ws" && protocol != "wss") { - throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Unknow protocol `" + protocol + "'"); + throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Unknown protocol `" + protocol + "'"); } _protocol = protocol; } @@ -951,11 +922,25 @@ Glacier2::SessionFactoryHelper::setConnectContext(map<string, string> context) _context = context; } +void +Glacier2::SessionFactoryHelper::setUseCallbacks(bool useCallbacks) +{ + IceUtil::Mutex::Lock sync(_mutex); + _useCallbacks = useCallbacks; +} + +bool +Glacier2::SessionFactoryHelper::getUseCallbacks() const +{ + IceUtil::Mutex::Lock sync(_mutex); + return _useCallbacks; +} + Glacier2::SessionHelperPtr Glacier2::SessionFactoryHelper::connect() { IceUtil::Mutex::Lock sync(_mutex); - SessionHelperIPtr session = new SessionHelperI(_callback, createInitData(), getRouterFinderStr()); + SessionHelperIPtr session = new SessionHelperI(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session->connect(_context); return session; } @@ -964,7 +949,7 @@ Glacier2::SessionHelperPtr Glacier2::SessionFactoryHelper::connect(const string& user, const string& password) { IceUtil::Mutex::Lock sync(_mutex); - SessionHelperIPtr session = new SessionHelperI(_callback, createInitData(), getRouterFinderStr()); + SessionHelperIPtr session = new SessionHelperI(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session->connect(user, password, _context); return session; } diff --git a/cs/src/Glacier2/Application.cs b/cs/src/Glacier2/Application.cs index fb7d6cb22d3..b5d4aa604c2 100644 --- a/cs/src/Glacier2/Application.cs +++ b/cs/src/Glacier2/Application.cs @@ -24,7 +24,7 @@ namespace Glacier2 /// error output. /// /// Applications must create a derived class that implements the {@link #run} method. -/// +/// /// A program can contain only one instance of this class. /// </summary> public abstract class Application : Ice.Application @@ -49,7 +49,7 @@ public abstract class Application : Ice.Application /// Initializes an instance that handles signals according to the signal /// policy. /// </summary> - /// <param name="signalPolicy">@param signalPolicy Determines how to + /// <param name="signalPolicy">@param signalPolicy Determines how to /// respond to signals.</param> public Application(Ice.SignalPolicy signalPolicy) : base(signalPolicy) @@ -93,7 +93,7 @@ public abstract class Application : Ice.Application /// method never returns. The exception produce an application restart /// when called from the Application main thread. /// </summary> - /// <returns>throws RestartSessionException This exception is + /// <returns>throws RestartSessionException This exception is /// always thrown.</returns> /// public void @@ -104,7 +104,7 @@ public abstract class Application : Ice.Application /// <summary> /// Creates a new Glacier2 session. A call to createSession always - /// precedes a call to runWithSession. If Ice.LocalException is thrown + /// precedes a call to runWithSession. If Ice.LocalException is thrown /// from this method, the application is terminated. /// </summary> /// <returns> The Glacier2 session.</returns> @@ -205,42 +205,6 @@ public abstract class Application : Ice.Application return _adapter; } - private class SessionRefreshTask : IceInternal.TimerTask - { - public SessionRefreshTask(Application app, Glacier2.RouterPrx router) - { - _app = app; - _router = router; - } - - public void - runTimerTask() - { - try - { - _router.begin_refreshSession().whenCompleted( - (Ice.Exception ex) => - { - // - // Here the session has been destroyed. Notify the - // application that the session has been destroyed. - // - _app.sessionDestroyed(); - }); - } - catch(Ice.CommunicatorDestroyedException) - { - // - // AMI requests can raise CommunicatorDestroyedException - // directly. - // - } - } - - private Application _app; - private Glacier2.RouterPrx _router; - } - private class ConnectionCallbackI : Ice.ConnectionCallback { internal ConnectionCallbackI(Application application) @@ -250,7 +214,7 @@ public abstract class Application : Ice.Application public void heartbeat(Ice.Connection con) { - + } public void closed(Ice.Connection con) @@ -346,22 +310,17 @@ public abstract class Application : Ice.Application catch(Ice.OperationNotExistException) { } + if(acmTimeout <= 0) + { + acmTimeout = (int)_router.getSessionTimeout(); + } if(acmTimeout > 0) { Ice.Connection connection = _router.ice_getCachedConnection(); Debug.Assert(connection != null); - connection.setACM(acmTimeout, Ice.Util.None, Ice.ACMHeartbeat.HeartbeatAlways); + connection.setACM((int)acmTimeout, Ice.Util.None, Ice.ACMHeartbeat.HeartbeatAlways); connection.setCallback(new ConnectionCallbackI(this)); } - else - { - long timeout = _router.getSessionTimeout(); - if(timeout > 0) - { - IceInternal.Timer timer = IceInternal.Util.getInstance(communicator()).timer(); - timer.scheduleRepeated(new SessionRefreshTask(this, _router), (timeout * 1000) / 2); - } - } _category = _router.getCategoryForClient(); status = runWithSession(args); } @@ -468,7 +427,7 @@ public abstract class Application : Ice.Application // // Not expected. // - Ice.Util.getProcessLogger().error("unexpected exception when destroying the session:\n" + + Ice.Util.getProcessLogger().error("unexpected exception when destroying the session:\n" + ex.ToString()); } _router = null; diff --git a/cs/src/Glacier2/SessionFactoryHelper.cs b/cs/src/Glacier2/SessionFactoryHelper.cs index 7fc792d1633..c37aff27581 100644 --- a/cs/src/Glacier2/SessionFactoryHelper.cs +++ b/cs/src/Glacier2/SessionFactoryHelper.cs @@ -167,7 +167,7 @@ public class SessionFactoryHelper !protocol.Equals("wss") && !protocol.Equals("ws")) { - throw new ArgumentException("Unknow protocol `" + protocol + "'"); + throw new ArgumentException("Unknown protocol `" + protocol + "'"); } _protocol = protocol; } @@ -276,6 +276,34 @@ public class SessionFactoryHelper } /// <summary> + /// Determines whether the session should create an object adapter that the client + /// can use for receiving callbacks. + /// </summary> + /// <param name="useCallbacks">True if the session should create an object adapter.</param> + public void + setUseCallbacks(bool useCallbacks) + { + lock(this) + { + _useCallbacks = useCallbacks; + } + } + + /// <summary> + /// Indicates whether a newly-created session will also create an object adapter that + /// the client can use for receiving callbaks. + /// </summary> + /// <returns>True if the session will create an object adapter.</returns> + public bool + getUseCallbacks() + { + lock(this) + { + return _useCallbacks; + } + } + + /// <summary> /// Connects to the Glacier2 router using the associated SSL credentials. /// /// Once the connection is established, SesssionCallback.connected is called on @@ -288,7 +316,7 @@ public class SessionFactoryHelper { lock(this) { - SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr()); + SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session.connect(_context); return session; } @@ -309,7 +337,7 @@ public class SessionFactoryHelper { lock(this) { - SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr()); + SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session.connect(username, password, _context); return session; } @@ -384,6 +412,7 @@ public class SessionFactoryHelper private int _port = 0; private int _timeout = 10000; private Dictionary<string, string> _context; + private bool _useCallbacks = true; private static int GLACIER2_SSL_PORT = 4064; private static int GLACIER2_TCP_PORT = 4063; } diff --git a/cs/src/Glacier2/SessionHelper.cs b/cs/src/Glacier2/SessionHelper.cs index 873019b124a..f9432d6003f 100644 --- a/cs/src/Glacier2/SessionHelper.cs +++ b/cs/src/Glacier2/SessionHelper.cs @@ -20,37 +20,6 @@ namespace Glacier2 /// </summary> public class SessionHelper { - private class SessionRefreshTask : IceInternal.TimerTask - { - public SessionRefreshTask(SessionHelper session, Glacier2.RouterPrx router) - { - _session = session; - _router = router; - } - - public void - runTimerTask() - { - try - { - _router.begin_refreshSession().whenCompleted( - (Ice.Exception ex) => - { - _session.destroy(); - }); - } - catch(Ice.CommunicatorDestroyedException) - { - // - // AMI requests can raise CommunicatorDestroyedException directly. - // - } - } - - private SessionHelper _session; - private Glacier2.RouterPrx _router; - } - private class ConnectionCallbackI : Ice.ConnectionCallback { internal ConnectionCallbackI(SessionHelper sessionHelper) @@ -79,11 +48,13 @@ public class SessionHelper /// <param name="initData">The Ice.InitializationData for initializing /// the communicator.</param> /// <param name="finderStr">The stringified Ice.RouterFinder proxy.</param> - public SessionHelper(SessionCallback callback, Ice.InitializationData initData, string finderStr) + /// <param name="useCallbacks">True if the session should create an object adapter for receiving callbacks.</param> + public SessionHelper(SessionCallback callback, Ice.InitializationData initData, string finderStr, bool useCallbacks) { _callback = callback; _initData = initData; _finderStr = finderStr; + _useCallbacks = useCallbacks; } /// <summary> @@ -115,8 +86,7 @@ public class SessionHelper _session = null; _connected = false; // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // Thread t = new Thread(new ThreadStart(destroyInternal)); t.Start(); @@ -215,7 +185,7 @@ public class SessionHelper /// <summary> /// Returns an object adapter for callback objects, creating it if necessary. /// </summary> - /// <return>The object adapter. throws SessionNotExistException + /// <return>The object adapter. Throws SessionNotExistException /// if no session exists.</return> public Ice.ObjectAdapter objectAdapter() @@ -223,9 +193,6 @@ public class SessionHelper return internalObjectAdapter(); } - // - // Only call this method when the calling thread owns the lock - // private Ice.ObjectAdapter internalObjectAdapter() { @@ -235,10 +202,10 @@ public class SessionHelper { throw new SessionNotExistException(); } - if(_adapter == null) + if(!_useCallbacks) { - _adapter = _communicator.createObjectAdapterWithRouter("", _router); - _adapter.activate(); + throw new Ice.InitializationException( + "Object adapter not available, call SessionFactoryHelper.setUseCallbacks(true)"); } return _adapter; } @@ -288,8 +255,12 @@ public class SessionHelper private void connected(RouterPrx router, SessionPrx session) { + // + // Remote invocation should be done without acquiring a mutex lock. + // + Debug.Assert(router != null); + Ice.Connection conn = router.ice_getCachedConnection(); string category = router.getCategoryForClient(); - long sessionTimeout = router.getSessionTimeout(); int acmTimeout = 0; try { @@ -298,7 +269,24 @@ public class SessionHelper catch(Ice.OperationNotExistException) { } - Ice.Connection conn = router.ice_getCachedConnection(); + + if(acmTimeout <= 0) + { + acmTimeout = (int)router.getSessionTimeout(); + } + + // + // We create the callback object adapter here because createObjectAdapter internally + // makes synchronous RPCs to the router. We can't create the OA on-demand when the + // client calls objectAdapter() or addWithUUID() because they can be called from the + // GUI thread. + // + if(_useCallbacks) + { + Debug.Assert(_adapter == null); + _adapter = _communicator.createObjectAdapterWithRouter("", router); + _adapter.activate(); + } lock(this) { @@ -307,8 +295,7 @@ public class SessionHelper if(_destroy) { // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // Thread t = new Thread(new ThreadStart(destroyInternal)); t.Start(); @@ -333,11 +320,6 @@ public class SessionHelper connection.setACM(acmTimeout, Ice.Util.None, Ice.ACMHeartbeat.HeartbeatAlways); connection.setCallback(new ConnectionCallbackI(this)); } - else if(sessionTimeout > 0) - { - IceInternal.Timer timer = IceInternal.Util.getInstance(communicator()).timer(); - timer.scheduleRepeated(new SessionRefreshTask(this, _router), (sessionTimeout * 1000)/2); - } } dispatchCallback(() => @@ -397,7 +379,6 @@ public class SessionHelper communicator.getLogger().warning("SessionHelper: unexpected exception when destroying the session:\n" + e); } - try { communicator.destroy(); @@ -450,8 +431,8 @@ public class SessionHelper } catch(Exception) { - // In case of error getting router identity from RouterFinder use - // default identity. + // + // In case of error getting router identity from RouterFinder use default identity. // Ice.Identity ident = new Ice.Identity("router", "Glacier2"); _communicator.setDefaultRouter(Ice.RouterPrxHelper.uncheckedCast(finder.ice_identity(ident))); @@ -465,8 +446,7 @@ public class SessionHelper _callback.createdCommunicator(this); }); - Glacier2.RouterPrx routerPrx = Glacier2.RouterPrxHelper.uncheckedCast( - _communicator.getDefaultRouter()); + Glacier2.RouterPrx routerPrx = Glacier2.RouterPrxHelper.uncheckedCast(_communicator.getDefaultRouter()); Glacier2.SessionPrx session = factory(routerPrx); connected(routerPrx, session); } @@ -537,6 +517,7 @@ public class SessionHelper private bool _connected = false; private string _category; private string _finderStr; + private bool _useCallbacks; private readonly SessionCallback _callback; private bool _destroy = false; diff --git a/distribution/src/windows/docs/thirdparty/README.txt b/distribution/src/windows/docs/thirdparty/README.txt index aaf6b28f6f6..ef0b53ec4dc 100644 --- a/distribution/src/windows/docs/thirdparty/README.txt +++ b/distribution/src/windows/docs/thirdparty/README.txt @@ -1,5 +1,5 @@ Ice 3.6.0 Third Party Packages ------------------------------ +------------------------------ This distribution contains the development kit (including binaries) for the open-source packages used by Ice 3.6.0 on Windows. Its primary diff --git a/java/src/Glacier2/src/main/java/Glacier2/Application.java b/java/src/Glacier2/src/main/java/Glacier2/Application.java index 8a1e2b62d9f..90a4ff21c30 100644 --- a/java/src/Glacier2/src/main/java/Glacier2/Application.java +++ b/java/src/Glacier2/src/main/java/Glacier2/Application.java @@ -291,7 +291,6 @@ public abstract class Application extends Ice.Application boolean restart = false; status.value = 0; - try { _communicator = Ice.Util.initialize(argHolder, initData); @@ -336,6 +335,10 @@ public abstract class Application extends Ice.Application catch(Ice.OperationNotExistException ex) { } + if(acmTimeout <= 0) + { + acmTimeout = (int)_router.getSessionTimeout(); + } if(acmTimeout > 0) { Ice.Connection connection = _router.ice_getCachedConnection(); @@ -345,61 +348,6 @@ public abstract class Application extends Ice.Application new Ice.Optional<Ice.ACMHeartbeat>(Ice.ACMHeartbeat.HeartbeatAlways)); connection.setCallback(new ConnectionCallbackI()); } - else - { - long timeout = _router.getSessionTimeout(); - if(timeout > 0) - { - java.util.concurrent.ScheduledExecutorService timer = - IceInternal.Util.getInstance(_communicator).timer(); - // - // We don't need to cancel the task as the communicator is destroyed at the end and - // ContinueExistingPeriodicTasksAfterShutdownPolicy is false. - // - timer.scheduleAtFixedRate(new Runnable() - { - @Override - public void run() - { - _router.begin_refreshSession(new Glacier2.Callback_Router_refreshSession() - { - @Override - public void - response() - { - } - - @Override - public void - exception(Ice.LocalException ex) - { - // - // Here the session has gone and we notify the application that - // the session has been destroyed. - // - sessionDestroyed(); - } - - @Override - public void - exception(Ice.UserException ex) - { - // - // Here the session has gone and we notify the application that - // the session has been destroyed. - // - sessionDestroyed(); - } - }); - // - // AMI requests can raise CommunicatorDestroyedException directly. We let this - // out of the task and terminate the timer. - // - - } - }, timeout / 2, timeout / 2, java.util.concurrent.TimeUnit.SECONDS); - } - } _category = _router.getCategoryForClient(); status.value = runWithSession(argHolder.value); } diff --git a/java/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java b/java/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java index eeb90412060..0899bb786cb 100644 --- a/java/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java +++ b/java/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java @@ -272,6 +272,30 @@ public class SessionFactoryHelper } /** + * Determines whether the session should create an object adapter that the client + * can use for receiving callbacks. + * + * @param useCallbacks True if the session should create an object adapter. + */ + synchronized public void + setUseCallbacks(boolean useCallbacks) + { + _useCallbacks = useCallbacks; + } + + /** + * Indicates whether a newly-created session will also create an object adapter that + * the client can use for receiving callbacks. + * + * @return True if the session will create an object adapter. + */ + synchronized public boolean + getUseCallbacks() + { + return _useCallbacks; + } + + /** * Connects to the Glacier2 router using the associated SSL credentials. * * Once the connection is established, {@link SessionCallback#connected} is called on the callback object; @@ -282,7 +306,7 @@ public class SessionFactoryHelper synchronized public SessionHelper connect() { - SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr()); + SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session.connect(_context); return session; } @@ -300,7 +324,7 @@ public class SessionFactoryHelper synchronized public SessionHelper connect(final String username, final String password) { - SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr()); + SessionHelper session = new SessionHelper(_callback, createInitData(), getRouterFinderStr(), _useCallbacks); session.connect(username, password, _context); return session; } @@ -368,6 +392,7 @@ public class SessionFactoryHelper private int _port = 0; private int _timeout = 10000; private java.util.Map<String, String> _context; + private boolean _useCallbacks = true; private static final int GLACIER2_SSL_PORT = 4064; private static final int GLACIER2_TCP_PORT = 4063; } diff --git a/java/src/Glacier2/src/main/java/Glacier2/SessionHelper.java b/java/src/Glacier2/src/main/java/Glacier2/SessionHelper.java index f39223c3e10..3e3311bacb7 100644 --- a/java/src/Glacier2/src/main/java/Glacier2/SessionHelper.java +++ b/java/src/Glacier2/src/main/java/Glacier2/SessionHelper.java @@ -19,12 +19,16 @@ public class SessionHelper * * @param callback The callback for notifications about session establishment. * @param initData The {@link Ice.InitializationData} for initializing the communicator. + * @param finderStr The stringified Ice.RouterFinder proxy. + * @param useCallbacks True if the session should create an object adapter for receiving callbacks. */ - public SessionHelper(SessionCallback callback, Ice.InitializationData initData, String finderStr) + public SessionHelper(SessionCallback callback, Ice.InitializationData initData, String finderStr, + boolean useCallbacks) { _callback = callback; _initData = initData; _finderStr = finderStr; + _useCallbacks = useCallbacks; } /** @@ -71,8 +75,7 @@ public class SessionHelper } // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // new Thread(new Runnable() { @@ -182,10 +185,10 @@ public class SessionHelper { throw new SessionNotExistException(); } - if(_adapter == null) + if(!_useCallbacks) { - _adapter = _communicator.createObjectAdapterWithRouter("", _router); - _adapter.activate(); + throw new Ice.InitializationException( + "Object adapter not available, call SessionFactoryHelper.setUseCallbacks(true)"); } return _adapter; } @@ -246,8 +249,12 @@ public class SessionHelper private void connected(RouterPrx router, SessionPrx session) { + // + // Remote invocation should be done without acquiring a mutex lock. + // + assert(router != null); + Ice.Connection conn = router.ice_getCachedConnection(); String category = router.getCategoryForClient(); - long sessionTimeout = router.getSessionTimeout(); int acmTimeout = 0; try { @@ -256,7 +263,24 @@ public class SessionHelper catch(Ice.OperationNotExistException ex) { } - Ice.Connection conn = router.ice_getCachedConnection(); + + if(acmTimeout <= 0) + { + acmTimeout = (int)router.getSessionTimeout(); + } + + // + // We create the callback object adapter here because createObjectAdapter internally + // makes synchronous RPCs to the router. We can't create the OA on-demand when the + // client calls objectAdapter() or addWithUUID() because they can be called from the + // GUI thread. + // + if(_useCallbacks) + { + assert(_adapter == null); + _adapter = _communicator.createObjectAdapterWithRouter("", router); + _adapter.activate(); + } synchronized(this) { @@ -265,8 +289,7 @@ public class SessionHelper if(_destroy) { // - // Run the destroyInternal in a thread. This is because it - // destroyInternal makes remote invocations. + // Run destroyInternal in a thread because it makes remote invocations. // new Thread(new Runnable() { @@ -311,45 +334,6 @@ public class SessionHelper } }); } - else if(sessionTimeout > 0) - { - java.util.concurrent.ScheduledExecutorService timer = - IceInternal.Util.getInstance(_communicator).timer(); - // - // We don't need to cancel the task as the communicator is destroyed at the end and - // ContinueExistingPeriodicTasksAfterShutdownPolicy is false. - // - timer.scheduleAtFixedRate(new Runnable() - { - @Override - public void run() - { - _router.begin_refreshSession(new Glacier2.Callback_Router_refreshSession() - { - @Override - public void response() - { - } - - @Override - public void exception(Ice.LocalException ex) - { - SessionHelper.this.destroy(); - } - - @Override - public void exception(Ice.UserException ex) - { - SessionHelper.this.destroy(); - } - }); - // - // AMI requests can raise CommunicatorDestroyedException directly. We let this - // out of the task and terminate the timer. - // - } - }, sessionTimeout / 2, sessionTimeout / 2, java.util.concurrent.TimeUnit.SECONDS); - } _shutdownHook = new Thread("Shutdown hook") { @@ -601,6 +585,7 @@ public class SessionHelper private Glacier2.SessionPrx _session; private String _category; private String _finderStr; + private boolean _useCallbacks; private final SessionCallback _callback; private boolean _destroy = false; diff --git a/py/python/Glacier2.py b/py/python/Glacier2.py index 59efb676f6d..149dde48386 100644 --- a/py/python/Glacier2.py +++ b/py/python/Glacier2.py @@ -33,49 +33,6 @@ class RestartSessionException(Exception): def __init__(self): pass -class SessionPingThread(threading.Thread): - def __init__(self, app, router, period): - threading.Thread.__init__(self) - self._app = app - self._router = router - self._period = period - self._done = False - self._cond = threading.Condition() - - def run(self): - self._cond.acquire() - try: - while not self._done: - self._router.begin_refreshSession(self.response, self.exception) - - if not self._done: - self._cond.wait(self._period) - finally: - self._cond.release() - - def done(self): - self._cond.acquire() - try: - if not self._done: - self._done = True - self._cond.notify() - finally: - self._cond.release() - - def response(self): - # - # Ignore successful call to refreshSession. - # - pass - - def exception(self, ex): - # - # Here the session has gone. The thread terminates, and we notify the - # application that the session has been destroyed. - # - self.done() - self._app.sessionDestroyed() - class ConnectionCallbackI(Ice.ConnectionCallback): def __init__(self, app): self._app = app @@ -159,7 +116,6 @@ Application.NoSignalHandling. restart = False status = 0 - ping = None try: Ice.Application._communicator = Ice.initialize(args, initData) @@ -188,16 +144,13 @@ Application.NoSignalHandling. acmTimeout = Application._router.getACMTimeout() except(Ice.OperationNotExistException): pass + if acmTimeout <= 0: + acmTimeout = Application._router.getSessionTimeout() if acmTimeout > 0: connection = Application._router.ice_getCachedConnection() assert(connection) connection.setACM(acmTimeout, Ice.Unset, Ice.ACMHeartbeat.HeartbeatAlways) connection.setCallback(ConnectionCallbackI(self)) - else: - timeout = Application._router.getSessionTimeout() - if timeout > 0: - ping = SessionPingThread(self, Application._router, timeout / 2) - ping.start() Application._category = Application._router.getCategoryForClient() status = self.runWithSession(args) @@ -237,10 +190,6 @@ Application.NoSignalHandling. # Ice.Application._condVar.release() - if ping: - ping.done() - ping.join() - if Application._createdSession and Application._router: try: Application._router.destroySession() |