#pragma once #include #include #include #include #include #include "Session.h" typedef ObjectReferencer SessionReferencer; typedef std::map SessionMap; typedef SessionMap::iterator SessionMapIter; typedef SessionMap::value_type SessionMapVal; typedef std::list SessionList; typedef SessionList::iterator SessionListIter; /* * A session always belongs to a client ID, therefore the session ID is always the nodeID of the * corresponding client */ class SessionStore { friend class TestSerialization; // for testing public: SessionStore() {} Session* referenceSession(NumNodeID sessionID, bool addIfNotExists=true); void releaseSession(Session* session); void syncSessions(const std::vector& masterList, SessionList& outRemovedSessions, NumNodeIDList& outUnremovableSessions); NumNodeIDList getAllSessionIDs(); size_t getSize(); void serialize(Serializer& ser) const; void deserialize(Deserializer& des); void deserializeLockStates(Deserializer& des, MetaStore& metaStore); std::pair, size_t> serializeToBuf(); bool deserializeFromBuf(const char* buf, size_t bufLen, MetaStore& metaStore); bool loadFromFile(const std::string& filePath, MetaStore& metaStore); bool saveToFile(const std::string& filePath); bool clear(); EntryLockStore* getEntryLockStore() { return &this->entryLockStore; } bool operator==(const SessionStore& other) const; bool operator!=(const SessionStore& other) const { return !(*this == other); } private: SessionMap sessions; Mutex mutex; EntryLockStore entryLockStore; // Locks on entryIDs to synchronize with mirror buddy. void addSession(Session* session); // actually not needed (maybe later one day...) bool removeSession(NumNodeID sessionID); // actually not needed (maybe later one day...) Session* removeSessionUnlocked(NumNodeID sessionID); bool relinkInodes(MetaStore& store) { bool result = true; for (auto it = sessions.begin(); it != sessions.end(); ) { const bool relinkRes = it->second->getReferencedObject()->relinkInodes(store); if (!relinkRes) { // Relinking failed on at least one SessionFile in this Session -> remove if empty if (it->second->getReferencedObject()->getFiles()->getSize() == 0) sessions.erase(it++); else ++it; } else { ++it; } result &= relinkRes; } return result; } };