blob: e7a9a975e1756b9979a3fc945d83df7c3e3497ef [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>
8#include <string>
9#include <unordered_map>
10#include <vector>
11
12namespace blobs
13{
14
Patrick Venture86c87f52019-02-01 14:44:15 -080015/* The maximum read size.
16 * NOTE: Once this can be dynamically determined, we'll switch to that method.
17 * Having this in a header allows it to used cleanly for now.
18 */
19const int crcSize = sizeof(uint16_t);
20const int btReplyHdrLen = 5;
21const int btTransportLength = 64;
22const uint32_t maximumReadSize =
23 btTransportLength - (btReplyHdrLen + oem::groupMagicSize + crcSize);
24
Patrick Ventureef3aead2018-09-12 08:53:29 -070025struct SessionInfo
26{
27 SessionInfo() = default;
28 SessionInfo(const std::string& path, GenericBlobInterface* handler,
29 uint16_t flags) :
30 blobId(path),
31 handler(handler), flags(flags)
32 {
33 }
34 ~SessionInfo() = default;
35
36 std::string blobId;
37 GenericBlobInterface* handler;
38 uint16_t flags;
Kun Yi7fc52c82019-11-19 13:45:05 -080039
40 /* Initially set during open(). read/write/writeMeta/commit/stat operations
41 * would update it.
42 */
43 std::chrono::time_point<std::chrono::steady_clock> lastActionTime =
44 std::chrono::steady_clock::now();
Patrick Ventureef3aead2018-09-12 08:53:29 -070045};
46
47class ManagerInterface
48{
49 public:
50 virtual ~ManagerInterface() = default;
51
52 virtual bool
53 registerHandler(std::unique_ptr<GenericBlobInterface> handler) = 0;
54
55 virtual uint32_t buildBlobList() = 0;
56
57 virtual std::string getBlobId(uint32_t index) = 0;
58
59 virtual bool open(uint16_t flags, const std::string& path,
60 uint16_t* session) = 0;
61
Patrick Venture8bc11772019-06-04 07:20:24 -070062 virtual bool stat(const std::string& path, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070063
Patrick Venture8bc11772019-06-04 07:20:24 -070064 virtual bool stat(uint16_t session, BlobMeta* meta) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070065
66 virtual bool commit(uint16_t session, const std::vector<uint8_t>& data) = 0;
67
68 virtual bool close(uint16_t session) = 0;
69
70 virtual std::vector<uint8_t> read(uint16_t session, uint32_t offset,
71 uint32_t requestedSize) = 0;
72
73 virtual bool write(uint16_t session, uint32_t offset,
74 const std::vector<uint8_t>& data) = 0;
75
76 virtual bool deleteBlob(const std::string& path) = 0;
Patrick Venture5c4b17b2018-10-04 10:32:22 -070077
78 virtual bool writeMeta(uint16_t session, uint32_t offset,
79 const std::vector<uint8_t>& data) = 0;
Patrick Ventureef3aead2018-09-12 08:53:29 -070080};
81
82/**
83 * Blob Manager used to store handlers and sessions.
84 */
85class BlobManager : public ManagerInterface
86{
87 public:
88 BlobManager()
89 {
90 next = static_cast<uint16_t>(std::time(nullptr));
91 };
92
93 ~BlobManager() = default;
94 /* delete copy constructor & assignment operator, only support move
95 * operations.
96 */
97 BlobManager(const BlobManager&) = delete;
98 BlobManager& operator=(const BlobManager&) = delete;
99 BlobManager(BlobManager&&) = default;
100 BlobManager& operator=(BlobManager&&) = default;
101
102 /**
103 * Register a handler. We own the pointer.
104 *
105 * @param[in] handler - a pointer to a blob handler.
106 * @return bool - true if registered.
107 */
108 bool
109 registerHandler(std::unique_ptr<GenericBlobInterface> handler) override;
110
111 /**
112 * Builds the blobId list for enumeration.
113 *
114 * @return lowest value returned is 0, otherwise the number of
115 * blobIds.
116 */
117 uint32_t buildBlobList() override;
118
119 /**
120 * Grabs the blobId for the indexed blobId.
121 *
122 * @param[in] index - the index into the blobId cache.
123 * @return string - the blobId or empty string on failure.
124 */
125 std::string getBlobId(uint32_t index) override;
126
127 /**
128 * Attempts to open the file specified and associates with a session.
129 *
130 * @param[in] flags - the flags to pass to open.
131 * @param[in] path - the file path to open.
132 * @param[in,out] session - pointer to store the session on success.
133 * @return bool - true if able to open.
134 */
135 bool open(uint16_t flags, const std::string& path,
136 uint16_t* session) override;
137
138 /**
139 * Attempts to retrieve a BlobMeta for the specified path.
140 *
141 * @param[in] path - the file path for stat().
142 * @param[in,out] meta - a pointer to store the metadata.
143 * @return bool - true if able to retrieve the information.
144 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700145 bool stat(const std::string& path, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700146
147 /**
148 * Attempts to retrieve a BlobMeta for a given session.
149 *
150 * @param[in] session - the session for this command.
151 * @param[in,out] meta - a pointer to store the metadata.
152 * @return bool - true if able to retrieve the information.
153 */
Patrick Venture8bc11772019-06-04 07:20:24 -0700154 bool stat(uint16_t session, BlobMeta* meta) override;
Patrick Ventureef3aead2018-09-12 08:53:29 -0700155
156 /**
157 * Attempt to commit a blob for a given session.
158 *
159 * @param[in] session - the session for this command.
160 * @param[in] data - an optional commit blob.
161 * @return bool - true if the commit succeeds.
162 */
163 bool commit(uint16_t session, const std::vector<uint8_t>& data) override;
164
165 /**
166 * Attempt to close a session. If the handler returns a failure
167 * in closing, the session is kept open.
168 *
169 * @param[in] session - the session for this command.
170 * @return bool - true if the session was closed.
171 */
172 bool close(uint16_t session) override;
173
174 /**
175 * Attempt to read bytes from the blob. If there's a failure, such as
176 * an invalid offset it'll just return 0 bytes.
177 *
178 * @param[in] session - the session for this command.
179 * @param[in] offset - the offset from which to read.
180 * @param[in] requestedSize - the number of bytes to try and read.
181 * @return the bytes read.
182 */
183 std::vector<uint8_t> read(uint16_t session, uint32_t offset,
184 uint32_t requestedSize) override;
185
186 /**
187 * Attempt to write to a blob. The manager does not track whether
188 * the session opened the file for writing.
189 *
190 * @param[in] session - the session for this command.
191 * @param[in] offset - the offset into the blob to write.
192 * @param[in] data - the bytes to write to the blob.
193 * @return bool - true if the write succeeded.
194 */
195 bool write(uint16_t session, uint32_t offset,
196 const std::vector<uint8_t>& data) override;
197
198 /**
199 * Attempt to delete a blobId. This method will just call the
200 * handler, which will return failure if the blob doesn't support
201 * deletion. This command will also fail if there are any open
202 * sessions against the specific blob.
203 *
204 * In the case where they specify a folder, such as /blob/skm where
205 * the "real" blobIds are /blob/skm/1, or /blob/skm/2, the manager
206 * may see there are on open sessions to that specific path and will
207 * call the handler. In this case, the handler is responsible for
208 * handling any checks or logic.
209 *
210 * @param[in] path - the blobId path.
211 * @return bool - true if delete was successful.
212 */
213 bool deleteBlob(const std::string& path) override;
214
215 /**
Patrick Venture5c4b17b2018-10-04 10:32:22 -0700216 * Attempt to write Metadata to a blob.
217 *
218 * @param[in] session - the session for this command.
219 * @param[in] offset - the offset into the blob to write.
220 * @param[in] data - the bytes to write to the blob.
221 * @return bool - true if the write succeeded.
222 */
223 bool writeMeta(uint16_t session, uint32_t offset,
224 const std::vector<uint8_t>& data) override;
225
226 /**
Patrick Ventureef3aead2018-09-12 08:53:29 -0700227 * Attempts to return a valid unique session id.
228 *
229 * @param[in,out] - pointer to the session.
230 * @return bool - true if able to allocate.
231 */
232 bool getSession(uint16_t* session);
233
234 /**
235 * Given a file path will return first handler to answer that it owns
236 * it.
237 *
238 * @param[in] path - the file path.
239 * @return pointer to the handler or nullptr if not found.
240 */
241 GenericBlobInterface* getHandler(const std::string& path);
242
243 /**
Kun Yic892f4a2019-11-19 13:42:46 -0800244 * Given a session id, update session time and return a handle to take
245 * action
Patrick Ventureef3aead2018-09-12 08:53:29 -0700246 *
Kun Yic892f4a2019-11-19 13:42:46 -0800247 * @param[in] session - session ID
248 * @param[in] requiredFlags - only return handle if the flags for this
249 * session contain these flags; defaults to any flag
250 * @return session handler, nullptr if cannot get handler
Patrick Ventureef3aead2018-09-12 08:53:29 -0700251 */
Kun Yic892f4a2019-11-19 13:42:46 -0800252 GenericBlobInterface* getActionHandle(
253 uint16_t session,
254 uint16_t requiredFlags = std::numeric_limits<uint16_t>::max())
255 {
256 if (auto item = sessions.find(session);
257 item != sessions.end() && (item->second.flags & requiredFlags))
258 {
Kun Yi7fc52c82019-11-19 13:45:05 -0800259 item->second.lastActionTime = std::chrono::steady_clock::now();
Kun Yic892f4a2019-11-19 13:42:46 -0800260 return item->second.handler;
261 }
262 return nullptr;
263 }
Patrick Ventureef3aead2018-09-12 08:53:29 -0700264
265 /**
266 * Given a session id will return associated path.
267 *
268 * @param[in] session - the session.
269 * @return the path or "" on failure.
270 */
271 std::string getPath(uint16_t session) const;
272
273 private:
274 void incrementOpen(const std::string& path);
275 void decrementOpen(const std::string& path);
276 int getOpen(const std::string& path) const;
277
278 /* The next session ID to use */
279 uint16_t next;
280 /* Temporary list of blobIds used for enumeration. */
281 std::vector<std::string> ids;
282 /* List of Blob handler. */
283 std::vector<std::unique_ptr<GenericBlobInterface>> handlers;
284 /* Mapping of session ids to blob handlers and the path used with open.
285 */
286 std::unordered_map<uint16_t, SessionInfo> sessions;
287 /* Mapping of open blobIds */
288 std::unordered_map<std::string, int> openFiles;
289};
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700290
291/**
292 * @brief Gets a handle to the BlobManager.
293 *
294 * @return a pointer to the BlobManager instance.
295 */
Patrick Venture73eb6872018-10-01 18:37:34 -0700296ManagerInterface* getBlobManager();
Patrick Ventureb3e07e22018-09-27 15:11:57 -0700297
Patrick Ventureef3aead2018-09-12 08:53:29 -0700298} // namespace blobs