blob: b6ac545752265ad1f4a0d51233a9caf812492d9f [file] [log] [blame]
Matt Spinler89fa0822019-07-17 13:54:30 -05001#pragma once
2#include "bcd_time.hpp"
3#include "pel.hpp"
4
5#include <algorithm>
Matt Spinler0ff00482019-11-06 16:19:46 -06006#include <bitset>
Matt Spinler89fa0822019-07-17 13:54:30 -05007#include <filesystem>
Matt Spinler475e5742019-07-18 16:09:49 -05008#include <map>
Matt Spinler89fa0822019-07-17 13:54:30 -05009
10namespace openpower
11{
12namespace pels
13{
14
15/**
16 * @class Repository
17 *
18 * The class handles saving and retrieving PELs on the BMC.
19 */
20class Repository
21{
22 public:
Matt Spinler475e5742019-07-18 16:09:49 -050023 /**
Matt Spinler0ff00482019-11-06 16:19:46 -060024 * @brief Structure of commonly used PEL attributes.
25 */
26 struct PELAttributes
27 {
28 std::filesystem::path path;
29 std::bitset<16> actionFlags;
Matt Spinler346f99a2019-11-21 13:06:35 -060030 TransmissionState hostState;
31 TransmissionState hmcState;
Matt Spinler0ff00482019-11-06 16:19:46 -060032
33 PELAttributes() = delete;
34
Matt Spinler346f99a2019-11-21 13:06:35 -060035 PELAttributes(const std::filesystem::path& p, uint16_t flags,
36 TransmissionState hostState, TransmissionState hmcState) :
37 path(p),
38 actionFlags(flags), hostState(hostState), hmcState(hmcState)
Matt Spinler0ff00482019-11-06 16:19:46 -060039 {
40 }
41 };
42
43 /**
Matt Spinler475e5742019-07-18 16:09:49 -050044 * @brief A structure that holds both the PEL and corresponding
45 * OpenBMC IDs.
46 * Used for correlating the IDs with their data files for quick
47 * lookup. To find a PEL based on just one of the IDs, just use
48 * the constructor that takes that ID.
49 */
50 struct LogID
51 {
52 struct Pel
53 {
54 uint32_t id;
55 explicit Pel(uint32_t i) : id(i)
56 {
57 }
58 };
59 struct Obmc
60 {
61 uint32_t id;
62 explicit Obmc(uint32_t i) : id(i)
63 {
64 }
65 };
66
67 Pel pelID;
68
69 Obmc obmcID;
70
71 LogID(Pel pel, Obmc obmc) : pelID(pel), obmcID(obmc)
72 {
73 }
74
75 explicit LogID(Pel id) : pelID(id), obmcID(0)
76 {
77 }
78
79 explicit LogID(Obmc id) : pelID(0), obmcID(id)
80 {
81 }
82
83 LogID() = delete;
84
85 /**
86 * @brief A == operator that will match on either ID
87 * being equal if the other is zero, so that
88 * one can look up a PEL with just one of the IDs.
89 */
90 bool operator==(const LogID& id) const
91 {
92 if (id.pelID.id != 0)
93 {
94 return id.pelID.id == pelID.id;
95 }
96 if (id.obmcID.id != 0)
97 {
98 return id.obmcID.id == obmcID.id;
99 }
100 return false;
101 }
102
103 bool operator<(const LogID& id) const
104 {
105 return pelID.id < id.pelID.id;
106 }
107 };
108
Matt Spinler89fa0822019-07-17 13:54:30 -0500109 Repository() = delete;
110 ~Repository() = default;
111 Repository(const Repository&) = default;
112 Repository& operator=(const Repository&) = default;
113 Repository(Repository&&) = default;
114 Repository& operator=(Repository&&) = default;
115
116 /**
117 * @brief Constructor
118 *
119 * @param[in] basePath - the base filesystem path for the repository
120 */
121 Repository(const std::filesystem::path& basePath);
122
123 /**
124 * @brief Adds a PEL to the repository
125 *
126 * Throws File.Error.Open or File.Error.Write exceptions on failure
127 *
128 * @param[in] pel - the PEL to add
129 */
130 void add(std::unique_ptr<PEL>& pel);
131
132 /**
Matt Spinler475e5742019-07-18 16:09:49 -0500133 * @brief Removes a PEL from the repository
134 *
135 * @param[in] id - the ID (either the pel ID, OBMC ID, or both) to remove
136 */
137 void remove(const LogID& id);
138
139 /**
Matt Spinler89fa0822019-07-17 13:54:30 -0500140 * @brief Generates the filename to use for the PEL ID and BCDTime.
141 *
142 * @param[in] pelID - the PEL ID
143 * @param[in] time - the BCD time
144 *
145 * @return string - A filename string of <BCD_time>_<pelID>
146 */
147 static std::string getPELFilename(uint32_t pelID, const BCDTime& time);
148
Matt Spinler475e5742019-07-18 16:09:49 -0500149 /**
150 * @brief Returns true if the PEL with the specified ID is in the repo.
151 *
152 * @param[in] id - the ID (either the pel ID, OBMC ID, or both)
153 * @return bool - true if that PEL is present
154 */
155 inline bool hasPEL(const LogID& id)
156 {
Matt Spinler0ff00482019-11-06 16:19:46 -0600157 return findPEL(id) != _pelAttributes.end();
Matt Spinler475e5742019-07-18 16:09:49 -0500158 }
159
Matt Spinler2813f362019-07-19 12:45:28 -0500160 /**
161 * @brief Returns the PEL data based on its ID.
162 *
163 * If the data can't be found for that ID, then the optional object
164 * will be empty.
165 *
166 * @param[in] id - the LogID to get the PEL for, which can be either a
167 * PEL ID or OpenBMC log ID.
168 * @return std::optional<std::vector<uint8_t>> - the PEL data
169 */
170 std::optional<std::vector<uint8_t>> getPELData(const LogID& id);
171
Matt Spinler1ea78802019-11-01 13:04:59 -0500172 using ForEachFunc = std::function<bool(const PEL&)>;
173
174 /**
175 * @brief Run a user defined function on every PEL in the repository.
176 *
177 * ForEachFunc takes a const PEL reference, and should return
178 * true to stop iterating and return out of for_each.
179 *
180 * For example, to save up to 100 IDs in the repo into a vector:
181 *
182 * std::vector<uint32_t> ids;
183 * ForEachFunc f = [&ids](const PEL& pel) {
184 * ids.push_back(pel.id());
185 * return ids.size() == 100 ? true : false;
186 * };
187 *
188 * @param[in] func - The function to run.
189 */
190 void for_each(ForEachFunc func) const;
191
Matt Spinler421f6532019-11-06 15:40:45 -0600192 using AddCallback = std::function<void(const PEL&)>;
193
194 /**
195 * @brief Subscribe to PELs being added to the repository.
196 *
197 * Every time a PEL is added to the repository, the provided
198 * function will be called with the new PEL as the argument.
199 *
200 * The function must be of type void(const PEL&).
201 *
202 * @param[in] name - The subscription name
203 * @param[in] func - The callback function
204 */
205 void subscribeToAdds(const std::string& name, AddCallback func)
206 {
207 if (_addSubscriptions.find(name) == _addSubscriptions.end())
208 {
209 _addSubscriptions.emplace(name, func);
210 }
211 }
212
213 /**
214 * @brief Unsubscribe from new PELs.
215 *
216 * @param[in] name - The subscription name
217 */
218 void unsubscribeFromAdds(const std::string& name)
219 {
220 _addSubscriptions.erase(name);
221 }
222
223 using DeleteCallback = std::function<void(uint32_t)>;
224
225 /**
226 * @brief Subscribe to PELs being deleted from the repository.
227 *
228 * Every time a PEL is deleted from the repository, the provided
229 * function will be called with the PEL ID as the argument.
230 *
231 * The function must be of type void(const uint32_t).
232 *
233 * @param[in] name - The subscription name
234 * @param[in] func - The callback function
235 */
236 void subscribeToDeletes(const std::string& name, DeleteCallback func)
237 {
238 if (_deleteSubscriptions.find(name) == _deleteSubscriptions.end())
239 {
240 _deleteSubscriptions.emplace(name, func);
241 }
242 }
243
244 /**
245 * @brief Unsubscribe from deleted PELs.
246 *
247 * @param[in] name - The subscription name
248 */
249 void unsubscribeFromDeletes(const std::string& name)
250 {
251 _deleteSubscriptions.erase(name);
252 }
253
Matt Spinler0ff00482019-11-06 16:19:46 -0600254 /**
255 * @brief Get the PEL attributes for a PEL
256 *
257 * @param[in] id - The ID to find the attributes for
258 *
259 * @return The attributes or an empty optional if not found
260 */
261 std::optional<std::reference_wrapper<const PELAttributes>>
262 getPELAttributes(const LogID& id) const;
263
Matt Spinler29d18c12019-11-21 13:31:27 -0600264 /**
265 * @brief Sets the host transmission state on a PEL file
266 *
267 * Writes the host transmission state field in the User Header
268 * section in the PEL data specified by the ID.
269 *
270 * @param[in] pelID - The PEL ID
271 * @param[in] state - The state to write
272 */
273 void setPELHostTransState(uint32_t pelID, TransmissionState state);
274
275 /**
276 * @brief Sets the HMC transmission state on a PEL file
277 *
278 * Writes the HMC transmission state field in the User Header
279 * section in the PEL data specified by the ID.
280 *
281 * @param[in] pelID - The PEL ID
282 * @param[in] state - The state to write
283 */
284 void setPELHMCTransState(uint32_t pelID, TransmissionState state);
285
Matt Spinler89fa0822019-07-17 13:54:30 -0500286 private:
Matt Spinler29d18c12019-11-21 13:31:27 -0600287 using PELUpdateFunc = std::function<void(PEL&)>;
288
289 /**
290 * @brief Lets a function modify a PEL and saves the results
291 *
292 * Runs updateFunc (a void(PEL&) function) on the PEL data
293 * on the file specified, and writes the results back to the file.
294 *
295 * @param[in] path - The file path to use
296 * @param[in] updateFunc - The function to run to update the PEL.
297 */
298 void updatePEL(const std::filesystem::path& path, PELUpdateFunc updateFunc);
299
Matt Spinler89fa0822019-07-17 13:54:30 -0500300 /**
Matt Spinler0ff00482019-11-06 16:19:46 -0600301 * @brief Finds an entry in the _pelAttributes map.
Matt Spinler475e5742019-07-18 16:09:49 -0500302 *
303 * @param[in] id - the ID (either the pel ID, OBMC ID, or both)
304 *
305 * @return an iterator to the entry
306 */
Matt Spinler0ff00482019-11-06 16:19:46 -0600307 std::map<LogID, PELAttributes>::const_iterator
308 findPEL(const LogID& id) const
Matt Spinler475e5742019-07-18 16:09:49 -0500309 {
Matt Spinler0ff00482019-11-06 16:19:46 -0600310 return std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
311 [&id](const auto& a) { return a.first == id; });
Matt Spinler475e5742019-07-18 16:09:49 -0500312 }
313
314 /**
Matt Spinler421f6532019-11-06 15:40:45 -0600315 * @brief Call any subscribed functions for new PELs
316 *
317 * @param[in] pel - The new PEL
318 */
319 void processAddCallbacks(const PEL& pel) const;
320
321 /**
322 * @brief Call any subscribed functions for deleted PELs
323 *
324 * @param[in] id - The ID of the deleted PEL
325 */
326 void processDeleteCallbacks(uint32_t id) const;
327
328 /**
Matt Spinler0ff00482019-11-06 16:19:46 -0600329 * @brief Restores the _pelAttributes map on startup based on the existing
Matt Spinler475e5742019-07-18 16:09:49 -0500330 * PEL data files.
331 */
332 void restore();
333
334 /**
Matt Spinlerab1b97f2019-11-07 13:38:07 -0600335 * @brief Stores a PEL object in the filesystem.
336 *
337 * @param[in] pel - The PEL to write
338 * @param[in] path - The file to write to
339 *
340 * Throws exceptions on failures.
341 */
342 void write(const PEL& pel, const std::filesystem::path& path);
343
344 /**
Matt Spinler89fa0822019-07-17 13:54:30 -0500345 * @brief The filesystem path to the PEL logs.
346 */
347 const std::filesystem::path _logPath;
Matt Spinler475e5742019-07-18 16:09:49 -0500348
349 /**
Matt Spinler0ff00482019-11-06 16:19:46 -0600350 * @brief A map of the PEL/OBMC IDs to PEL attributes.
Matt Spinler475e5742019-07-18 16:09:49 -0500351 */
Matt Spinler0ff00482019-11-06 16:19:46 -0600352 std::map<LogID, PELAttributes> _pelAttributes;
Matt Spinler421f6532019-11-06 15:40:45 -0600353
354 /**
355 * @brief Subcriptions for new PELs.
356 */
357 std::map<std::string, AddCallback> _addSubscriptions;
358
359 /**
360 * @brief Subscriptions for deleted PELs.
361 */
362 std::map<std::string, DeleteCallback> _deleteSubscriptions;
Matt Spinler89fa0822019-07-17 13:54:30 -0500363};
364
365} // namespace pels
366} // namespace openpower