blob: 3dc09cd0a9b502c33dc1986342de9d74de4f0418 [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>
Kun Yi7fc52c82019-11-19 13:45:05 -08004#include <chrono>
Patrick Ventureef3aead2018-09-12 08:53:29 -07005#include <ctime>
William A. Kennington IIIacebece2019-02-07 15:15:44 -08006#include <ipmid/oemrouter.hpp>
Patrick Ventureef3aead2018-09-12 08:53:29 -07007#include <memory>
Kun Yib61a88b2019-11-12 22:50:34 -08008#include <set>
Patrick Ventureef3aead2018-09-12 08:53:29 -07009#include <string>
10#include <unordered_map>
11#include <vector>
12
13namespace blobs
14{
15
Kun Yib61a88b2019-11-12 22:50:34 -080016using namespace std::chrono_literals;
17
Patrick Venture86c87f52019-02-01 14:44:15 -080018/* The maximum read size.
19 * NOTE: Once this can be dynamically determined, we'll switch to that method.
20 * Having this in a header allows it to used cleanly for now.
21 */
22const int crcSize = sizeof(uint16_t);
23const int btReplyHdrLen = 5;
24const int btTransportLength = 64;
25const uint32_t maximumReadSize =
26 btTransportLength - (btReplyHdrLen + oem::groupMagicSize + crcSize);
Kun Yib61a88b2019-11-12 22:50:34 -080027constexpr auto defaultSessionTimeout = 10min;
Patrick Venture86c87f52019-02-01 14:44:15 -080028
Patrick Ventureef3aead2018-09-12 08:53:29 -070029struct SessionInfo
30{
31 SessionInfo() = default;
32 SessionInfo(const std::string& path, GenericBlobInterface* handler,
33 uint16_t flags) :
34 blobId(path),
35 handler(handler), flags(flags)
36 {
37 }
38 ~SessionInfo() = default;
39
40 std::string blobId;
41 GenericBlobInterface* handler;
42 uint16_t flags;
Kun Yi7fc52c82019-11-19 13:45:05 -080043
44 /* Initially set during open(). read/write/writeMeta/commit/stat operations
45 * would update it.
46 */
47 std::chrono::time_point<std::chrono::steady_clock> lastActionTime =
48 std::chrono::steady_clock::now();
Patrick Ventureef3aead2018-09-12 08:53:29 -070049};
50
51class ManagerInterface
52{
53 public:
54 virtual ~ManagerInterface() = default;
55
56 virtual bool
57 registerHandler(std::unique_ptr<GenericBlobInterface> handler) = 0;
58
59 virtual uint32_t buildBlobList() = 0;
60
61 virtual std::string getBlobId(uint32_t index) = 0;
62
63 virtual bool open(uint16_t flags, const std::string& path,
64 uint16_t* session) = 0;
65
Patrick Venture8bc11772019-06-04 07:20:24 -070066 virtual bool stat(const std::string& path, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070067
Patrick Venture8bc11772019-06-04 07:20:24 -070068 virtual bool stat(uint16_t session, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070069
70 virtual bool commit(uint16_t session, const std::vector<uint8_t>& data) = 0;
71
72 virtual bool close(uint16_t session) = 0;
73
74 virtual std::vector<uint8_t> read(uint16_t session, uint32_t offset,
75 uint32_t requestedSize) = 0;
76
77 virtual bool write(uint16_t session, uint32_t offset,
78 const std::vector<uint8_t>& data) = 0;
79
80 virtual bool deleteBlob(const std::string& path) = 0;
Patrick Venture5c4b17b2018-10-04 10:32:22 -070081
82 virtual bool writeMeta(uint16_t session, uint32_t offset,
83 const std::vector<uint8_t>& data) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070084};
85
86/**
87 * Blob Manager used to store handlers and sessions.
88 */
89class BlobManager : public ManagerInterface
90{
91 public:
Kun Yib61a88b2019-11-12 22:50:34 -080092 BlobManager(std::chrono::seconds sessionTimeout = defaultSessionTimeout) :
93 sessionTimeout(sessionTimeout)
Patrick Ventureef3aead2018-09-12 08:53:29 -070094 {
95 next = static_cast<uint16_t>(std::time(nullptr));
96 };
97
98 ~BlobManager() = default;
99 /* delete copy constructor & assignment operator, only support move
100 * operations.
101 */
102 BlobManager(const BlobManager&) = delete;
103 BlobManager& operator=(const BlobManager&) = delete;
104 BlobManager(BlobManager&&) = default;
105 BlobManager& operator=(BlobManager&&) = default;
106
107 /**
108 * Register a handler. We own the pointer.
109 *
110 * @param[in] handler - a pointer to a blob handler.
111 * @return bool - true if registered.
112 */
113 bool
114 registerHandler(std::unique_ptr<GenericBlobInterface> handler) override;
115
116 /**
117 * Builds the blobId list for enumeration.
118 *
119 * @return lowest value returned is 0, otherwise the number of
120 * blobIds.
121 */
122 uint32_t buildBlobList() override;
123
124 /**
125 * Grabs the blobId for the indexed blobId.
126 *
127 * @param[in] index - the index into the blobId cache.
128 * @return string - the blobId or empty string on failure.
129 */
130 std::string getBlobId(uint32_t index) override;
131
132 /**
133 * Attempts to open the file specified and associates with a session.
134 *
135 * @param[in] flags - the flags to pass to open.
136 * @param[in] path - the file path to open.
137 * @param[in,out] session - pointer to store the session on success.
138 * @return bool - true if able to open.
139 */
140 bool open(uint16_t flags, const std::string& path,
141 uint16_t* session) override;
142
143 /**
144 * Attempts to retrieve a BlobMeta for the specified path.
145 *
146 * @param[in] path - the file path for stat().
147 * @param[in,out] meta - a pointer to store the metadata.
148 * @return bool - true if able to retrieve the information.
149 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700150 bool stat(const std::string& path, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700151
152 /**
153 * Attempts to retrieve a BlobMeta for a given session.
154 *
155 * @param[in] session - the session for this command.
156 * @param[in,out] meta - a pointer to store the metadata.
157 * @return bool - true if able to retrieve the information.
158 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700159 bool stat(uint16_t session, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700160
161 /**
162 * Attempt to commit a blob for a given session.
163 *
164 * @param[in] session - the session for this command.
165 * @param[in] data - an optional commit blob.
166 * @return bool - true if the commit succeeds.
167 */
168 bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
169
170 /**
171 * Attempt to close a session. If the handler returns a failure
172 * in closing, the session is kept open.
173 *
174 * @param[in] session - the session for this command.
175 * @return bool - true if the session was closed.
176 */
177 bool close(uint16_t session) override;
178
179 /**
180 * Attempt to read bytes from the blob. If there's a failure, such as
181 * an invalid offset it'll just return 0 bytes.
182 *
183 * @param[in] session - the session for this command.
184 * @param[in] offset - the offset from which to read.
185 * @param[in] requestedSize - the number of bytes to try and read.
186 * @return the bytes read.
187 */
188 std::vector<uint8_t> read(uint16_t session, uint32_t offset,
189 uint32_t requestedSize) override;
190
191 /**
192 * Attempt to write to a blob. The manager does not track whether
193 * the session opened the file for writing.
194 *
195 * @param[in] session - the session for this command.
196 * @param[in] offset - the offset into the blob to write.
197 * @param[in] data - the bytes to write to the blob.
198 * @return bool - true if the write succeeded.
199 */
200 bool write(uint16_t session, uint32_t offset,
201 const std::vector<uint8_t>& data) override;
202
203 /**
204 * Attempt to delete a blobId. This method will just call the
205 * handler, which will return failure if the blob doesn't support
206 * deletion. This command will also fail if there are any open
207 * sessions against the specific blob.
208 *
209 * In the case where they specify a folder, such as /blob/skm where
210 * the "real" blobIds are /blob/skm/1, or /blob/skm/2, the manager
211 * may see there are on open sessions to that specific path and will
212 * call the handler. In this case, the handler is responsible for
213 * handling any checks or logic.
214 *
215 * @param[in] path - the blobId path.
216 * @return bool - true if delete was successful.
217 */
218 bool deleteBlob(const std::string& path) override;
219
220 /**
Patrick Venture5c4b17b2018-10-04 10:32:22 -0700221 * Attempt to write Metadata to a blob.
222 *
223 * @param[in] session - the session for this command.
224 * @param[in] offset - the offset into the blob to write.
225 * @param[in] data - the bytes to write to the blob.
226 * @return bool - true if the write succeeded.
227 */
228 bool writeMeta(uint16_t session, uint32_t offset,
229 const std::vector<uint8_t>& data) override;
230
231 /**
Patrick Ventureef3aead2018-09-12 08:53:29 -0700232 * Attempts to return a valid unique session id.
233 *
234 * @param[in,out] - pointer to the session.
235 * @return bool - true if able to allocate.
236 */
237 bool getSession(uint16_t* session);
238
Kun Yi9cd8f762019-11-22 20:11:42 -0800239 private:
Patrick Ventureef3aead2018-09-12 08:53:29 -0700240 /**
241 * Given a file path will return first handler to answer that it owns
242 * it.
243 *
244 * @param[in] path - the file path.
245 * @return pointer to the handler or nullptr if not found.
246 */
247 GenericBlobInterface* getHandler(const std::string& path);
248
249 /**
Kun Yi9cd8f762019-11-22 20:11:42 -0800250 * Given a session id, update session time and return a handler to take
Kun Yic892f4a2019-11-19 13:42:46 -0800251 * action
Patrick Ventureef3aead2018-09-12 08:53:29 -0700252 *
Kun Yic892f4a2019-11-19 13:42:46 -0800253 * @param[in] session - session ID
Kun Yi9cd8f762019-11-22 20:11:42 -0800254 * @param[in] requiredFlags - only return handler if the flags for this
Kun Yic892f4a2019-11-19 13:42:46 -0800255 * session contain these flags; defaults to any flag
256 * @return session handler, nullptr if cannot get handler
Patrick Ventureef3aead2018-09-12 08:53:29 -0700257 */
Kun Yi9cd8f762019-11-22 20:11:42 -0800258 GenericBlobInterface* getActionHandler(
Kun Yic892f4a2019-11-19 13:42:46 -0800259 uint16_t session,
Kun Yifea1d812019-11-14 11:38:44 -0800260 uint16_t requiredFlags = std::numeric_limits<uint16_t>::max());
Patrick Ventureef3aead2018-09-12 08:53:29 -0700261
Kun Yi9cd8f762019-11-22 20:11:42 -0800262 /**
263 * Helper method to erase a session from all maps
264 *
265 * @param[in] handler - handler pointer for lookup
266 * @param[in] session - session ID for lookup
267 * @return None
268 */
269 void eraseSession(GenericBlobInterface* const handler, uint16_t session);
270
271 /**
272 * For each session owned by this handler, call expire if it is stale
273 *
274 * @param[in] handler - handler pointer for lookup
275 * @return None
276 */
277 void cleanUpStaleSessions(GenericBlobInterface* const handler);
Kun Yib61a88b2019-11-12 22:50:34 -0800278
279 /* How long a session has to be inactive to be considered stale */
280 std::chrono::seconds sessionTimeout;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700281 /* The next session ID to use */
282 uint16_t next;
283 /* Temporary list of blobIds used for enumeration. */
284 std::vector<std::string> ids;
285 /* List of Blob handler. */
286 std::vector<std::unique_ptr<GenericBlobInterface>> handlers;
287 /* Mapping of session ids to blob handlers and the path used with open.
288 */
289 std::unordered_map<uint16_t, SessionInfo> sessions;
290 /* Mapping of open blobIds */
291 std::unordered_map<std::string, int> openFiles;
Kun Yib61a88b2019-11-12 22:50:34 -0800292 /* Map of handlers to their open sessions */
293 std::unordered_map<GenericBlobInterface*, std::set<uint16_t>> openSessions;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700294};
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700295
296/**
297 * @brief Gets a handle to the BlobManager.
298 *
299 * @return a pointer to the BlobManager instance.
300 */
Patrick Venture73eb6872018-10-01 18:37:34 -0700301ManagerInterface* getBlobManager();
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700302
Patrick Ventureef3aead2018-09-12 08:53:29 -0700303} // namespace blobs