blob: 0b77f809237cb72a4dd5cb8cb32fe8e1af421d9a [file] [log] [blame]
Jason Lingc78bfc82020-11-05 18:58:16 -08001#include "version_handler.hpp"
2
William A. Kennington IIIabf17352020-12-22 21:07:11 -08003#include <utility>
4#include <vector>
5
Jason Lingc78bfc82020-11-05 18:58:16 -08006namespace ipmi_flash
7{
William A. Kennington IIIabf17352020-12-22 21:07:11 -08008
9VersionBlobHandler::VersionBlobHandler(
10 std::vector<HandlerConfig<ActionPack>>&& configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080011{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080012 for (auto& config : configs)
Jason Lingc78bfc82020-11-05 18:58:16 -080013 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080014 auto info = std::make_unique<BlobInfo>();
15 info->blobId = std::move(config.blobId);
16 info->actions = std::move(config.actions);
17 info->handler = std::move(config.handler);
William A. Kennington III9936c452020-12-23 23:31:23 -080018 info->actions->onOpen->setCallback(
19 [infoP = info.get()](TriggerableActionInterface& tai) {
20 auto data =
21 std::make_shared<std::optional<std::vector<uint8_t>>>();
22 do
23 {
24 if (tai.status() != ActionStatus::success)
25 {
26 fprintf(stderr, "Version file unit failed for %s\n",
27 infoP->blobId.c_str());
28 continue;
29 }
30 if (!infoP->handler->open("", std::ios::in))
31 {
32 fprintf(stderr, "Opening version file failed for %s\n",
33 infoP->blobId.c_str());
34 continue;
35 }
36 auto d = infoP->handler->read(
37 0, std::numeric_limits<uint32_t>::max());
38 infoP->handler->close();
39 if (!d)
40 {
41 fprintf(stderr, "Reading version file failed for %s\n",
42 infoP->blobId.c_str());
43 continue;
44 }
45 *data = std::move(d);
46 } while (false);
47 for (auto sessionP : infoP->sessionsToUpdate)
48 {
49 sessionP->data = data;
50 }
51 infoP->sessionsToUpdate.clear();
52 });
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080053 if (!blobInfoMap.try_emplace(info->blobId, std::move(info)).second)
William A. Kennington IIIabf17352020-12-22 21:07:11 -080054 {
55 fprintf(stderr, "Ignoring duplicate config for %s\n",
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080056 info->blobId.c_str());
William A. Kennington IIIabf17352020-12-22 21:07:11 -080057 }
Jason Lingc78bfc82020-11-05 18:58:16 -080058 }
Jason Lingc78bfc82020-11-05 18:58:16 -080059}
60
61bool VersionBlobHandler::canHandleBlob(const std::string& path)
62{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080063 return blobInfoMap.find(path) != blobInfoMap.end();
Jason Lingc78bfc82020-11-05 18:58:16 -080064}
65
66std::vector<std::string> VersionBlobHandler::getBlobIds()
67{
William A. Kennington IIIabf17352020-12-22 21:07:11 -080068 std::vector<std::string> ret;
69 for (const auto& [key, _] : blobInfoMap)
70 {
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -080071 ret.emplace_back(key);
William A. Kennington IIIabf17352020-12-22 21:07:11 -080072 }
73 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -080074}
75
76/**
77 * deleteBlob - does nothing, always fails
78 */
79bool VersionBlobHandler::deleteBlob(const std::string& path)
80{
81 return false;
82}
83
84bool VersionBlobHandler::stat(const std::string& path, blobs::BlobMeta* meta)
85{
William A. Kennington IIIeba0c342021-01-12 14:23:01 -080086 return false;
Jason Lingc78bfc82020-11-05 18:58:16 -080087}
88
89bool VersionBlobHandler::open(uint16_t session, uint16_t flags,
90 const std::string& path)
91{
Jason Lingc78bfc82020-11-05 18:58:16 -080092 /* only reads are supported, check if blob is handled and make sure
93 * the blob isn't already opened
94 */
95 if (flags != blobs::read)
96 {
97 fprintf(stderr, "open %s fail: unsupported flags(0x%04X.)\n",
98 path.c_str(), flags);
Jason Lingc78bfc82020-11-05 18:58:16 -080099 return false;
100 }
Jason Lingc78bfc82020-11-05 18:58:16 -0800101
William A. Kennington III9936c452020-12-23 23:31:23 -0800102 auto info = std::make_unique<SessionInfo>();
103 info->blob = blobInfoMap.at(path).get();
104 info->blob->sessionsToUpdate.emplace(info.get());
105 if (info->blob->sessionsToUpdate.size() == 1 &&
106 !info->blob->actions->onOpen->trigger())
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800107 {
108 fprintf(stderr, "open %s fail: onOpen trigger failed\n", path.c_str());
William A. Kennington III9936c452020-12-23 23:31:23 -0800109 info->blob->sessionsToUpdate.erase(info.get());
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800110 return false;
111 }
William A. Kennington III007c0162020-12-23 16:36:22 -0800112
William A. Kennington III9936c452020-12-23 23:31:23 -0800113 sessionInfoMap[session] = std::move(info);
William A. Kennington IIIb45eb5e2020-12-23 11:47:05 -0800114 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -0800115}
116
117std::vector<uint8_t> VersionBlobHandler::read(uint16_t session, uint32_t offset,
118 uint32_t requestedSize)
119{
William A. Kennington III9936c452020-12-23 23:31:23 -0800120 auto& data = sessionInfoMap.at(session)->data;
121 if (data == nullptr || !*data || (*data)->size() < offset)
Jason Lingc78bfc82020-11-05 18:58:16 -0800122 {
Jason Lingc78bfc82020-11-05 18:58:16 -0800123 return {};
124 }
William A. Kennington III9936c452020-12-23 23:31:23 -0800125 std::vector<uint8_t> ret(
126 std::min<size_t>(requestedSize, (*data)->size() - offset));
127 std::memcpy(&ret[0], &(**data)[offset], ret.size());
128 return ret;
Jason Lingc78bfc82020-11-05 18:58:16 -0800129}
130
131bool VersionBlobHandler::close(uint16_t session)
132{
William A. Kennington III9936c452020-12-23 23:31:23 -0800133 auto it = sessionInfoMap.find(session);
134 if (it == sessionInfoMap.end())
Jason Lingc78bfc82020-11-05 18:58:16 -0800135 {
136 return false;
137 }
William A. Kennington III9936c452020-12-23 23:31:23 -0800138 auto& info = *it->second;
139 info.blob->sessionsToUpdate.erase(&info);
140 if (info.blob->sessionsToUpdate.empty())
141 {
142 info.blob->actions->onOpen->abort();
143 }
144 sessionInfoMap.erase(it);
145 return true;
Jason Lingc78bfc82020-11-05 18:58:16 -0800146}
William A. Kennington IIIc5b901d2020-12-23 17:07:20 -0800147
148bool VersionBlobHandler::stat(uint16_t session, blobs::BlobMeta* meta)
149{
William A. Kennington IIIeba0c342021-01-12 14:23:01 -0800150 const auto& data = sessionInfoMap.at(session)->data;
151 if (data == nullptr)
152 {
153 meta->blobState = blobs::StateFlags::committing;
154 meta->size = 0;
155 }
156 else if (!*data)
157 {
158 meta->blobState = blobs::StateFlags::commit_error;
159 meta->size = 0;
160 }
161 else
162 {
163 meta->blobState =
164 blobs::StateFlags::committed | blobs::StateFlags::open_read;
165 meta->size = (*data)->size();
166 }
167 return true;
William A. Kennington IIIc5b901d2020-12-23 17:07:20 -0800168}
169
170bool VersionBlobHandler::expire(uint16_t session)
171{
172 close(session);
173 return true;
174}
175
Jason Lingc78bfc82020-11-05 18:58:16 -0800176} // namespace ipmi_flash