diff options
-rw-r--r-- | manager.cpp | 55 | ||||
-rw-r--r-- | manager.hpp | 16 |
2 files changed, 68 insertions, 3 deletions
diff --git a/manager.cpp b/manager.cpp index 684f20c..286b81a 100644 --- a/manager.cpp +++ b/manager.cpp @@ -17,6 +17,7 @@ #include "manager.hpp" #include <algorithm> +#include <iostream> #include <memory> #include <string> #include <vector> @@ -67,6 +68,52 @@ int BlobManager::getOpen(const std::string& path) const return 0; } +void BlobManager::eraseSession(GenericBlobInterface* handler, uint16_t session) +{ + sessions.erase(session); + /* Ok for openSessions[handler] to be an empty set */ + openSessions[handler].erase(session); + decrementOpen(getPath(session)); +} + +void BlobManager::cleanUpStaleSessions(GenericBlobInterface* handler) +{ + if (openSessions.count(handler) == 0) + { + return; + } + + auto timeNow = std::chrono::steady_clock::now(); + std::set<uint16_t> expiredSet; + + for (auto sessionId : openSessions[handler]) + { + if (timeNow - sessions[sessionId].lastActionTime >= sessionTimeout) + { + expiredSet.insert(sessionId); + } + } + + for (auto sessionId : expiredSet) + { + std::cerr << "phosphor-ipmi-blobs: expiring stale session " << sessionId + << std::endl; + + /* We do a best case recovery by issuing an expire call. If it fails + * don't erase sessions since the handler side might be still tracking + * it as open. */ + if (handler->expire(sessionId)) + { + eraseSession(handler, sessionId); + } + else + { + std::cerr << "phosphor-ipmi-blobs: failed to expire session " + << sessionId << std::endl; + } + } +} + bool BlobManager::registerHandler(std::unique_ptr<GenericBlobInterface> handler) { if (!handler) @@ -130,6 +177,10 @@ bool BlobManager::open(uint16_t flags, const std::string& path, return false; } + /* Try to clean up anything that's falling out of cleanup timeout for this + * handler */ + cleanUpStaleSessions(handler); + if (!handler->open(*session, flags, path)) { return false; @@ -137,6 +188,7 @@ bool BlobManager::open(uint16_t flags, const std::string& path, /* Associate session with handler */ sessions[*session] = SessionInfo(path, handler, flags); + openSessions[handler].insert(*session); incrementOpen(path); return true; } @@ -206,8 +258,7 @@ bool BlobManager::close(uint16_t session) { return false; } - sessions.erase(session); - decrementOpen(getPath(session)); + eraseSession(handler, session); return true; } return false; diff --git a/manager.hpp b/manager.hpp index e7a9a97..011fe88 100644 --- a/manager.hpp +++ b/manager.hpp @@ -5,6 +5,7 @@ #include <ctime> #include <ipmid/oemrouter.hpp> #include <memory> +#include <set> #include <string> #include <unordered_map> #include <vector> @@ -12,6 +13,8 @@ namespace blobs { +using namespace std::chrono_literals; + /* The maximum read size. * NOTE: Once this can be dynamically determined, we'll switch to that method. * Having this in a header allows it to used cleanly for now. @@ -21,6 +24,7 @@ const int btReplyHdrLen = 5; const int btTransportLength = 64; const uint32_t maximumReadSize = btTransportLength - (btReplyHdrLen + oem::groupMagicSize + crcSize); +constexpr auto defaultSessionTimeout = 10min; struct SessionInfo { @@ -85,7 +89,8 @@ class ManagerInterface class BlobManager : public ManagerInterface { public: - BlobManager() + BlobManager(std::chrono::seconds sessionTimeout = defaultSessionTimeout) : + sessionTimeout(sessionTimeout) { next = static_cast<uint16_t>(std::time(nullptr)); }; @@ -275,6 +280,13 @@ class BlobManager : public ManagerInterface void decrementOpen(const std::string& path); int getOpen(const std::string& path) const; + /* Helper method to erase a session from all maps */ + void eraseSession(GenericBlobInterface* handler, uint16_t session); + /* For each session owned by this handler, call expire if it is stale */ + void cleanUpStaleSessions(GenericBlobInterface* handler); + + /* How long a session has to be inactive to be considered stale */ + std::chrono::seconds sessionTimeout; /* The next session ID to use */ uint16_t next; /* Temporary list of blobIds used for enumeration. */ @@ -286,6 +298,8 @@ class BlobManager : public ManagerInterface std::unordered_map<uint16_t, SessionInfo> sessions; /* Mapping of open blobIds */ std::unordered_map<std::string, int> openFiles; + /* Map of handlers to their open sessions */ + std::unordered_map<GenericBlobInterface*, std::set<uint16_t>> openSessions; }; /** |