blob: a1d4a24d05f55a12e1735991f830bf1c77578880 [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>
6#include <filesystem>
Matt Spinler475e5742019-07-18 16:09:49 -05007#include <map>
Matt Spinler89fa0822019-07-17 13:54:30 -05008
9namespace openpower
10{
11namespace pels
12{
13
14/**
15 * @class Repository
16 *
17 * The class handles saving and retrieving PELs on the BMC.
18 */
19class Repository
20{
21 public:
Matt Spinler475e5742019-07-18 16:09:49 -050022 /**
23 * @brief A structure that holds both the PEL and corresponding
24 * OpenBMC IDs.
25 * Used for correlating the IDs with their data files for quick
26 * lookup. To find a PEL based on just one of the IDs, just use
27 * the constructor that takes that ID.
28 */
29 struct LogID
30 {
31 struct Pel
32 {
33 uint32_t id;
34 explicit Pel(uint32_t i) : id(i)
35 {
36 }
37 };
38 struct Obmc
39 {
40 uint32_t id;
41 explicit Obmc(uint32_t i) : id(i)
42 {
43 }
44 };
45
46 Pel pelID;
47
48 Obmc obmcID;
49
50 LogID(Pel pel, Obmc obmc) : pelID(pel), obmcID(obmc)
51 {
52 }
53
54 explicit LogID(Pel id) : pelID(id), obmcID(0)
55 {
56 }
57
58 explicit LogID(Obmc id) : pelID(0), obmcID(id)
59 {
60 }
61
62 LogID() = delete;
63
64 /**
65 * @brief A == operator that will match on either ID
66 * being equal if the other is zero, so that
67 * one can look up a PEL with just one of the IDs.
68 */
69 bool operator==(const LogID& id) const
70 {
71 if (id.pelID.id != 0)
72 {
73 return id.pelID.id == pelID.id;
74 }
75 if (id.obmcID.id != 0)
76 {
77 return id.obmcID.id == obmcID.id;
78 }
79 return false;
80 }
81
82 bool operator<(const LogID& id) const
83 {
84 return pelID.id < id.pelID.id;
85 }
86 };
87
Matt Spinler89fa0822019-07-17 13:54:30 -050088 Repository() = delete;
89 ~Repository() = default;
90 Repository(const Repository&) = default;
91 Repository& operator=(const Repository&) = default;
92 Repository(Repository&&) = default;
93 Repository& operator=(Repository&&) = default;
94
95 /**
96 * @brief Constructor
97 *
98 * @param[in] basePath - the base filesystem path for the repository
99 */
100 Repository(const std::filesystem::path& basePath);
101
102 /**
103 * @brief Adds a PEL to the repository
104 *
105 * Throws File.Error.Open or File.Error.Write exceptions on failure
106 *
107 * @param[in] pel - the PEL to add
108 */
109 void add(std::unique_ptr<PEL>& pel);
110
111 /**
Matt Spinler475e5742019-07-18 16:09:49 -0500112 * @brief Removes a PEL from the repository
113 *
114 * @param[in] id - the ID (either the pel ID, OBMC ID, or both) to remove
115 */
116 void remove(const LogID& id);
117
118 /**
Matt Spinler89fa0822019-07-17 13:54:30 -0500119 * @brief Generates the filename to use for the PEL ID and BCDTime.
120 *
121 * @param[in] pelID - the PEL ID
122 * @param[in] time - the BCD time
123 *
124 * @return string - A filename string of <BCD_time>_<pelID>
125 */
126 static std::string getPELFilename(uint32_t pelID, const BCDTime& time);
127
Matt Spinler475e5742019-07-18 16:09:49 -0500128 /**
129 * @brief Returns true if the PEL with the specified ID is in the repo.
130 *
131 * @param[in] id - the ID (either the pel ID, OBMC ID, or both)
132 * @return bool - true if that PEL is present
133 */
134 inline bool hasPEL(const LogID& id)
135 {
136 return findPEL(id) != _idsToPELs.end();
137 }
138
Matt Spinler2813f362019-07-19 12:45:28 -0500139 /**
140 * @brief Returns the PEL data based on its ID.
141 *
142 * If the data can't be found for that ID, then the optional object
143 * will be empty.
144 *
145 * @param[in] id - the LogID to get the PEL for, which can be either a
146 * PEL ID or OpenBMC log ID.
147 * @return std::optional<std::vector<uint8_t>> - the PEL data
148 */
149 std::optional<std::vector<uint8_t>> getPELData(const LogID& id);
150
Matt Spinler1ea78802019-11-01 13:04:59 -0500151 using ForEachFunc = std::function<bool(const PEL&)>;
152
153 /**
154 * @brief Run a user defined function on every PEL in the repository.
155 *
156 * ForEachFunc takes a const PEL reference, and should return
157 * true to stop iterating and return out of for_each.
158 *
159 * For example, to save up to 100 IDs in the repo into a vector:
160 *
161 * std::vector<uint32_t> ids;
162 * ForEachFunc f = [&ids](const PEL& pel) {
163 * ids.push_back(pel.id());
164 * return ids.size() == 100 ? true : false;
165 * };
166 *
167 * @param[in] func - The function to run.
168 */
169 void for_each(ForEachFunc func) const;
170
Matt Spinler89fa0822019-07-17 13:54:30 -0500171 private:
172 /**
Matt Spinler475e5742019-07-18 16:09:49 -0500173 * @brief Finds an entry in the _idsToPELs map.
174 *
175 * @param[in] id - the ID (either the pel ID, OBMC ID, or both)
176 *
177 * @return an iterator to the entry
178 */
179 std::map<LogID, std::filesystem::path>::iterator findPEL(const LogID& id)
180 {
181 return std::find_if(_idsToPELs.begin(), _idsToPELs.end(),
182 [&id](const auto& i) { return i.first == id; });
183 }
184
185 /**
186 * @brief Restores the _idsToPELs map on startup based on the existing
187 * PEL data files.
188 */
189 void restore();
190
191 /**
Matt Spinler89fa0822019-07-17 13:54:30 -0500192 * @brief The filesystem path to the PEL logs.
193 */
194 const std::filesystem::path _logPath;
Matt Spinler475e5742019-07-18 16:09:49 -0500195
196 /**
197 * @brief A map of the PEL/OBMC IDs to the PEL data files.
198 */
199 std::map<LogID, std::filesystem::path> _idsToPELs;
Matt Spinler89fa0822019-07-17 13:54:30 -0500200};
201
202} // namespace pels
203} // namespace openpower