1 #pragma once 2 3 #include <blobs-ipmid/blobs.hpp> 4 #include <ipmid/oemrouter.hpp> 5 6 #include <chrono> 7 #include <ctime> 8 #include <memory> 9 #include <set> 10 #include <string> 11 #include <unordered_map> 12 #include <vector> 13 14 namespace blobs 15 { 16 17 using namespace std::chrono_literals; 18 constexpr auto defaultSessionTimeout = 10min; 19 20 struct SessionInfo 21 { 22 SessionInfo() = default; SessionInfoblobs::SessionInfo23 SessionInfo(const std::string& path, GenericBlobInterface* handler, 24 uint16_t flags) : blobId(path), handler(handler), flags(flags) 25 {} 26 ~SessionInfo() = default; 27 28 std::string blobId; 29 GenericBlobInterface* handler; 30 uint16_t flags; 31 32 /* Initially set during open(). read/write/writeMeta/commit/stat operations 33 * would update it. 34 */ 35 std::chrono::time_point<std::chrono::steady_clock> lastActionTime = 36 std::chrono::steady_clock::now(); 37 }; 38 39 class ManagerInterface 40 { 41 public: 42 virtual ~ManagerInterface() = default; 43 44 virtual bool 45 registerHandler(std::unique_ptr<GenericBlobInterface> handler) = 0; 46 47 virtual uint32_t buildBlobList() = 0; 48 49 virtual std::string getBlobId(uint32_t index) = 0; 50 51 virtual bool open(uint16_t flags, const std::string& path, 52 uint16_t* session) = 0; 53 54 virtual bool stat(const std::string& path, BlobMeta* meta) = 0; 55 56 virtual bool stat(uint16_t session, BlobMeta* meta) = 0; 57 58 virtual bool commit(uint16_t session, const std::vector<uint8_t>& data) = 0; 59 60 virtual bool close(uint16_t session) = 0; 61 62 virtual std::vector<uint8_t> read(uint16_t session, uint32_t offset, 63 uint32_t requestedSize) = 0; 64 65 virtual bool write(uint16_t session, uint32_t offset, 66 const std::vector<uint8_t>& data) = 0; 67 68 virtual bool deleteBlob(const std::string& path) = 0; 69 70 virtual bool writeMeta(uint16_t session, uint32_t offset, 71 const std::vector<uint8_t>& data) = 0; 72 }; 73 74 /** 75 * Blob Manager used to store handlers and sessions. 76 */ 77 class BlobManager : public ManagerInterface 78 { 79 public: BlobManager(std::chrono::seconds sessionTimeout=defaultSessionTimeout)80 BlobManager(std::chrono::seconds sessionTimeout = defaultSessionTimeout) : 81 sessionTimeout(sessionTimeout) 82 { 83 next = static_cast<uint16_t>(std::time(nullptr)); 84 }; 85 86 ~BlobManager() = default; 87 /* delete copy constructor & assignment operator, only support move 88 * operations. 89 */ 90 BlobManager(const BlobManager&) = delete; 91 BlobManager& operator=(const BlobManager&) = delete; 92 BlobManager(BlobManager&&) = default; 93 BlobManager& operator=(BlobManager&&) = default; 94 95 /** 96 * Register a handler. We own the pointer. 97 * 98 * @param[in] handler - a pointer to a blob handler. 99 * @return bool - true if registered. 100 */ 101 bool 102 registerHandler(std::unique_ptr<GenericBlobInterface> handler) override; 103 104 /** 105 * Builds the blobId list for enumeration. 106 * 107 * @return lowest value returned is 0, otherwise the number of 108 * blobIds. 109 */ 110 uint32_t buildBlobList() override; 111 112 /** 113 * Grabs the blobId for the indexed blobId. 114 * 115 * @param[in] index - the index into the blobId cache. 116 * @return string - the blobId or empty string on failure. 117 */ 118 std::string getBlobId(uint32_t index) override; 119 120 /** 121 * Attempts to open the file specified and associates with a session. 122 * 123 * @param[in] flags - the flags to pass to open. 124 * @param[in] path - the file path to open. 125 * @param[in,out] session - pointer to store the session on success. 126 * @return bool - true if able to open. 127 */ 128 bool open(uint16_t flags, const std::string& path, 129 uint16_t* session) override; 130 131 /** 132 * Attempts to retrieve a BlobMeta for the specified path. 133 * 134 * @param[in] path - the file path for stat(). 135 * @param[in,out] meta - a pointer to store the metadata. 136 * @return bool - true if able to retrieve the information. 137 */ 138 bool stat(const std::string& path, BlobMeta* meta) override; 139 140 /** 141 * Attempts to retrieve a BlobMeta for a given session. 142 * 143 * @param[in] session - the session for this command. 144 * @param[in,out] meta - a pointer to store the metadata. 145 * @return bool - true if able to retrieve the information. 146 */ 147 bool stat(uint16_t session, BlobMeta* meta) override; 148 149 /** 150 * Attempt to commit a blob for a given session. 151 * 152 * @param[in] session - the session for this command. 153 * @param[in] data - an optional commit blob. 154 * @return bool - true if the commit succeeds. 155 */ 156 bool commit(uint16_t session, const std::vector<uint8_t>& data) override; 157 158 /** 159 * Attempt to close a session. If the handler returns a failure 160 * in closing, the session is kept open. 161 * 162 * @param[in] session - the session for this command. 163 * @return bool - true if the session was closed. 164 */ 165 bool close(uint16_t session) override; 166 167 /** 168 * Attempt to read bytes from the blob. If there's a failure, such as 169 * an invalid offset it'll just return 0 bytes. 170 * 171 * @param[in] session - the session for this command. 172 * @param[in] offset - the offset from which to read. 173 * @param[in] requestedSize - the number of bytes to try and read. 174 * @return the bytes read. 175 */ 176 std::vector<uint8_t> read(uint16_t session, uint32_t offset, 177 uint32_t requestedSize) override; 178 179 /** 180 * Attempt to write to a blob. The manager does not track whether 181 * the session opened the file for writing. 182 * 183 * @param[in] session - the session for this command. 184 * @param[in] offset - the offset into the blob to write. 185 * @param[in] data - the bytes to write to the blob. 186 * @return bool - true if the write succeeded. 187 */ 188 bool write(uint16_t session, uint32_t offset, 189 const std::vector<uint8_t>& data) override; 190 191 /** 192 * Attempt to delete a blobId. This method will just call the 193 * handler, which will return failure if the blob doesn't support 194 * deletion. This command will also fail if there are any open 195 * sessions against the specific blob. 196 * 197 * In the case where they specify a folder, such as /blob/skm where 198 * the "real" blobIds are /blob/skm/1, or /blob/skm/2, the manager 199 * may see there are on open sessions to that specific path and will 200 * call the handler. In this case, the handler is responsible for 201 * handling any checks or logic. 202 * 203 * @param[in] path - the blobId path. 204 * @return bool - true if delete was successful. 205 */ 206 bool deleteBlob(const std::string& path) override; 207 208 /** 209 * Attempt to write Metadata to a blob. 210 * 211 * @param[in] session - the session for this command. 212 * @param[in] offset - the offset into the blob to write. 213 * @param[in] data - the bytes to write to the blob. 214 * @return bool - true if the write succeeded. 215 */ 216 bool writeMeta(uint16_t session, uint32_t offset, 217 const std::vector<uint8_t>& data) override; 218 219 /** 220 * Attempts to return a valid unique session id. 221 * 222 * @param[in,out] - pointer to the session. 223 * @return bool - true if able to allocate. 224 */ 225 bool getSession(uint16_t* session); 226 227 private: 228 /** 229 * Given a file path will return first handler to answer that it owns 230 * it. 231 * 232 * @param[in] path - the file path. 233 * @return pointer to the handler or nullptr if not found. 234 */ 235 GenericBlobInterface* getHandler(const std::string& path); 236 237 /** 238 * Given a session id, update session time and return a handler to take 239 * action 240 * 241 * @param[in] session - session ID 242 * @param[in] requiredFlags - only return handler if the flags for this 243 * session contain these flags; defaults to any flag 244 * @return session handler, nullptr if cannot get handler 245 */ 246 GenericBlobInterface* getActionHandler( 247 uint16_t session, 248 uint16_t requiredFlags = std::numeric_limits<uint16_t>::max()); 249 250 /** 251 * Helper method to erase a session from all maps 252 * 253 * @param[in] handler - handler pointer for lookup 254 * @param[in] session - session ID for lookup 255 * @return None 256 */ 257 void eraseSession(GenericBlobInterface* const handler, uint16_t session); 258 259 /** 260 * For each session owned by this handler, call expire if it is stale 261 * 262 * @param[in] handler - handler pointer for lookup 263 * @return None 264 */ 265 void cleanUpStaleSessions(GenericBlobInterface* const handler); 266 267 /* How long a session has to be inactive to be considered stale */ 268 std::chrono::seconds sessionTimeout; 269 /* The next session ID to use */ 270 uint16_t next; 271 /* Temporary list of blobIds used for enumeration. */ 272 std::vector<std::string> ids; 273 /* List of Blob handler. */ 274 std::vector<std::unique_ptr<GenericBlobInterface>> handlers; 275 /* Mapping of session ids to blob handlers and the path used with open. 276 */ 277 std::unordered_map<uint16_t, SessionInfo> sessions; 278 /* Mapping of open blobIds */ 279 std::unordered_map<std::string, int> openFiles; 280 /* Map of handlers to their open sessions */ 281 std::unordered_map<GenericBlobInterface*, std::set<uint16_t>> openSessions; 282 }; 283 284 /** 285 * @brief Gets a handle to the BlobManager. 286 * 287 * @return a pointer to the BlobManager instance. 288 */ 289 ManagerInterface* getBlobManager(); 290 291 } // namespace blobs 292