#include #include #include "SessionLocalFileStore.h" /** * Add a new session to the store (if it doesn't exist yet) and return a referenced version * of the session with this ID. * * @param session belongs to the store after calling this method */ std::shared_ptr SessionLocalFileStore::addAndReferenceSession( std::unique_ptr session) { std::string fileHandleID(session->getFileHandleID() ); uint16_t targetID = session->getTargetID(); bool isMirrorSession = session->getIsMirrorSession(); std::lock_guard const lock(mutex); // try to insert the new session auto insertRes = sessions.insert( {Key{fileHandleID, targetID, isMirrorSession}, std::move(session)}); // reference session (note: insertRes.first is an iterator to the inserted/existing session) return insertRes.first->second; } /** * @param targetID really targetID (not buddy group ID for mirrors, because both buddies can be * attached to the same server). * @param isMirrorSession true if this is a session for a mirrored chunk file. * @return NULL if no such session exists. */ std::shared_ptr SessionLocalFileStore::referenceSession( const std::string& fileHandleID, uint16_t targetID, bool isMirrorSession) const { std::lock_guard const lock(mutex); auto iter = sessions.find({fileHandleID, targetID, isMirrorSession}); if (iter != sessions.end()) return iter->second; return nullptr; } /** * @param isMirrorSession true if this is a session for a mirror chunk file * @return filesystem state of the session if it was unused, nullptr otherwise. */ std::shared_ptr SessionLocalFileStore::removeSession( const std::string& fileHandleID, uint16_t targetID, bool isMirrorSession) { std::shared_ptr file; { std::lock_guard const lock(mutex); auto iter = sessions.find({fileHandleID, targetID, isMirrorSession}); if (iter == sessions.end()) return nullptr; file = std::move(iter->second); sessions.erase(iter); } return releaseLastReference(std::move(file)); } size_t SessionLocalFileStore::removeAllSessions() { std::lock_guard const lock(mutex); size_t total = sessions.size(); sessions.clear(); return total; } /** * Removes all mirror sessions on a specific target. */ void SessionLocalFileStore::removeAllMirrorSessions(uint16_t targetID) { std::lock_guard const lock(mutex); for (auto iter = sessions.begin(); iter != sessions.end(); ) { auto& session = iter->second; ++iter; if (session->getTargetID() == targetID && session->getIsMirrorSession()) sessions.erase(std::prev(iter)); } } /* * Intended to be used for cleanup if deserialization failed, no locking is used */ void SessionLocalFileStore::deleteAllSessions() { sessions.clear(); } size_t SessionLocalFileStore::getSize() const { std::lock_guard const lock(mutex); return sessions.size(); } /* Merges the SessionLocalFiles of the given SessionLocalFileStore into this SessionLocalFileStore. * Only not existing SessionLocalFiles will be added to the existing SessionLocalFileStore * * @param sessionLocalFileStore the sessionLocalFileStore which will be merged with this * sessionLocalFileStore */ void SessionLocalFileStore::mergeSessionLocalFiles(SessionLocalFileStore* sessionLocalFileStore) { for (auto sessionIter = sessionLocalFileStore->sessions.begin(); sessionIter != sessionLocalFileStore->sessions.end(); ++sessionIter) { if (sessions.count(sessionIter->first)) { const auto& id = sessionIter->first; LOG(GENERAL, WARNING, "Found SessionLocalFile with same ID, merge not possible, may be a bug?", id.fileHandleID, id.targetID, id.isMirrored); continue; } sessions[sessionIter->first] = std::move(sessionIter->second); } } void SessionLocalFileStore::serializeForTarget(Serializer& ser, uint16_t targetID) { Serializer atStart = ser.mark(); uint32_t elemCount = 0; ser % elemCount; // needs fixup for (auto it = sessions.begin(), end = sessions.end(); it != end; ++it) { if (it->first.targetID != targetID) continue; ser % it->first % *it->second; elemCount++; } atStart % elemCount; LOG_DEBUG("SessionLocalFileStore serialize", Log_DEBUG, "count of serialized " "SessionLocalFiles: " + StringTk::uintToStr(elemCount) + " of " + StringTk::uintToStr(sessions.size())); } void SessionLocalFileStore::deserializeForTarget(Deserializer& des, uint16_t targetID) { uint32_t elemCount; des % elemCount; if (unlikely(!des.good())) return; for (uint32_t i = 0; i < elemCount; i++) { Key key; auto sessionLocalFile = boost::make_unique(); des % key % *sessionLocalFile; if (unlikely(!des.good() || key.targetID != targetID)) { des.setBad(); return; } this->sessions.insert({key, std::move(sessionLocalFile)}); } LOG_DEBUG("SessionLocalFileStore deserialize", Log_DEBUG, "count of deserialized " "SessionLocalFiles: " + StringTk::uintToStr(elemCount)); }