diff options
author | Marc Laukien <marc@zeroc.com> | 2004-09-30 17:21:47 +0000 |
---|---|---|
committer | Marc Laukien <marc@zeroc.com> | 2004-09-30 17:21:47 +0000 |
commit | 338f12d50adc609ddff7641af1d84be3cba282b7 (patch) | |
tree | 06ffe08c28ab4da3cd710a7165e1ba7356823f9d /cpp | |
parent | Added tests for collection of leaf nodes. (diff) | |
download | ice-338f12d50adc609ddff7641af1d84be3cba282b7.tar.bz2 ice-338f12d50adc609ddff7641af1d84be3cba282b7.tar.xz ice-338f12d50adc609ddff7641af1d84be3cba282b7.zip |
more glacier2
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/demo/Glacier2/callback/config.glacier2 | 9 | ||||
-rw-r--r-- | cpp/src/Glacier/Blobject.h | 7 | ||||
-rw-r--r-- | cpp/src/Glacier/ClientBlobject.h | 3 | ||||
-rw-r--r-- | cpp/src/Glacier/ServerBlobject.h | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/Blobject.cpp | 5 | ||||
-rw-r--r-- | cpp/src/Glacier2/Blobject.h | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/ClientBlobject.cpp | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/ClientBlobject.h | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/Glacier2Router.cpp | 18 | ||||
-rw-r--r-- | cpp/src/Glacier2/RequestQueue.cpp | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/RouterI.cpp | 143 | ||||
-rw-r--r-- | cpp/src/Glacier2/RouterI.h | 20 | ||||
-rw-r--r-- | cpp/src/Glacier2/ServerBlobject.h | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/SessionRouterI.cpp | 232 | ||||
-rw-r--r-- | cpp/src/Glacier2/SessionRouterI.h | 10 | ||||
-rw-r--r-- | cpp/src/Ice/Instance.cpp | 2 |
16 files changed, 347 insertions, 120 deletions
diff --git a/cpp/demo/Glacier2/callback/config.glacier2 b/cpp/demo/Glacier2/callback/config.glacier2 index e8b0ca1fe72..e43f4cb3822 100644 --- a/cpp/demo/Glacier2/callback/config.glacier2 +++ b/cpp/demo/Glacier2/callback/config.glacier2 @@ -21,6 +21,13 @@ Glacier2.Server.Endpoints=tcp -h 127.0.0.1 Glacier2.PermissionsVerifier=verifier:tcp -h 127.0.0.1 -p 10000 # +# The timeout for inactive sessions. If any client session is inactive +# for longer than this value, the session expires and is removed. The +# unit is seconds. +# +Glacier2.SessionTimeout=30 + +# # These two lines instruct Glacier to forward contexts both for # regular routing, as well as for callbacks (reverse routing). # @@ -33,7 +40,7 @@ Glacier2.Server.ForwardContext=1 # period after all current requests for this client have been # forwarded. During this sleep period, new requests for the client are # queued. These requests are then all sent once the sleep period is -# over. +# over. The unit is milliseconds. # Glacier2.Client.SleepTime=500 Glacier2.Server.SleepTime=500 diff --git a/cpp/src/Glacier/Blobject.h b/cpp/src/Glacier/Blobject.h index 7491c63b929..cc757d8ce3b 100644 --- a/cpp/src/Glacier/Blobject.h +++ b/cpp/src/Glacier/Blobject.h @@ -47,13 +47,14 @@ public: Blobject(const Ice::CommunicatorPtr&, bool); virtual ~Blobject(); - void destroy(); + virtual void destroy(); + +protected: + void invoke(Ice::ObjectPrx&, const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); bool modifyProxy(Ice::ObjectPrx&, const Ice::Current&); -protected: - Ice::CommunicatorPtr _communicator; const bool _reverse; diff --git a/cpp/src/Glacier/ClientBlobject.h b/cpp/src/Glacier/ClientBlobject.h index de5930b3707..7deeb9677e4 100644 --- a/cpp/src/Glacier/ClientBlobject.h +++ b/cpp/src/Glacier/ClientBlobject.h @@ -22,7 +22,8 @@ public: ClientBlobject(const Ice::CommunicatorPtr&, const IceInternal::RoutingTablePtr&, const std::string&); - void destroy(); + virtual void destroy(); + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); diff --git a/cpp/src/Glacier/ServerBlobject.h b/cpp/src/Glacier/ServerBlobject.h index a04ef3d3d15..fbab7ad0d79 100644 --- a/cpp/src/Glacier/ServerBlobject.h +++ b/cpp/src/Glacier/ServerBlobject.h @@ -21,7 +21,8 @@ public: ServerBlobject(const Ice::ObjectAdapterPtr&); - void destroy(); + virtual void destroy(); + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); diff --git a/cpp/src/Glacier2/Blobject.cpp b/cpp/src/Glacier2/Blobject.cpp index 334ecd3164a..57bf70e55dd 100644 --- a/cpp/src/Glacier2/Blobject.cpp +++ b/cpp/src/Glacier2/Blobject.cpp @@ -17,10 +17,11 @@ static const string serverAlwaysBatch = "Glacier2.Server.AlwaysBatch"; static const string clientAlwaysBatch = "Glacier2.Client.AlwaysBatch"; Glacier2::Blobject::Blobject(const CommunicatorPtr& communicator, bool reverse) : + _properties(communicator->getProperties()), _logger(communicator->getLogger()), _alwaysBatch(reverse ? - communicator->getProperties()->getPropertyAsInt(serverAlwaysBatch) > 0 : - communicator->getProperties()->getPropertyAsInt(clientAlwaysBatch) > 0) + _properties->getPropertyAsInt(serverAlwaysBatch) > 0 : + _properties->getPropertyAsInt(clientAlwaysBatch) > 0) { _requestQueue = new RequestQueue(communicator, reverse); _requestQueue->start(); diff --git a/cpp/src/Glacier2/Blobject.h b/cpp/src/Glacier2/Blobject.h index 8d5e89f6652..5895b2fad06 100644 --- a/cpp/src/Glacier2/Blobject.h +++ b/cpp/src/Glacier2/Blobject.h @@ -23,13 +23,14 @@ public: Blobject(const Ice::CommunicatorPtr&, bool); virtual ~Blobject(); - void destroy(); + virtual void destroy(); protected: void invoke(Ice::ObjectPrx&, const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); + const Ice::PropertiesPtr _properties; const Ice::LoggerPtr _logger; private: diff --git a/cpp/src/Glacier2/ClientBlobject.cpp b/cpp/src/Glacier2/ClientBlobject.cpp index f568efa27df..30fe28b30f1 100644 --- a/cpp/src/Glacier2/ClientBlobject.cpp +++ b/cpp/src/Glacier2/ClientBlobject.cpp @@ -1,4 +1,3 @@ - // ********************************************************************** // // Copyright (c) 2003-2004 ZeroC, Inc. All rights reserved. @@ -21,7 +20,7 @@ Glacier2::ClientBlobject::ClientBlobject(const CommunicatorPtr& communicator, const string& allow) : Glacier2::Blobject(communicator, false), _routingTable(routingTable), - _rejectTraceLevel(communicator->getProperties()->getPropertyAsInt("Glacier2.Client.Trace.Reject")) + _rejectTraceLevel(_properties->getPropertyAsInt("Glacier2.Client.Trace.Reject")) { vector<string>& allowCategories = const_cast<vector<string>&>(_allowCategories); diff --git a/cpp/src/Glacier2/ClientBlobject.h b/cpp/src/Glacier2/ClientBlobject.h index 412c3c9b485..2d3d24ad695 100644 --- a/cpp/src/Glacier2/ClientBlobject.h +++ b/cpp/src/Glacier2/ClientBlobject.h @@ -26,7 +26,8 @@ public: ClientBlobject(const Ice::CommunicatorPtr&, const IceInternal::RoutingTablePtr&, const std::string&); virtual ~ClientBlobject(); - void destroy(); + virtual void destroy(); + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); diff --git a/cpp/src/Glacier2/Glacier2Router.cpp b/cpp/src/Glacier2/Glacier2Router.cpp index 3c59e915638..ee0acd991d1 100644 --- a/cpp/src/Glacier2/Glacier2Router.cpp +++ b/cpp/src/Glacier2/Glacier2Router.cpp @@ -153,18 +153,20 @@ Glacier2::RouterService::start(int argc, char* argv[]) } // - // Create a router implementation that can handle sessions, and - // add it to the client object adapter. + // Create the session router. The session router registers itself + // and all required servant locators, so no registration has to be + // done here. // _sessionRouter = new SessionRouterI(clientAdapter, serverAdapter, verifier); - const char* routerIdProperty = "Glacier2.RouterIdentity"; - Identity routerId = stringToIdentity(properties->getPropertyWithDefault(routerIdProperty, "Glacier2/router")); - clientAdapter->add(_sessionRouter, routerId); // // Everything ok, let's go. // clientAdapter->activate(); + if(serverAdapter) + { + serverAdapter->activate(); + } return true; } @@ -172,12 +174,8 @@ Glacier2::RouterService::start(int argc, char* argv[]) bool Glacier2::RouterService::stop() { - // - // Destroy the session router. - // - assert(_sessionRouter); _sessionRouter->destroy(); - + _sessionRouter = 0; return true; } diff --git a/cpp/src/Glacier2/RequestQueue.cpp b/cpp/src/Glacier2/RequestQueue.cpp index 50d7402c83a..fa4e6eb921c 100644 --- a/cpp/src/Glacier2/RequestQueue.cpp +++ b/cpp/src/Glacier2/RequestQueue.cpp @@ -187,7 +187,6 @@ Glacier2::RequestQueue::run() while(true) { vector<RequestPtr> requests; - set<ConnectionPtr> flushSet; { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); @@ -216,6 +215,8 @@ Glacier2::RequestQueue::run() try { + set<ConnectionPtr> flushSet; + for(vector<RequestPtr>::const_iterator p = requests.begin(); p != requests.end(); ++p) { const ObjectPrx& proxy = (*p)->getProxy(); diff --git a/cpp/src/Glacier2/RouterI.cpp b/cpp/src/Glacier2/RouterI.cpp index 609d6363093..5f49cbc52e2 100644 --- a/cpp/src/Glacier2/RouterI.cpp +++ b/cpp/src/Glacier2/RouterI.cpp @@ -14,108 +14,89 @@ using namespace std; using namespace Ice; using namespace Glacier2; -class RouterLocator : public ServantLocator -{ -public: - - RouterLocator(const ServerBlobjectPtr& serverBlobject) : - _serverBlobject(serverBlobject) - { - } - - virtual ObjectPtr - locate(const Current& current, LocalObjectPtr&) - { - return _serverBlobject; - } - - virtual void - finished(const Current&, const ObjectPtr&, const LocalObjectPtr&) - { - } - - virtual void - deactivate(const string&) - { - } - -private: - - ServerBlobjectPtr _serverBlobject; -}; - -Glacier2::RouterI::RouterI(const ObjectAdapterPtr& clientAdapter, - const ObjectAdapterPtr& serverAdapter, - const ConnectionPtr& connection) : +Glacier2::RouterI::RouterI(const ObjectAdapterPtr& clientAdapter, const ObjectAdapterPtr& serverAdapter, + const ConnectionPtr& connection, const string& userId) : _communicator(clientAdapter->getCommunicator()), _routingTable(new IceInternal::RoutingTable), _routingTableTraceLevel(_communicator->getProperties()->getPropertyAsInt("Glacier2.Trace.RoutingTable")), _clientProxy(clientAdapter->createProxy(stringToIdentity("dummy"))), - _clientBlobject(new ClientBlobject(_communicator, _routingTable, "")) + _clientBlobject(new ClientBlobject(_communicator, _routingTable, "")), + _connection(connection), + _userId(userId), + _timestamp(IceUtil::Time::now()), + _destroy(false) { - try + if(serverAdapter) { - if(serverAdapter) + ObjectPrx& serverProxy = const_cast<ObjectPrx&>(_serverProxy); + Identity ident; + ident.name = "dummy"; + ident.category.resize(20); + for(string::iterator p = ident.category.begin(); p != ident.category.end(); ++p) { - ObjectPrx& serverProxy = const_cast<ObjectPrx&>(_serverProxy); - Identity ident; - ident.name = "dummy"; - ident.category.resize(20); - for(string::iterator p = ident.category.begin(); p != ident.category.end(); ++p) - { - *p = static_cast<char>(33 + rand() % (127-33)); // We use ASCII 33-126 (from ! to ~, w/o space). - } - serverProxy = serverAdapter->createProxy(ident); - - ServerBlobjectPtr& serverBlobject = const_cast<ServerBlobjectPtr&>(_serverBlobject); - serverBlobject = new ServerBlobject(_communicator, connection); - serverAdapter->addServantLocator(new RouterLocator(serverBlobject), ident.category); - serverAdapter->activate(); + *p = static_cast<char>(33 + rand() % (127-33)); // We use ASCII 33-126 (from ! to ~, w/o space). } - } - catch(...) - { - destroy(); - throw; + serverProxy = serverAdapter->createProxy(ident); + + ServerBlobjectPtr& serverBlobject = const_cast<ServerBlobjectPtr&>(_serverBlobject); + serverBlobject = new ServerBlobject(_communicator, connection); } } Glacier2::RouterI::~RouterI() { + assert(_destroy); } void Glacier2::RouterI::destroy() { - _clientBlobject->destroy(); + IceUtil::Mutex::Lock lock(*this); + + assert(!_destroy); + _clientBlobject->destroy(); + if(_serverBlobject) { _serverBlobject->destroy(); - } + } + + _destroy = true; } ObjectPrx Glacier2::RouterI::getClientProxy(const Current&) const { + // No mutex lock necessary, _clientProxy is immutable and is never destroyed. return _clientProxy; } ObjectPrx Glacier2::RouterI::getServerProxy(const Current&) const { + // No mutex lock necessary, _serverProxy is immutable and is never destroyed. return _serverProxy; } void Glacier2::RouterI::addProxy(const ObjectPrx& proxy, const Current&) { + IceUtil::Mutex::Lock lock(*this); + + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } + if(_routingTableTraceLevel) { Trace out(_communicator->getLogger(), "Glacier2"); out << "adding proxy to routing table:\n" << _communicator->proxyToString(proxy); } + _timestamp = IceUtil::Time::now(); + _routingTable->add(proxy); } @@ -128,11 +109,59 @@ Glacier2::RouterI::createSession(const std::string&, const std::string&, const C ClientBlobjectPtr Glacier2::RouterI::getClientBlobject() const { + IceUtil::Mutex::Lock lock(*this); + + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } + + _timestamp = IceUtil::Time::now(); + return _clientBlobject; } ServerBlobjectPtr Glacier2::RouterI::getServerBlobject() const { + IceUtil::Mutex::Lock lock(*this); + + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } + + _timestamp = IceUtil::Time::now(); + return _serverBlobject; } + +IceUtil::Time +Glacier2::RouterI::getTimestamp() const +{ + IceUtil::Mutex::TryLock lock(*this); + + if(lock.acquired()) + { + return _timestamp; + } + else + { + return IceUtil::Time::now(); + } +} + +string +Glacier2::RouterI::toString() const +{ + ostringstream out; + + out << "user-id = " << _userId << '\n'; + if(_serverProxy) + { + out << "category = " << _serverProxy->ice_getIdentity().category << '\n'; + } + out << _connection->toString(); + + return out.str(); +} diff --git a/cpp/src/Glacier2/RouterI.h b/cpp/src/Glacier2/RouterI.h index fc5dd9297c1..f21fb543f59 100644 --- a/cpp/src/Glacier2/RouterI.h +++ b/cpp/src/Glacier2/RouterI.h @@ -21,11 +21,11 @@ namespace Glacier2 class RouterI; typedef IceUtil::Handle<RouterI> RouterIPtr; -class RouterI : public Router +class RouterI : public Router, public IceUtil::Mutex { public: - RouterI(const Ice::ObjectAdapterPtr&, const Ice::ObjectAdapterPtr&, const Ice::ConnectionPtr&); + RouterI(const Ice::ObjectAdapterPtr&, const Ice::ObjectAdapterPtr&, const Ice::ConnectionPtr&, const std::string&); virtual ~RouterI(); void destroy(); @@ -34,8 +34,12 @@ public: virtual void addProxy(const Ice::ObjectPrx&, const Ice::Current&); virtual void createSession(const std::string&, const std::string&, const Ice::Current&); - Glacier2::ClientBlobjectPtr getClientBlobject() const; - Glacier2::ServerBlobjectPtr getServerBlobject() const; + ClientBlobjectPtr getClientBlobject() const; + ServerBlobjectPtr getServerBlobject() const; + + IceUtil::Time getTimestamp() const; + + std::string toString() const; private: @@ -44,8 +48,12 @@ private: const int _routingTableTraceLevel; const Ice::ObjectPrx _clientProxy; const Ice::ObjectPrx _serverProxy; - const Glacier2::ClientBlobjectPtr _clientBlobject; - const Glacier2::ServerBlobjectPtr _serverBlobject; + const ClientBlobjectPtr _clientBlobject; + const ServerBlobjectPtr _serverBlobject; + const Ice::ConnectionPtr _connection; + const std::string _userId; + mutable IceUtil::Time _timestamp; + bool _destroy; }; } diff --git a/cpp/src/Glacier2/ServerBlobject.h b/cpp/src/Glacier2/ServerBlobject.h index 2cc3a42e673..7f5ac076cf2 100644 --- a/cpp/src/Glacier2/ServerBlobject.h +++ b/cpp/src/Glacier2/ServerBlobject.h @@ -25,7 +25,8 @@ public: ServerBlobject(const Ice::CommunicatorPtr&, const Ice::ConnectionPtr&); virtual ~ServerBlobject(); - void destroy(); + virtual void destroy(); + virtual void ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&, const std::vector<Ice::Byte>&, const Ice::Current&); diff --git a/cpp/src/Glacier2/SessionRouterI.cpp b/cpp/src/Glacier2/SessionRouterI.cpp index 80b8d88b02a..8bb60387729 100644 --- a/cpp/src/Glacier2/SessionRouterI.cpp +++ b/cpp/src/Glacier2/SessionRouterI.cpp @@ -15,11 +15,11 @@ using namespace std; using namespace Ice; using namespace Glacier2; -class SessionLocator : public ServantLocator +class ClientLocator : public ServantLocator { public: - SessionLocator(const SessionRouterIPtr& sessionRouter) : + ClientLocator(const SessionRouterIPtr& sessionRouter) : _sessionRouter(sessionRouter) { } @@ -27,7 +27,6 @@ public: virtual ObjectPtr locate(const Current& current, LocalObjectPtr&) { - assert(current.con); return _sessionRouter->getRouter(current.con)->getClientBlobject(); } @@ -46,46 +45,121 @@ private: const SessionRouterIPtr _sessionRouter; }; +class ServerLocator : public ServantLocator +{ +public: + + ServerLocator(const SessionRouterIPtr& sessionRouter) : + _sessionRouter(sessionRouter) + { + } + + virtual ObjectPtr + locate(const Current& current, LocalObjectPtr&) + { + return _sessionRouter->getRouter(current.id.category)->getServerBlobject(); + } + + virtual void + finished(const Current&, const ObjectPtr&, const LocalObjectPtr&) + { + } + + virtual void + deactivate(const std::string&) + { + } + +private: + + const SessionRouterIPtr _sessionRouter; +}; + Glacier2::SessionRouterI::SessionRouterI(const ObjectAdapterPtr& clientAdapter, const ObjectAdapterPtr& serverAdapter, const PermissionsVerifierPrx& verifier) : + _properties(clientAdapter->getCommunicator()->getProperties()), _logger(clientAdapter->getCommunicator()->getLogger()), - _traceLevel(clientAdapter->getCommunicator()->getProperties()->getPropertyAsInt("Glacier2.Trace.Session")), + _traceLevel(_properties->getPropertyAsInt("Glacier2.Trace.Session")), _clientAdapter(clientAdapter), _serverAdapter(serverAdapter), _verifier(verifier), - _sessionThread(new SessionThread(this)), - _routersHint(_routers.end()), + _sessionTimeout(IceUtil::Time::seconds(_properties->getPropertyAsInt("Glacier2.SessionTimeout"))), + _sessionThread(_sessionTimeout > IceUtil::Time() ? new SessionThread(this) : 0), + _routersByConnectionHint(_routersByConnection.end()), + _routersByCategoryHint(_routersByCategory.end()), _destroy(false) { - _clientAdapter->addServantLocator(new SessionLocator(this), ""); + // + // This session router is used directly as servant for the main + // Glacier2 router Ice object. + // + const char* routerIdProperty = "Glacier2.RouterIdentity"; + Identity routerId = stringToIdentity(_properties->getPropertyWithDefault(routerIdProperty, "Glacier2/router")); + _clientAdapter->add(this, routerId); + + // + // All other calls on the client object adapter are dispatched to + // a router servant based on connection information. + // + ServantLocatorPtr clientLocator = new ClientLocator(this); + _clientAdapter->addServantLocator(clientLocator, ""); + + // + // If there is a server object adapter, all calls on this adapter + // are dispatched to a router servant based on the category field + // of the identity. + // + if(_serverAdapter) + { + ServantLocatorPtr serverLocator = new ServerLocator(this); + _serverAdapter->addServantLocator(serverLocator, ""); + } + + if(_sessionThread) + { + _sessionThread->start(); + } } Glacier2::SessionRouterI::~SessionRouterI() { assert(_destroy); - assert(_routers.empty()); + assert(_routersByConnection.empty()); + assert(_routersByCategory.empty()); } void Glacier2::SessionRouterI::destroy() { + map<ConnectionPtr, RouterIPtr> routers; + { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); assert(!_destroy); - _destroy = true; + _routersByConnection.swap(routers); + _routersByConnectionHint = _routersByConnection.end(); - for_each(_routers.begin(), _routers.end(), - IceUtil::secondVoidMemFun<const ConnectionPtr, RouterI>(&RouterI::destroy)); - _routers.clear(); - _routersHint = _routers.end(); + _routersByCategory.clear(); + _routersByCategoryHint = _routersByCategory.end(); + _destroy = true; notify(); } - _sessionThread->getThreadControl().join(); + // + // We destroy the routers outside the thread synchronization, to + // avoid deadlocks. + // + for_each(routers.begin(), routers.end(), + IceUtil::secondVoidMemFun<const ConnectionPtr, RouterI>(&RouterI::destroy)); + + if(_sessionThread) + { + _sessionThread->getThreadControl().join(); + } } ObjectPrx @@ -111,7 +185,10 @@ Glacier2::SessionRouterI::createSession(const std::string& userId, const std::st { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - assert(!_destroy); + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } // // Check the user-id and password. @@ -127,14 +204,22 @@ Glacier2::SessionRouterI::createSession(const std::string& userId, const std::st // // Add a new per-client router. // - RouterIPtr router = new RouterI(_clientAdapter, _serverAdapter, current.con); - _routersHint = _routers.insert(_routersHint, pair<const ConnectionPtr, RouterIPtr>(current.con, router)); + RouterIPtr router = new RouterI(_clientAdapter, _serverAdapter, current.con, userId); + _routersByConnectionHint = _routersByConnection.insert(_routersByConnectionHint, + pair<const ConnectionPtr, RouterIPtr>(current.con, router)); + if(_serverAdapter) + { + string category = router->getServerProxy(current)->ice_getIdentity().category; + assert(!category.empty()); + _routersByCategoryHint = _routersByCategory.insert(_routersByCategoryHint, + pair<string, RouterIPtr>(category, router)); + } if(_traceLevel >= 1) { Trace out(_logger, "Glacier2"); - out << "added session for `" << userId << "':\n"; - out << current.con->toString(); + out << "new session\n"; + out << router->toString(); } } @@ -143,36 +228,125 @@ Glacier2::SessionRouterI::getRouter(const ConnectionPtr& connection) const { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - assert(!_destroy); + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } - map<ConnectionPtr, RouterIPtr>& routers = const_cast<map<ConnectionPtr, RouterIPtr>&>(_routers); + map<ConnectionPtr, RouterIPtr>& routers = const_cast<map<ConnectionPtr, RouterIPtr>&>(_routersByConnection); - if(_routersHint != routers.end() && _routersHint->first == connection) + if(_routersByConnectionHint != routers.end() && _routersByConnectionHint->first == connection) { - return _routersHint->second; + return _routersByConnectionHint->second; } map<ConnectionPtr, RouterIPtr>::iterator p = routers.find(connection); if(p != routers.end()) { - _routersHint = p; + _routersByConnectionHint = p; + return p->second; + } + else + { + throw ObjectNotExistException(__FILE__, __LINE__); + } +} + +RouterIPtr +Glacier2::SessionRouterI::getRouter(const string& category) const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + if(_destroy) + { + throw ObjectNotExistException(__FILE__, __LINE__); + } + + map<string, RouterIPtr>& routers = const_cast<map<string, RouterIPtr>&>(_routersByCategory); + + if(_routersByCategoryHint != routers.end() && _routersByCategoryHint->first == category) + { + return _routersByCategoryHint->second; + } + + map<string, RouterIPtr>::iterator p = routers.find(category); + + if(p != routers.end()) + { + _routersByCategoryHint = p; return p->second; } else { - return 0; + throw ObjectNotExistException(__FILE__, __LINE__); } } void Glacier2::SessionRouterI::run() { - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + while(true) + { + vector<RouterIPtr> routers; + + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + if(_destroy) + { + return; + } + + assert(_sessionTimeout > IceUtil::Time()); + timedWait(_sessionTimeout); + + if(_destroy) + { + return; + } + + IceUtil::Time minTimestamp = IceUtil::Time::now() - _sessionTimeout; + + map<ConnectionPtr, RouterIPtr>::iterator p = _routersByConnection.begin(); + + while(p != _routersByConnection.end()) + { + if(minTimestamp < p->second->getTimestamp()) + { + RouterIPtr router = p->second; + routers.push_back(router); + + _routersByConnection.erase(p++); + _routersByConnectionHint = p; + + if(_serverAdapter) + { + string category = router->getServerProxy(Current())->ice_getIdentity().category; + assert(!category.empty()); + _routersByCategory.erase(category); + _routersByCategoryHint = _routersByCategory.end(); + } + + if(_traceLevel >= 1) + { + Trace out(_logger, "Glacier2"); + out << "expired session\n"; + out << router->toString(); + } + } + else + { + ++p; + } + } + } - while(!_destroy) - { - wait(); + // + // We destroy the expired routers outside the thread + // synchronization, to avoid deadlocks. + // + for_each(routers.begin(), routers.end(), IceUtil::voidMemFun(&RouterI::destroy)); } } diff --git a/cpp/src/Glacier2/SessionRouterI.h b/cpp/src/Glacier2/SessionRouterI.h index 649ce0cfd57..fd8a1170ee0 100644 --- a/cpp/src/Glacier2/SessionRouterI.h +++ b/cpp/src/Glacier2/SessionRouterI.h @@ -39,16 +39,19 @@ public: virtual void createSession(const std::string&, const std::string&, const Ice::Current&); RouterIPtr getRouter(const Ice::ConnectionPtr&) const; + RouterIPtr getRouter(const std::string&) const; virtual void run(); private: + const Ice::PropertiesPtr _properties; const Ice::LoggerPtr _logger; const int _traceLevel; const Ice::ObjectAdapterPtr _clientAdapter; const Ice::ObjectAdapterPtr _serverAdapter; const PermissionsVerifierPrx _verifier; + const IceUtil::Time _sessionTimeout; // // TODO: I can't inherit directly from IceUtil::Thread, because of @@ -68,10 +71,11 @@ private: }; const IceUtil::Handle<SessionThread> _sessionThread; - int _serverAdapterCount; + std::map<Ice::ConnectionPtr, RouterIPtr> _routersByConnection; + mutable std::map<Ice::ConnectionPtr, RouterIPtr>::iterator _routersByConnectionHint; - std::map<Ice::ConnectionPtr, RouterIPtr> _routers; - mutable std::map<Ice::ConnectionPtr, RouterIPtr>::iterator _routersHint; + std::map<std::string, RouterIPtr> _routersByCategory; + mutable std::map<std::string, RouterIPtr>::iterator _routersByCategoryHint; bool _destroy; }; diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp index 5bee1edad51..a1588e45e68 100644 --- a/cpp/src/Ice/Instance.cpp +++ b/cpp/src/Ice/Instance.cpp @@ -522,7 +522,7 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Prope } { - Int num = _properties->getPropertyAsIntWithDefault("Ice.ConnectiondleTime", 60); + Int num = _properties->getPropertyAsIntWithDefault("Ice.ConnectionIdleTime", 60); if(num < 0) { const_cast<Int&>(_connectionIdleTime) = 0; |