| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 1 | #pragma once | 
|  | 2 | #include "bcd_time.hpp" | 
| Matt Spinler | 8d5f3a2 | 2020-07-07 10:30:33 -0500 | [diff] [blame] | 3 | #include "paths.hpp" | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 4 | #include "pel.hpp" | 
|  | 5 |  | 
|  | 6 | #include <algorithm> | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 7 | #include <bitset> | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 8 | #include <filesystem> | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 9 | #include <map> | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 10 |  | 
|  | 11 | namespace openpower | 
|  | 12 | { | 
|  | 13 | namespace pels | 
|  | 14 | { | 
|  | 15 |  | 
|  | 16 | /** | 
|  | 17 | * @class Repository | 
|  | 18 | * | 
|  | 19 | * The class handles saving and retrieving PELs on the BMC. | 
|  | 20 | */ | 
|  | 21 | class Repository | 
|  | 22 | { | 
|  | 23 | public: | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 24 | /** | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 25 | * @brief Structure of commonly used PEL attributes. | 
|  | 26 | */ | 
|  | 27 | struct PELAttributes | 
|  | 28 | { | 
|  | 29 | std::filesystem::path path; | 
| Matt Spinler | dd325c3 | 2020-07-07 11:01:54 -0500 | [diff] [blame] | 30 | size_t sizeOnDisk; | 
|  | 31 | uint8_t creator; | 
| Vijay Lobo | afb1b46 | 2021-07-21 23:29:13 -0500 | [diff] [blame] | 32 | uint8_t subsystem; | 
| Matt Spinler | dd325c3 | 2020-07-07 11:01:54 -0500 | [diff] [blame] | 33 | uint8_t severity; | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 34 | std::bitset<16> actionFlags; | 
| Matt Spinler | 346f99a | 2019-11-21 13:06:35 -0600 | [diff] [blame] | 35 | TransmissionState hostState; | 
|  | 36 | TransmissionState hmcState; | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 37 |  | 
|  | 38 | PELAttributes() = delete; | 
|  | 39 |  | 
| Matt Spinler | dd325c3 | 2020-07-07 11:01:54 -0500 | [diff] [blame] | 40 | PELAttributes(const std::filesystem::path& p, size_t size, | 
| Vijay Lobo | afb1b46 | 2021-07-21 23:29:13 -0500 | [diff] [blame] | 41 | uint8_t creator, uint8_t subsystem, uint8_t sev, | 
|  | 42 | uint16_t flags, TransmissionState hostState, | 
|  | 43 | TransmissionState hmcState) : | 
| Matt Spinler | 346f99a | 2019-11-21 13:06:35 -0600 | [diff] [blame] | 44 | path(p), | 
| Vijay Lobo | afb1b46 | 2021-07-21 23:29:13 -0500 | [diff] [blame] | 45 | sizeOnDisk(size), creator(creator), subsystem(subsystem), | 
|  | 46 | severity(sev), actionFlags(flags), hostState(hostState), | 
|  | 47 | hmcState(hmcState) | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 48 | {} | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 49 | }; | 
|  | 50 |  | 
|  | 51 | /** | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 52 | * @brief A structure that holds both the PEL and corresponding | 
|  | 53 | *        OpenBMC IDs. | 
|  | 54 | * Used for correlating the IDs with their data files for quick | 
|  | 55 | * lookup.  To find a PEL based on just one of the IDs, just use | 
|  | 56 | * the constructor that takes that ID. | 
|  | 57 | */ | 
|  | 58 | struct LogID | 
|  | 59 | { | 
|  | 60 | struct Pel | 
|  | 61 | { | 
|  | 62 | uint32_t id; | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 63 | explicit Pel(uint32_t i) : id(i) {} | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 64 | }; | 
|  | 65 | struct Obmc | 
|  | 66 | { | 
|  | 67 | uint32_t id; | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 68 | explicit Obmc(uint32_t i) : id(i) {} | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 69 | }; | 
|  | 70 |  | 
|  | 71 | Pel pelID; | 
|  | 72 |  | 
|  | 73 | Obmc obmcID; | 
|  | 74 |  | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 75 | LogID(Pel pel, Obmc obmc) : pelID(pel), obmcID(obmc) {} | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 76 |  | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 77 | explicit LogID(Pel id) : pelID(id), obmcID(0) {} | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 78 |  | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 79 | explicit LogID(Obmc id) : pelID(0), obmcID(id) {} | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 80 |  | 
|  | 81 | LogID() = delete; | 
|  | 82 |  | 
|  | 83 | /** | 
|  | 84 | * @brief A == operator that will match on either ID | 
|  | 85 | *        being equal if the other is zero, so that | 
|  | 86 | *        one can look up a PEL with just one of the IDs. | 
|  | 87 | */ | 
|  | 88 | bool operator==(const LogID& id) const | 
|  | 89 | { | 
|  | 90 | if (id.pelID.id != 0) | 
|  | 91 | { | 
|  | 92 | return id.pelID.id == pelID.id; | 
|  | 93 | } | 
|  | 94 | if (id.obmcID.id != 0) | 
|  | 95 | { | 
|  | 96 | return id.obmcID.id == obmcID.id; | 
|  | 97 | } | 
|  | 98 | return false; | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | bool operator<(const LogID& id) const | 
|  | 102 | { | 
|  | 103 | return pelID.id < id.pelID.id; | 
|  | 104 | } | 
|  | 105 | }; | 
|  | 106 |  | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 107 | using AttributesReference = | 
|  | 108 | std::reference_wrapper<const std::pair<const LogID, PELAttributes>>; | 
|  | 109 |  | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 110 | /** | 
|  | 111 | * @brief A structure for keeping a breakdown of the sizes of PELs | 
|  | 112 | *        of different types in the repository. | 
|  | 113 | */ | 
|  | 114 | struct SizeStats | 
|  | 115 | { | 
|  | 116 | uint64_t total; | 
|  | 117 | uint64_t bmc; | 
|  | 118 | uint64_t nonBMC; | 
|  | 119 | uint64_t bmcServiceable; | 
|  | 120 | uint64_t bmcInfo; | 
|  | 121 | uint64_t nonBMCServiceable; | 
|  | 122 | uint64_t nonBMCInfo; | 
|  | 123 |  | 
|  | 124 | SizeStats() : | 
|  | 125 | total(0), bmc(0), nonBMC(0), bmcServiceable(0), bmcInfo(0), | 
|  | 126 | nonBMCServiceable(0), nonBMCInfo(0) | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 127 | {} | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 128 | }; | 
|  | 129 |  | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 130 | Repository() = delete; | 
|  | 131 | ~Repository() = default; | 
|  | 132 | Repository(const Repository&) = default; | 
|  | 133 | Repository& operator=(const Repository&) = default; | 
|  | 134 | Repository(Repository&&) = default; | 
|  | 135 | Repository& operator=(Repository&&) = default; | 
|  | 136 |  | 
|  | 137 | /** | 
|  | 138 | * @brief Constructor | 
|  | 139 | * | 
|  | 140 | * @param[in] basePath - the base filesystem path for the repository | 
|  | 141 | */ | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 142 | explicit Repository(const std::filesystem::path& basePath) : | 
| Matt Spinler | 8d5f3a2 | 2020-07-07 10:30:33 -0500 | [diff] [blame] | 143 | Repository(basePath, getPELRepoSize(), getMaxNumPELs()) | 
| Patrick Williams | 2544b41 | 2022-10-04 08:41:06 -0500 | [diff] [blame] | 144 | {} | 
| Matt Spinler | 8d5f3a2 | 2020-07-07 10:30:33 -0500 | [diff] [blame] | 145 |  | 
|  | 146 | /** | 
|  | 147 | * @brief Constructor that takes the repository size | 
|  | 148 | * | 
|  | 149 | * @param[in] basePath - the base filesystem path for the repository | 
|  | 150 | * @param[in] repoSize - The maximum amount of space to use for PELs, | 
|  | 151 | *                       in bytes | 
|  | 152 | * @param[in] maxNumPELs - The maximum number of PELs to allow | 
|  | 153 | */ | 
|  | 154 | Repository(const std::filesystem::path& basePath, size_t repoSize, | 
|  | 155 | size_t maxNumPELs); | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 156 |  | 
|  | 157 | /** | 
|  | 158 | * @brief Adds a PEL to the repository | 
|  | 159 | * | 
|  | 160 | * Throws File.Error.Open or File.Error.Write exceptions on failure | 
|  | 161 | * | 
|  | 162 | * @param[in] pel - the PEL to add | 
|  | 163 | */ | 
|  | 164 | void add(std::unique_ptr<PEL>& pel); | 
|  | 165 |  | 
|  | 166 | /** | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 167 | * @brief Removes a PEL from the repository | 
|  | 168 | * | 
| Matt Spinler | 52602e3 | 2020-07-15 12:37:28 -0500 | [diff] [blame] | 169 | * Note that the returned LogID is the fully filled in LogID, i.e. | 
|  | 170 | * it has both the PEL and OpenBMC IDs, unlike the passed in LogID | 
|  | 171 | * which can just have one or the other. | 
|  | 172 | * | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 173 | * @param[in] id - the ID (either the pel ID, OBMC ID, or both) to remove | 
| Matt Spinler | 52602e3 | 2020-07-15 12:37:28 -0500 | [diff] [blame] | 174 | * | 
|  | 175 | * @return std::optional<LogID> - The LogID of the removed PEL | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 176 | */ | 
| Matt Spinler | 52602e3 | 2020-07-15 12:37:28 -0500 | [diff] [blame] | 177 | std::optional<LogID> remove(const LogID& id); | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 178 |  | 
|  | 179 | /** | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 180 | * @brief Generates the filename to use for the PEL ID and BCDTime. | 
|  | 181 | * | 
|  | 182 | * @param[in] pelID - the PEL ID | 
|  | 183 | * @param[in] time - the BCD time | 
|  | 184 | * | 
|  | 185 | * @return string - A filename string of <BCD_time>_<pelID> | 
|  | 186 | */ | 
|  | 187 | static std::string getPELFilename(uint32_t pelID, const BCDTime& time); | 
|  | 188 |  | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 189 | /** | 
|  | 190 | * @brief Returns true if the PEL with the specified ID is in the repo. | 
|  | 191 | * | 
|  | 192 | * @param[in] id - the ID (either the pel ID, OBMC ID, or both) | 
|  | 193 | * @return bool - true if that PEL is present | 
|  | 194 | */ | 
|  | 195 | inline bool hasPEL(const LogID& id) | 
|  | 196 | { | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 197 | return findPEL(id) != _pelAttributes.end(); | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 198 | } | 
|  | 199 |  | 
| Matt Spinler | 2813f36 | 2019-07-19 12:45:28 -0500 | [diff] [blame] | 200 | /** | 
|  | 201 | * @brief Returns the PEL data based on its ID. | 
|  | 202 | * | 
|  | 203 | * If the data can't be found for that ID, then the optional object | 
|  | 204 | * will be empty. | 
|  | 205 | * | 
|  | 206 | * @param[in] id - the LogID to get the PEL for, which can be either a | 
|  | 207 | *                 PEL ID or OpenBMC log ID. | 
|  | 208 | * @return std::optional<std::vector<uint8_t>> - the PEL data | 
|  | 209 | */ | 
|  | 210 | std::optional<std::vector<uint8_t>> getPELData(const LogID& id); | 
|  | 211 |  | 
| Matt Spinler | 6d51224 | 2019-12-09 13:44:17 -0600 | [diff] [blame] | 212 | /** | 
|  | 213 | * @brief Get a file descriptor to the PEL data | 
|  | 214 | * | 
|  | 215 | * @param[in] id - The ID to get the FD for | 
|  | 216 | * | 
|  | 217 | * @return std::optional<sdbusplus::message::unix_fd> - | 
|  | 218 | *         The FD, or an empty optional object. | 
|  | 219 | */ | 
|  | 220 | std::optional<sdbusplus::message::unix_fd> getPELFD(const LogID& id); | 
|  | 221 |  | 
| Matt Spinler | 1ea7880 | 2019-11-01 13:04:59 -0500 | [diff] [blame] | 222 | using ForEachFunc = std::function<bool(const PEL&)>; | 
|  | 223 |  | 
|  | 224 | /** | 
|  | 225 | * @brief Run a user defined function on every PEL in the repository. | 
|  | 226 | * | 
|  | 227 | * ForEachFunc takes a const PEL reference, and should return | 
|  | 228 | * true to stop iterating and return out of for_each. | 
|  | 229 | * | 
|  | 230 | * For example, to save up to 100 IDs in the repo into a vector: | 
|  | 231 | * | 
|  | 232 | *     std::vector<uint32_t> ids; | 
|  | 233 | *     ForEachFunc f = [&ids](const PEL& pel) { | 
|  | 234 | *         ids.push_back(pel.id()); | 
|  | 235 | *         return ids.size() == 100 ? true : false; | 
|  | 236 | *     }; | 
|  | 237 | * | 
|  | 238 | * @param[in] func - The function to run. | 
|  | 239 | */ | 
|  | 240 | void for_each(ForEachFunc func) const; | 
|  | 241 |  | 
| Matt Spinler | 421f653 | 2019-11-06 15:40:45 -0600 | [diff] [blame] | 242 | using AddCallback = std::function<void(const PEL&)>; | 
|  | 243 |  | 
|  | 244 | /** | 
|  | 245 | * @brief Subscribe to PELs being added to the repository. | 
|  | 246 | * | 
|  | 247 | * Every time a PEL is added to the repository, the provided | 
|  | 248 | * function will be called with the new PEL as the argument. | 
|  | 249 | * | 
|  | 250 | * The function must be of type void(const PEL&). | 
|  | 251 | * | 
|  | 252 | * @param[in] name - The subscription name | 
|  | 253 | * @param[in] func - The callback function | 
|  | 254 | */ | 
|  | 255 | void subscribeToAdds(const std::string& name, AddCallback func) | 
|  | 256 | { | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 257 | _addSubscriptions.emplace(name, func); | 
| Matt Spinler | 421f653 | 2019-11-06 15:40:45 -0600 | [diff] [blame] | 258 | } | 
|  | 259 |  | 
|  | 260 | /** | 
|  | 261 | * @brief Unsubscribe from new PELs. | 
|  | 262 | * | 
|  | 263 | * @param[in] name - The subscription name | 
|  | 264 | */ | 
|  | 265 | void unsubscribeFromAdds(const std::string& name) | 
|  | 266 | { | 
|  | 267 | _addSubscriptions.erase(name); | 
|  | 268 | } | 
|  | 269 |  | 
|  | 270 | using DeleteCallback = std::function<void(uint32_t)>; | 
|  | 271 |  | 
|  | 272 | /** | 
|  | 273 | * @brief Subscribe to PELs being deleted from the repository. | 
|  | 274 | * | 
|  | 275 | * Every time a PEL is deleted from the repository, the provided | 
|  | 276 | * function will be called with the PEL ID as the argument. | 
|  | 277 | * | 
|  | 278 | * The function must be of type void(const uint32_t). | 
|  | 279 | * | 
|  | 280 | * @param[in] name - The subscription name | 
|  | 281 | * @param[in] func - The callback function | 
|  | 282 | */ | 
|  | 283 | void subscribeToDeletes(const std::string& name, DeleteCallback func) | 
|  | 284 | { | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 285 | _deleteSubscriptions.emplace(name, func); | 
| Matt Spinler | 421f653 | 2019-11-06 15:40:45 -0600 | [diff] [blame] | 286 | } | 
|  | 287 |  | 
|  | 288 | /** | 
|  | 289 | * @brief Unsubscribe from deleted PELs. | 
|  | 290 | * | 
|  | 291 | * @param[in] name - The subscription name | 
|  | 292 | */ | 
|  | 293 | void unsubscribeFromDeletes(const std::string& name) | 
|  | 294 | { | 
|  | 295 | _deleteSubscriptions.erase(name); | 
|  | 296 | } | 
|  | 297 |  | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 298 | /** | 
|  | 299 | * @brief Get the PEL attributes for a PEL | 
|  | 300 | * | 
|  | 301 | * @param[in] id - The ID to find the attributes for | 
|  | 302 | * | 
|  | 303 | * @return The attributes or an empty optional if not found | 
|  | 304 | */ | 
|  | 305 | std::optional<std::reference_wrapper<const PELAttributes>> | 
|  | 306 | getPELAttributes(const LogID& id) const; | 
|  | 307 |  | 
| Matt Spinler | 29d18c1 | 2019-11-21 13:31:27 -0600 | [diff] [blame] | 308 | /** | 
|  | 309 | * @brief Sets the host transmission state on a PEL file | 
|  | 310 | * | 
|  | 311 | * Writes the host transmission state field in the User Header | 
|  | 312 | * section in the PEL data specified by the ID. | 
|  | 313 | * | 
|  | 314 | * @param[in] pelID - The PEL ID | 
|  | 315 | * @param[in] state - The state to write | 
|  | 316 | */ | 
|  | 317 | void setPELHostTransState(uint32_t pelID, TransmissionState state); | 
|  | 318 |  | 
|  | 319 | /** | 
|  | 320 | * @brief Sets the HMC transmission state on a PEL file | 
|  | 321 | * | 
|  | 322 | * Writes the HMC transmission state field in the User Header | 
|  | 323 | * section in the PEL data specified by the ID. | 
|  | 324 | * | 
|  | 325 | * @param[in] pelID - The PEL ID | 
|  | 326 | * @param[in] state - The state to write | 
|  | 327 | */ | 
|  | 328 | void setPELHMCTransState(uint32_t pelID, TransmissionState state); | 
|  | 329 |  | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 330 | /** | 
|  | 331 | * @brief Returns the size stats structure | 
|  | 332 | * | 
|  | 333 | * @return const SizeStats& - The stats structure | 
|  | 334 | */ | 
|  | 335 | const SizeStats& getSizeStats() const | 
|  | 336 | { | 
|  | 337 | return _sizes; | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | /** | 
|  | 341 | * @brief Says if the PEL is considered serviceable (not just | 
|  | 342 | *        informational) as determined by its severity. | 
|  | 343 | * | 
|  | 344 | * @param[in] pel - The PELAttributes entry for the PEL | 
|  | 345 | * @return bool - If serviceable or not | 
|  | 346 | */ | 
|  | 347 | static bool isServiceableSev(const PELAttributes& pel); | 
|  | 348 |  | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 349 | /** | 
| Matt Spinler | 7e727a3 | 2020-07-07 15:00:17 -0500 | [diff] [blame] | 350 | * @brief Returns true if the total amount of disk space occupied | 
|  | 351 | *        by the PELs in the repo is over 95% of the maximum | 
|  | 352 | *        size, or if there are over the maximum number of | 
|  | 353 | *        PELs allowed. | 
|  | 354 | * | 
|  | 355 | * @return bool - true if repo is > 95% full or too many PELs | 
|  | 356 | */ | 
| Sumit Kumar | c296692 | 2021-07-21 10:14:03 -0500 | [diff] [blame] | 357 | bool sizeWarning(); | 
| Matt Spinler | 7e727a3 | 2020-07-07 15:00:17 -0500 | [diff] [blame] | 358 |  | 
|  | 359 | /** | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 360 | * @brief Deletes PELs to bring the repository size down | 
|  | 361 | *        to at most 90% full by placing PELs into 4 different | 
|  | 362 | *        catogories and then removing PELs until those catogories | 
|  | 363 | *        only take up certain percentages of the allowed space. | 
|  | 364 | * | 
|  | 365 | * This does not delete the corresponding OpenBMC event logs, which | 
|  | 366 | * is why those IDs are returned, so they can be deleted later. | 
|  | 367 | * | 
|  | 368 | * The categories and their rules are: | 
|  | 369 | *  1) Informational BMC PELs cannot take up more than 15% of | 
|  | 370 | *     the allocated space. | 
|  | 371 | *  2) Non-informational BMC PELs cannot take up more than 30% | 
|  | 372 | *     of the allocated space. | 
|  | 373 | *  3) Informational non-BMC PELs cannot take up more than 15% of | 
|  | 374 | *     the allocated space. | 
|  | 375 | *  4) Non-informational non-BMC PELs cannot take up more than 30% | 
|  | 376 | *     of the allocated space. | 
|  | 377 | * | 
|  | 378 | *  While removing PELs in a category, 4 passes will be made, with | 
|  | 379 | *  PELs being removed oldest first during each pass. | 
|  | 380 | * | 
|  | 381 | *   Pass 1: only delete HMC acked PELs | 
|  | 382 | *   Pass 2: only delete OS acked PELs | 
|  | 383 | *   Pass 3: only delete PHYP sent PELs | 
|  | 384 | *   Pass 4: delete all PELs | 
|  | 385 | * | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 386 | * @param[in] ids - The OpenBMC event log Ids with hardware isolation entry. | 
|  | 387 | * | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 388 | * @return std::vector<uint32_t> - The OpenBMC event log IDs of | 
|  | 389 | *                                 the PELs that were deleted. | 
|  | 390 | */ | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 391 | std::vector<uint32_t> prune(const std::vector<uint32_t>& idsWithHwIsoEntry); | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 392 |  | 
| Matt Spinler | ff9cec2 | 2020-07-15 13:06:35 -0500 | [diff] [blame] | 393 | /** | 
|  | 394 | * @brief Returns the path to the directory where the PEL | 
|  | 395 | *        files are stored. | 
|  | 396 | * | 
|  | 397 | * @return std::filesystem::path - The directory path | 
|  | 398 | */ | 
|  | 399 | const std::filesystem::path& repoPath() const | 
|  | 400 | { | 
|  | 401 | return _logPath; | 
|  | 402 | } | 
|  | 403 |  | 
| Matt Spinler | 44893cc | 2020-08-26 11:34:17 -0500 | [diff] [blame] | 404 | /** | 
|  | 405 | * @brief Returns the ID of the most recently added PEL. | 
|  | 406 | * | 
|  | 407 | * @return uint32_t - The PEL ID | 
|  | 408 | */ | 
|  | 409 | uint32_t lastPelID() const | 
|  | 410 | { | 
|  | 411 | return _lastPelID; | 
|  | 412 | } | 
|  | 413 |  | 
| Ramesh Iyyar | 99f3717 | 2021-06-24 05:41:51 -0500 | [diff] [blame] | 414 | /** | 
|  | 415 | * @brief Get the LogID based on the given ObmcLogId or PelId. | 
|  | 416 | * | 
|  | 417 | * @param[in] id - The ID to find the LogID. | 
|  | 418 | * | 
|  | 419 | * @return The LogID or an empty optional if not found. | 
|  | 420 | * | 
|  | 421 | * @note The returned LogID is the fully filled in LogID, i.e. | 
|  | 422 | * it has both the PEL and OpenBMC Log IDs, unlike the passed in LogID | 
|  | 423 | * which can just have one or the other. | 
|  | 424 | */ | 
|  | 425 | std::optional<LogID> getLogID(const LogID& id) const | 
|  | 426 | { | 
|  | 427 | if (auto logID = findPEL(id); logID != _pelAttributes.end()) | 
|  | 428 | { | 
|  | 429 | return logID->first; | 
|  | 430 | } | 
|  | 431 | return std::nullopt; | 
|  | 432 | } | 
|  | 433 |  | 
| Sumit Kumar | 2ccdcef | 2021-07-31 10:04:58 -0500 | [diff] [blame] | 434 | /** | 
|  | 435 | * @brief Save the PEL to archive folder | 
|  | 436 | * | 
|  | 437 | * @param[in] pel - The PEL data | 
|  | 438 | */ | 
|  | 439 | void archivePEL(const PEL& pel); | 
|  | 440 |  | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 441 | private: | 
| Matt Spinler | 29d18c1 | 2019-11-21 13:31:27 -0600 | [diff] [blame] | 442 | using PELUpdateFunc = std::function<void(PEL&)>; | 
|  | 443 |  | 
|  | 444 | /** | 
|  | 445 | * @brief Lets a function modify a PEL and saves the results | 
|  | 446 | * | 
|  | 447 | * Runs updateFunc (a void(PEL&) function) on the PEL data | 
|  | 448 | * on the file specified, and writes the results back to the file. | 
|  | 449 | * | 
|  | 450 | * @param[in] path - The file path to use | 
|  | 451 | * @param[in] updateFunc - The function to run to update the PEL. | 
|  | 452 | */ | 
|  | 453 | void updatePEL(const std::filesystem::path& path, PELUpdateFunc updateFunc); | 
|  | 454 |  | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 455 | /** | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 456 | * @brief Finds an entry in the _pelAttributes map. | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 457 | * | 
|  | 458 | * @param[in] id - the ID (either the pel ID, OBMC ID, or both) | 
|  | 459 | * | 
|  | 460 | * @return an iterator to the entry | 
|  | 461 | */ | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 462 | std::map<LogID, PELAttributes>::const_iterator | 
|  | 463 | findPEL(const LogID& id) const | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 464 | { | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 465 | return std::find_if(_pelAttributes.begin(), _pelAttributes.end(), | 
|  | 466 | [&id](const auto& a) { return a.first == id; }); | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 467 | } | 
|  | 468 |  | 
|  | 469 | /** | 
| Matt Spinler | 421f653 | 2019-11-06 15:40:45 -0600 | [diff] [blame] | 470 | * @brief Call any subscribed functions for new PELs | 
|  | 471 | * | 
|  | 472 | * @param[in] pel - The new PEL | 
|  | 473 | */ | 
|  | 474 | void processAddCallbacks(const PEL& pel) const; | 
|  | 475 |  | 
|  | 476 | /** | 
|  | 477 | * @brief Call any subscribed functions for deleted PELs | 
|  | 478 | * | 
|  | 479 | * @param[in] id - The ID of the deleted PEL | 
|  | 480 | */ | 
|  | 481 | void processDeleteCallbacks(uint32_t id) const; | 
|  | 482 |  | 
|  | 483 | /** | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 484 | * @brief Restores the _pelAttributes map on startup based on the existing | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 485 | *        PEL data files. | 
|  | 486 | */ | 
|  | 487 | void restore(); | 
|  | 488 |  | 
|  | 489 | /** | 
| Matt Spinler | ab1b97f | 2019-11-07 13:38:07 -0600 | [diff] [blame] | 490 | * @brief Stores a PEL object in the filesystem. | 
|  | 491 | * | 
|  | 492 | * @param[in] pel - The PEL to write | 
|  | 493 | * @param[in] path - The file to write to | 
|  | 494 | * | 
|  | 495 | * Throws exceptions on failures. | 
|  | 496 | */ | 
|  | 497 | void write(const PEL& pel, const std::filesystem::path& path); | 
|  | 498 |  | 
|  | 499 | /** | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 500 | * @brief Updates the repository statistics after a PEL is | 
|  | 501 | *        added or removed. | 
|  | 502 | * | 
|  | 503 | * @param[in] pel - The PELAttributes entry for the PEL | 
|  | 504 | * @param[in] pelAdded - true if the PEL was added, false if removed | 
|  | 505 | */ | 
|  | 506 | void updateRepoStats(const PELAttributes& pel, bool pelAdded); | 
|  | 507 |  | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 508 | enum class SortOrder | 
|  | 509 | { | 
|  | 510 | ascending, | 
|  | 511 | descending | 
|  | 512 | }; | 
|  | 513 |  | 
|  | 514 | /** | 
|  | 515 | * @brief Returns a vector of all the _pelAttributes entries sorted | 
|  | 516 | *        as specified | 
|  | 517 | * | 
|  | 518 | * @param[in] order - If the PELs should be returned in ascending | 
|  | 519 | *                    (oldest first) or descending order. | 
|  | 520 | * | 
|  | 521 | * @return std::vector<AttributesReference> - The sorted vector of | 
|  | 522 | *         references to the pair<LogID, PELAttributes> entries of | 
|  | 523 | *         _pelAttributes. | 
|  | 524 | */ | 
|  | 525 | std::vector<AttributesReference> getAllPELAttributes(SortOrder order) const; | 
|  | 526 |  | 
|  | 527 | using IsOverLimitFunc = std::function<bool()>; | 
|  | 528 | using IsPELTypeFunc = std::function<bool(const PELAttributes&)>; | 
|  | 529 |  | 
|  | 530 | /** | 
|  | 531 | * @brief Makes 4 passes on the PELs that meet the IsPELTypeFunc | 
|  | 532 | *        criteria removing PELs until IsOverLimitFunc returns false. | 
|  | 533 | * | 
|  | 534 | *   Pass 1: only delete HMC acked PELs | 
|  | 535 | *   Pass 2: only delete Os acked PELs | 
|  | 536 | *   Pass 3: only delete PHYP sent PELs | 
|  | 537 | *   Pass 4: delete all PELs | 
|  | 538 | * | 
|  | 539 | * @param[in] isOverLimit - The bool(void) function that should | 
|  | 540 | *                          return true if PELs still need to be | 
|  | 541 | *                           removed. | 
|  | 542 | * @param[in] isPELType - The bool(const PELAttributes&) function | 
|  | 543 | *                         used to select the PELs to operate on. | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 544 | * @param[in] ids - The OpenBMC event log Ids with hardware isolation | 
|  | 545 | *                   entry. | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 546 | * | 
|  | 547 | * @param[out] removedBMCLogIDs - The OpenBMC event log IDs of the | 
|  | 548 | *                                removed PELs. | 
|  | 549 | */ | 
| Matt Spinler | 45796e8 | 2022-07-01 11:25:27 -0500 | [diff] [blame] | 550 | void removePELs(const IsOverLimitFunc& isOverLimit, | 
|  | 551 | const IsPELTypeFunc& isPELType, | 
| Sumit Kumar | 027bf28 | 2022-01-24 11:25:19 -0600 | [diff] [blame] | 552 | const std::vector<uint32_t>& idsWithHwIsoEntry, | 
| Matt Spinler | b0a8df5 | 2020-07-07 14:41:06 -0500 | [diff] [blame] | 553 | std::vector<uint32_t>& removedBMCLogIDs); | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 554 | /** | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 555 | * @brief The filesystem path to the PEL logs. | 
|  | 556 | */ | 
|  | 557 | const std::filesystem::path _logPath; | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 558 |  | 
|  | 559 | /** | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 560 | * @brief A map of the PEL/OBMC IDs to PEL attributes. | 
| Matt Spinler | 475e574 | 2019-07-18 16:09:49 -0500 | [diff] [blame] | 561 | */ | 
| Matt Spinler | 0ff0048 | 2019-11-06 16:19:46 -0600 | [diff] [blame] | 562 | std::map<LogID, PELAttributes> _pelAttributes; | 
| Matt Spinler | 421f653 | 2019-11-06 15:40:45 -0600 | [diff] [blame] | 563 |  | 
|  | 564 | /** | 
|  | 565 | * @brief Subcriptions for new PELs. | 
|  | 566 | */ | 
|  | 567 | std::map<std::string, AddCallback> _addSubscriptions; | 
|  | 568 |  | 
|  | 569 | /** | 
|  | 570 | * @brief Subscriptions for deleted PELs. | 
|  | 571 | */ | 
|  | 572 | std::map<std::string, DeleteCallback> _deleteSubscriptions; | 
| Matt Spinler | 8d5f3a2 | 2020-07-07 10:30:33 -0500 | [diff] [blame] | 573 |  | 
|  | 574 | /** | 
|  | 575 | * @brief The maximum amount of space that the PELs in the | 
|  | 576 | *        repository can occupy. | 
|  | 577 | */ | 
|  | 578 | const uint64_t _maxRepoSize; | 
|  | 579 |  | 
|  | 580 | /** | 
|  | 581 | * @brief The maximum number of PELs to allow in the repo | 
|  | 582 | *        before pruning. | 
|  | 583 | */ | 
|  | 584 | const size_t _maxNumPELs; | 
| Matt Spinler | b188f78 | 2020-07-07 11:18:12 -0500 | [diff] [blame] | 585 |  | 
|  | 586 | /** | 
|  | 587 | * @brief Statistics on the sizes of the stored PELs. | 
|  | 588 | */ | 
|  | 589 | SizeStats _sizes; | 
| Matt Spinler | 44893cc | 2020-08-26 11:34:17 -0500 | [diff] [blame] | 590 |  | 
|  | 591 | /** | 
|  | 592 | * @brief The ID of the most recently added PEL. | 
|  | 593 | */ | 
|  | 594 | uint32_t _lastPelID = 0; | 
| Sumit Kumar | 1d8835b | 2021-06-07 09:35:30 -0500 | [diff] [blame] | 595 |  | 
|  | 596 | /** | 
|  | 597 | * @brief The filesystem path to the archive PEL logs. | 
|  | 598 | */ | 
|  | 599 | const std::filesystem::path _archivePath; | 
|  | 600 |  | 
|  | 601 | /** | 
|  | 602 | * @brief The size of archive folder. | 
|  | 603 | */ | 
|  | 604 | uint64_t _archiveSize = 0; | 
| Matt Spinler | 89fa082 | 2019-07-17 13:54:30 -0500 | [diff] [blame] | 605 | }; | 
|  | 606 |  | 
|  | 607 | } // namespace pels | 
|  | 608 | } // namespace openpower |