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