1c78bfc82SJason Ling #include "version_handler.hpp"
2c78bfc82SJason Ling
3cc7f385bSWilliam A. Kennington III #include <algorithm>
4cc7f385bSWilliam A. Kennington III #include <cstring>
5cc7f385bSWilliam A. Kennington III #include <ios>
6cc7f385bSWilliam A. Kennington III #include <limits>
7cc7f385bSWilliam A. Kennington III #include <memory>
8cc7f385bSWilliam A. Kennington III #include <optional>
9abf17354SWilliam A. Kennington III #include <utility>
10abf17354SWilliam A. Kennington III #include <vector>
11abf17354SWilliam A. Kennington III
12c78bfc82SJason Ling namespace ipmi_flash
13c78bfc82SJason Ling {
14abf17354SWilliam A. Kennington III
VersionBlobHandler(std::vector<HandlerConfig<ActionPack>> && configs)15abf17354SWilliam A. Kennington III VersionBlobHandler::VersionBlobHandler(
16abf17354SWilliam A. Kennington III std::vector<HandlerConfig<ActionPack>>&& configs)
17c78bfc82SJason Ling {
18abf17354SWilliam A. Kennington III for (auto& config : configs)
19c78bfc82SJason Ling {
20b45eb5eeSWilliam A. Kennington III auto info = std::make_unique<BlobInfo>();
21b45eb5eeSWilliam A. Kennington III info->blobId = std::move(config.blobId);
22b45eb5eeSWilliam A. Kennington III info->actions = std::move(config.actions);
23b45eb5eeSWilliam A. Kennington III info->handler = std::move(config.handler);
249936c456SWilliam A. Kennington III info->actions->onOpen->setCallback(
259936c456SWilliam A. Kennington III [infoP = info.get()](TriggerableActionInterface& tai) {
26*42a44c28SPatrick Williams auto data =
27*42a44c28SPatrick Williams std::make_shared<std::optional<std::vector<uint8_t>>>();
289936c456SWilliam A. Kennington III do
299936c456SWilliam A. Kennington III {
309936c456SWilliam A. Kennington III if (tai.status() != ActionStatus::success)
319936c456SWilliam A. Kennington III {
329936c456SWilliam A. Kennington III fprintf(stderr, "Version file unit failed for %s\n",
339936c456SWilliam A. Kennington III infoP->blobId.c_str());
349936c456SWilliam A. Kennington III continue;
359936c456SWilliam A. Kennington III }
369936c456SWilliam A. Kennington III if (!infoP->handler->open("", std::ios::in))
379936c456SWilliam A. Kennington III {
389936c456SWilliam A. Kennington III fprintf(stderr, "Opening version file failed for %s\n",
399936c456SWilliam A. Kennington III infoP->blobId.c_str());
409936c456SWilliam A. Kennington III continue;
419936c456SWilliam A. Kennington III }
429936c456SWilliam A. Kennington III auto d = infoP->handler->read(
439936c456SWilliam A. Kennington III 0, std::numeric_limits<uint32_t>::max());
449936c456SWilliam A. Kennington III infoP->handler->close();
459936c456SWilliam A. Kennington III if (!d)
469936c456SWilliam A. Kennington III {
479936c456SWilliam A. Kennington III fprintf(stderr, "Reading version file failed for %s\n",
489936c456SWilliam A. Kennington III infoP->blobId.c_str());
499936c456SWilliam A. Kennington III continue;
509936c456SWilliam A. Kennington III }
519936c456SWilliam A. Kennington III *data = std::move(d);
529936c456SWilliam A. Kennington III } while (false);
539936c456SWilliam A. Kennington III for (auto sessionP : infoP->sessionsToUpdate)
549936c456SWilliam A. Kennington III {
559936c456SWilliam A. Kennington III sessionP->data = data;
569936c456SWilliam A. Kennington III }
579936c456SWilliam A. Kennington III infoP->sessionsToUpdate.clear();
589936c456SWilliam A. Kennington III });
59b45eb5eeSWilliam A. Kennington III if (!blobInfoMap.try_emplace(info->blobId, std::move(info)).second)
60abf17354SWilliam A. Kennington III {
61abf17354SWilliam A. Kennington III fprintf(stderr, "Ignoring duplicate config for %s\n",
62b45eb5eeSWilliam A. Kennington III info->blobId.c_str());
63c78bfc82SJason Ling }
64abf17354SWilliam A. Kennington III }
65c78bfc82SJason Ling }
66c78bfc82SJason Ling
canHandleBlob(const std::string & path)67c78bfc82SJason Ling bool VersionBlobHandler::canHandleBlob(const std::string& path)
68c78bfc82SJason Ling {
69abf17354SWilliam A. Kennington III return blobInfoMap.find(path) != blobInfoMap.end();
70c78bfc82SJason Ling }
71c78bfc82SJason Ling
getBlobIds()72c78bfc82SJason Ling std::vector<std::string> VersionBlobHandler::getBlobIds()
73c78bfc82SJason Ling {
74abf17354SWilliam A. Kennington III std::vector<std::string> ret;
75abf17354SWilliam A. Kennington III for (const auto& [key, _] : blobInfoMap)
76abf17354SWilliam A. Kennington III {
77b45eb5eeSWilliam A. Kennington III ret.emplace_back(key);
78abf17354SWilliam A. Kennington III }
79abf17354SWilliam A. Kennington III return ret;
80c78bfc82SJason Ling }
81c78bfc82SJason Ling
82c78bfc82SJason Ling /**
83c78bfc82SJason Ling * deleteBlob - does nothing, always fails
84c78bfc82SJason Ling */
deleteBlob(const std::string &)85b487eb47SWilly Tu bool VersionBlobHandler::deleteBlob(const std::string&)
86c78bfc82SJason Ling {
87c78bfc82SJason Ling return false;
88c78bfc82SJason Ling }
89c78bfc82SJason Ling
stat(const std::string &,blobs::BlobMeta *)90b487eb47SWilly Tu bool VersionBlobHandler::stat(const std::string&, blobs::BlobMeta*)
91c78bfc82SJason Ling {
92eba0c34aSWilliam A. Kennington III return false;
93c78bfc82SJason Ling }
94c78bfc82SJason Ling
open(uint16_t session,uint16_t flags,const std::string & path)95c78bfc82SJason Ling bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
96c78bfc82SJason Ling const std::string& path)
97c78bfc82SJason Ling {
98c78bfc82SJason Ling /* only reads are supported, check if blob is handled and make sure
99c78bfc82SJason Ling * the blob isn't already opened
100c78bfc82SJason Ling */
101c78bfc82SJason Ling if (flags != blobs::read)
102c78bfc82SJason Ling {
103c78bfc82SJason Ling fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
104c78bfc82SJason Ling path.c_str(), flags);
105c78bfc82SJason Ling return false;
106c78bfc82SJason Ling }
107c78bfc82SJason Ling
1089936c456SWilliam A. Kennington III auto info = std::make_unique<SessionInfo>();
1099936c456SWilliam A. Kennington III info->blob = blobInfoMap.at(path).get();
1109936c456SWilliam A. Kennington III info->blob->sessionsToUpdate.emplace(info.get());
1119936c456SWilliam A. Kennington III if (info->blob->sessionsToUpdate.size() == 1 &&
1129936c456SWilliam A. Kennington III !info->blob->actions->onOpen->trigger())
113c78bfc82SJason Ling {
114b45eb5eeSWilliam A. Kennington III fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
1159936c456SWilliam A. Kennington III info->blob->sessionsToUpdate.erase(info.get());
116c78bfc82SJason Ling return false;
117c78bfc82SJason Ling }
118007c0166SWilliam A. Kennington III
1199936c456SWilliam A. Kennington III sessionInfoMap[session] = std::move(info);
120c78bfc82SJason Ling return true;
121c78bfc82SJason Ling }
122c78bfc82SJason Ling
read(uint16_t session,uint32_t offset,uint32_t requestedSize)123c78bfc82SJason Ling std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
124c78bfc82SJason Ling uint32_t requestedSize)
125c78bfc82SJason Ling {
1269936c456SWilliam A. Kennington III auto& data = sessionInfoMap.at(session)->data;
1270674a6d7SWilliam A. Kennington III if (data == nullptr || !*data)
1280674a6d7SWilliam A. Kennington III {
1290674a6d7SWilliam A. Kennington III throw std::runtime_error("Version data not ready for read");
1300674a6d7SWilliam A. Kennington III }
1310674a6d7SWilliam A. Kennington III if ((*data)->size() < offset)
132c78bfc82SJason Ling {
133c78bfc82SJason Ling return {};
134c78bfc82SJason Ling }
1359936c456SWilliam A. Kennington III std::vector<uint8_t> ret(
1369936c456SWilliam A. Kennington III std::min<size_t>(requestedSize, (*data)->size() - offset));
1379936c456SWilliam A. Kennington III std::memcpy(&ret[0], &(**data)[offset], ret.size());
1389936c456SWilliam A. Kennington III return ret;
139c78bfc82SJason Ling }
140c78bfc82SJason Ling
close(uint16_t session)141c78bfc82SJason Ling bool VersionBlobHandler::close(uint16_t session)
142c78bfc82SJason Ling {
1439936c456SWilliam A. Kennington III auto it = sessionInfoMap.find(session);
1449936c456SWilliam A. Kennington III if (it == sessionInfoMap.end())
145c78bfc82SJason Ling {
146c78bfc82SJason Ling return false;
147c78bfc82SJason Ling }
1489936c456SWilliam A. Kennington III auto& info = *it->second;
1499936c456SWilliam A. Kennington III info.blob->sessionsToUpdate.erase(&info);
1509936c456SWilliam A. Kennington III if (info.blob->sessionsToUpdate.empty())
1519936c456SWilliam A. Kennington III {
1529936c456SWilliam A. Kennington III info.blob->actions->onOpen->abort();
1539936c456SWilliam A. Kennington III }
1549936c456SWilliam A. Kennington III sessionInfoMap.erase(it);
1559936c456SWilliam A. Kennington III return true;
156c78bfc82SJason Ling }
157c5b901d8SWilliam A. Kennington III
stat(uint16_t session,blobs::BlobMeta * meta)158c5b901d8SWilliam A. Kennington III bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
159c5b901d8SWilliam A. Kennington III {
160eba0c34aSWilliam A. Kennington III const auto& data = sessionInfoMap.at(session)->data;
161eba0c34aSWilliam A. Kennington III if (data == nullptr)
162eba0c34aSWilliam A. Kennington III {
163eba0c34aSWilliam A. Kennington III meta->blobState = blobs::StateFlags::committing;
164eba0c34aSWilliam A. Kennington III meta->size = 0;
165eba0c34aSWilliam A. Kennington III }
166eba0c34aSWilliam A. Kennington III else if (!*data)
167eba0c34aSWilliam A. Kennington III {
168eba0c34aSWilliam A. Kennington III meta->blobState = blobs::StateFlags::commit_error;
169eba0c34aSWilliam A. Kennington III meta->size = 0;
170eba0c34aSWilliam A. Kennington III }
171eba0c34aSWilliam A. Kennington III else
172eba0c34aSWilliam A. Kennington III {
1731038836cSPatrick Williams meta->blobState = blobs::StateFlags::committed |
1741038836cSPatrick Williams blobs::StateFlags::open_read;
175eba0c34aSWilliam A. Kennington III meta->size = (*data)->size();
176eba0c34aSWilliam A. Kennington III }
177eba0c34aSWilliam A. Kennington III return true;
178c5b901d8SWilliam A. Kennington III }
179c5b901d8SWilliam A. Kennington III
expire(uint16_t session)180c5b901d8SWilliam A. Kennington III bool VersionBlobHandler::expire(uint16_t session)
181c5b901d8SWilliam A. Kennington III {
182c5b901d8SWilliam A. Kennington III close(session);
183c5b901d8SWilliam A. Kennington III return true;
184c5b901d8SWilliam A. Kennington III }
185c5b901d8SWilliam A. Kennington III
186c78bfc82SJason Ling } // namespace ipmi_flash
187