blob: 02b9e8a31d7021f59d71d9228cab8576da3f1342 [file] [log] [blame]
Patrick Ventureef3aead2018-09-12 08:53:29 -07001#pragma once
2
Patrick Ventureaceb4ba2018-09-27 14:50:37 -07003#include <blobs-ipmid/blobs.hpp>
Patrick Williams52509572023-05-10 07:51:18 -05004#include <ipmid/oemrouter.hpp>
5
Kun Yi7fc52c82019-11-19 13:45:05 -08006#include <chrono>
Patrick Ventureef3aead2018-09-12 08:53:29 -07007#include <ctime>
8#include <memory>
Kun Yib61a88b2019-11-12 22:50:34 -08009#include <set>
Patrick Ventureef3aead2018-09-12 08:53:29 -070010#include <string>
11#include <unordered_map>
12#include <vector>
13
14namespace blobs
15{
16
Kun Yib61a88b2019-11-12 22:50:34 -080017using namespace std::chrono_literals;
Kun Yib61a88b2019-11-12 22:50:34 -080018constexpr auto defaultSessionTimeout = 10min;
Patrick Venture86c87f52019-02-01 14:44:15 -080019
Patrick Ventureef3aead2018-09-12 08:53:29 -070020struct 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)
Patrick Williams52509572023-05-10 07:51:18 -050027 {}
Patrick Ventureef3aead2018-09-12 08:53:29 -070028 ~SessionInfo() = default;
29
30 std::string blobId;
31 GenericBlobInterface* handler;
32 uint16_t flags;
Kun Yi7fc52c82019-11-19 13:45:05 -080033
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();
Patrick Ventureef3aead2018-09-12 08:53:29 -070039};
40
41class 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
Patrick Venture8bc11772019-06-04 07:20:24 -070056 virtual bool stat(const std::string& path, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070057
Patrick Venture8bc11772019-06-04 07:20:24 -070058 virtual bool stat(uint16_t session, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070059
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;
Patrick Venture5c4b17b2018-10-04 10:32:22 -070071
72 virtual bool writeMeta(uint16_t session, uint32_t offset,
73 const std::vector<uint8_t>& data) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070074};
75
76/**
77 * Blob Manager used to store handlers and sessions.
78 */
79class BlobManager : public ManagerInterface
80{
81 public:
Kun Yib61a88b2019-11-12 22:50:34 -080082 BlobManager(std::chrono::seconds sessionTimeout = defaultSessionTimeout) :
83 sessionTimeout(sessionTimeout)
Patrick Ventureef3aead2018-09-12 08:53:29 -070084 {
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 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700140 bool stat(const std::string& path, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700141
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 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700149 bool stat(uint16_t session, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700150
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 /**
Patrick Venture5c4b17b2018-10-04 10:32:22 -0700211 * 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 /**
Patrick Ventureef3aead2018-09-12 08:53:29 -0700222 * 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
Kun Yi9cd8f762019-11-22 20:11:42 -0800229 private:
Patrick Ventureef3aead2018-09-12 08:53:29 -0700230 /**
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 /**
Kun Yi9cd8f762019-11-22 20:11:42 -0800240 * Given a session id, update session time and return a handler to take
Kun Yic892f4a2019-11-19 13:42:46 -0800241 * action
Patrick Ventureef3aead2018-09-12 08:53:29 -0700242 *
Kun Yic892f4a2019-11-19 13:42:46 -0800243 * @param[in] session - session ID
Kun Yi9cd8f762019-11-22 20:11:42 -0800244 * @param[in] requiredFlags - only return handler if the flags for this
Kun Yic892f4a2019-11-19 13:42:46 -0800245 * session contain these flags; defaults to any flag
246 * @return session handler, nullptr if cannot get handler
Patrick Ventureef3aead2018-09-12 08:53:29 -0700247 */
Kun Yi9cd8f762019-11-22 20:11:42 -0800248 GenericBlobInterface* getActionHandler(
Kun Yic892f4a2019-11-19 13:42:46 -0800249 uint16_t session,
Kun Yifea1d812019-11-14 11:38:44 -0800250 uint16_t requiredFlags = std::numeric_limits<uint16_t>::max());
Patrick Ventureef3aead2018-09-12 08:53:29 -0700251
Kun Yi9cd8f762019-11-22 20:11:42 -0800252 /**
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);
Kun Yib61a88b2019-11-12 22:50:34 -0800268
269 /* How long a session has to be inactive to be considered stale */
270 std::chrono::seconds sessionTimeout;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700271 /* 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;
Kun Yib61a88b2019-11-12 22:50:34 -0800282 /* Map of handlers to their open sessions */
283 std::unordered_map<GenericBlobInterface*, std::set<uint16_t>> openSessions;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700284};
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700285
286/**
287 * @brief Gets a handle to the BlobManager.
288 *
289 * @return a pointer to the BlobManager instance.
290 */
Patrick Venture73eb6872018-10-01 18:37:34 -0700291ManagerInterface* getBlobManager();
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700292
Patrick Ventureef3aead2018-09-12 08:53:29 -0700293} // namespace blobs