diff --git a/server/json-adapter.cc b/server/json-adapter.cc index 4984fd9..9c71dab 100644 --- a/server/json-adapter.cc +++ b/server/json-adapter.cc @@ -258,7 +258,7 @@ void JsonAdapter::prepare_run(const std::string& address, unsigned start_port, u { check_guard(); // delayed after constructor, so virtual functions are working: - i->session_registry.reset(new SessionRegistry(messageToSend ? messageToSend : this->getMessageToSend(), this->getInjectSyncEvent())); + i->session_registry.reset(new SessionRegistry(messageToSend ? messageToSend : this->getMessageToSend(), this->getInjectSyncEvent(), i->client_session_timeout)); for(unsigned short port = start_port; port<=end_port; ++port) { diff --git a/server/server_version.cc b/server/server_version.cc index 5f7e41e..d22be12 100644 --- a/server/server_version.cc +++ b/server/server_version.cc @@ -76,7 +76,8 @@ static const std::string VersionName = // "(42) Gotha"; // JSON-152: 2-parameter version of pollForEvents(). // "(43) Wandersleben"; // JSON-153 passphrase support. *sigh* // "(44) Neudietendorf"; // replace my own sync thread code by libpEpAdapter's implementation. - "(45) Kreuz Erfurt"; // fix of context-saved function parameters that would cause trouble when >1 request is processed in parallel. +// "(45) Kreuz Erfurt"; // fix of context-saved function parameters that would cause trouble when >1 request is processed in parallel. + "(46) Erfurt-West"; // JSON-156: delete client cached values after timeout. } // end of anonymous namespace //////////////////////////////////////////////////////////////////////////// diff --git a/server/session_registry.cc b/server/session_registry.cc index 2a56167..ef4e11c 100644 --- a/server/session_registry.cc +++ b/server/session_registry.cc @@ -10,6 +10,8 @@ PEP_SESSION SessionRegistry::get(std::thread::id tid, const std::string& client_ { Lock L(_mtx); + update_last_use(client_id); + auto q = m.find(tid); if(q != m.end()) { @@ -69,6 +71,7 @@ void SessionRegistry::add_to_cache(const std::string& client_id, const std::stri Lock L(_mtx); Log.debug("add_to_cache(\"%s\", \"%s\")", client_id.c_str(), fn_name.c_str()); cache[client_id][fn_name] = func; + update_last_use(client_id); } @@ -83,3 +86,23 @@ std::string SessionRegistry::to_string() const } return ss.str(); } + + +void SessionRegistry::update_last_use(const std::string& client_id) +{ + const auto now = std::chrono::system_clock::now(); + const auto too_old = now - std::chrono::seconds(client_timeout); + last_use[client_id] = now; + + // TODO: replace by C++20 std::erase_if() + for(auto q = last_use.begin(); q != last_use.end(); /* no increment here */ ) + { + if(q->second < too_old) + { + cache.erase( q->first ); + q = last_use.erase(q); + }else{ + ++q; + } + } +} diff --git a/server/session_registry.hh b/server/session_registry.hh index d9e1fce..c44ac2c 100644 --- a/server/session_registry.hh +++ b/server/session_registry.hh @@ -1,6 +1,7 @@ #ifndef JSON_ADAPTER_SESSION_REGISTRY_HH #define JSON_ADAPTER_SESSION_REGISTRY_HH +#include #include #include #include @@ -11,10 +12,11 @@ class SessionRegistry { public: - SessionRegistry(messageToSend_t _mts, inject_sync_event_t _ise) + SessionRegistry(messageToSend_t _mts, inject_sync_event_t _ise, int _client_timeout) : mts{_mts} , ise{_ise} , Log{"SR"} + , client_timeout{_client_timeout} // in seconds {} // calls "init" for the given thread if no PEP_SESSION exists, yet for the given thread @@ -36,16 +38,23 @@ private: std::map m; messageToSend_t mts; inject_sync_event_t ise; - Logger Log; + Logger Log; + int client_timeout; // in seconds + // function name -> functor typedef std::map> cache_per_client_t; + // key=client_id std::map cache; + std::map > last_use; + typedef std::recursive_mutex Mutex; typedef std::unique_lock Lock; mutable Mutex _mtx; + + void update_last_use(const std::string& client_id); }; #endif // JSON_ADAPTER_SESSION_REGISTRY_HH