189fa082aSMatt Spinler #pragma once 289fa082aSMatt Spinler #include "bcd_time.hpp" 389fa082aSMatt Spinler #include "pel.hpp" 489fa082aSMatt Spinler 589fa082aSMatt Spinler #include <algorithm> 689fa082aSMatt Spinler #include <filesystem> 7475e574dSMatt Spinler #include <map> 889fa082aSMatt Spinler 989fa082aSMatt Spinler namespace openpower 1089fa082aSMatt Spinler { 1189fa082aSMatt Spinler namespace pels 1289fa082aSMatt Spinler { 1389fa082aSMatt Spinler 1489fa082aSMatt Spinler /** 1589fa082aSMatt Spinler * @class Repository 1689fa082aSMatt Spinler * 1789fa082aSMatt Spinler * The class handles saving and retrieving PELs on the BMC. 1889fa082aSMatt Spinler */ 1989fa082aSMatt Spinler class Repository 2089fa082aSMatt Spinler { 2189fa082aSMatt Spinler public: 22475e574dSMatt Spinler /** 23475e574dSMatt Spinler * @brief A structure that holds both the PEL and corresponding 24475e574dSMatt Spinler * OpenBMC IDs. 25475e574dSMatt Spinler * Used for correlating the IDs with their data files for quick 26475e574dSMatt Spinler * lookup. To find a PEL based on just one of the IDs, just use 27475e574dSMatt Spinler * the constructor that takes that ID. 28475e574dSMatt Spinler */ 29475e574dSMatt Spinler struct LogID 30475e574dSMatt Spinler { 31475e574dSMatt Spinler struct Pel 32475e574dSMatt Spinler { 33475e574dSMatt Spinler uint32_t id; 34475e574dSMatt Spinler explicit Pel(uint32_t i) : id(i) 35475e574dSMatt Spinler { 36475e574dSMatt Spinler } 37475e574dSMatt Spinler }; 38475e574dSMatt Spinler struct Obmc 39475e574dSMatt Spinler { 40475e574dSMatt Spinler uint32_t id; 41475e574dSMatt Spinler explicit Obmc(uint32_t i) : id(i) 42475e574dSMatt Spinler { 43475e574dSMatt Spinler } 44475e574dSMatt Spinler }; 45475e574dSMatt Spinler 46475e574dSMatt Spinler Pel pelID; 47475e574dSMatt Spinler 48475e574dSMatt Spinler Obmc obmcID; 49475e574dSMatt Spinler 50475e574dSMatt Spinler LogID(Pel pel, Obmc obmc) : pelID(pel), obmcID(obmc) 51475e574dSMatt Spinler { 52475e574dSMatt Spinler } 53475e574dSMatt Spinler 54475e574dSMatt Spinler explicit LogID(Pel id) : pelID(id), obmcID(0) 55475e574dSMatt Spinler { 56475e574dSMatt Spinler } 57475e574dSMatt Spinler 58475e574dSMatt Spinler explicit LogID(Obmc id) : pelID(0), obmcID(id) 59475e574dSMatt Spinler { 60475e574dSMatt Spinler } 61475e574dSMatt Spinler 62475e574dSMatt Spinler LogID() = delete; 63475e574dSMatt Spinler 64475e574dSMatt Spinler /** 65475e574dSMatt Spinler * @brief A == operator that will match on either ID 66475e574dSMatt Spinler * being equal if the other is zero, so that 67475e574dSMatt Spinler * one can look up a PEL with just one of the IDs. 68475e574dSMatt Spinler */ 69475e574dSMatt Spinler bool operator==(const LogID& id) const 70475e574dSMatt Spinler { 71475e574dSMatt Spinler if (id.pelID.id != 0) 72475e574dSMatt Spinler { 73475e574dSMatt Spinler return id.pelID.id == pelID.id; 74475e574dSMatt Spinler } 75475e574dSMatt Spinler if (id.obmcID.id != 0) 76475e574dSMatt Spinler { 77475e574dSMatt Spinler return id.obmcID.id == obmcID.id; 78475e574dSMatt Spinler } 79475e574dSMatt Spinler return false; 80475e574dSMatt Spinler } 81475e574dSMatt Spinler 82475e574dSMatt Spinler bool operator<(const LogID& id) const 83475e574dSMatt Spinler { 84475e574dSMatt Spinler return pelID.id < id.pelID.id; 85475e574dSMatt Spinler } 86475e574dSMatt Spinler }; 87475e574dSMatt Spinler 8889fa082aSMatt Spinler Repository() = delete; 8989fa082aSMatt Spinler ~Repository() = default; 9089fa082aSMatt Spinler Repository(const Repository&) = default; 9189fa082aSMatt Spinler Repository& operator=(const Repository&) = default; 9289fa082aSMatt Spinler Repository(Repository&&) = default; 9389fa082aSMatt Spinler Repository& operator=(Repository&&) = default; 9489fa082aSMatt Spinler 9589fa082aSMatt Spinler /** 9689fa082aSMatt Spinler * @brief Constructor 9789fa082aSMatt Spinler * 9889fa082aSMatt Spinler * @param[in] basePath - the base filesystem path for the repository 9989fa082aSMatt Spinler */ 10089fa082aSMatt Spinler Repository(const std::filesystem::path& basePath); 10189fa082aSMatt Spinler 10289fa082aSMatt Spinler /** 10389fa082aSMatt Spinler * @brief Adds a PEL to the repository 10489fa082aSMatt Spinler * 10589fa082aSMatt Spinler * Throws File.Error.Open or File.Error.Write exceptions on failure 10689fa082aSMatt Spinler * 10789fa082aSMatt Spinler * @param[in] pel - the PEL to add 10889fa082aSMatt Spinler */ 10989fa082aSMatt Spinler void add(std::unique_ptr<PEL>& pel); 11089fa082aSMatt Spinler 11189fa082aSMatt Spinler /** 112475e574dSMatt Spinler * @brief Removes a PEL from the repository 113475e574dSMatt Spinler * 114475e574dSMatt Spinler * @param[in] id - the ID (either the pel ID, OBMC ID, or both) to remove 115475e574dSMatt Spinler */ 116475e574dSMatt Spinler void remove(const LogID& id); 117475e574dSMatt Spinler 118475e574dSMatt Spinler /** 11989fa082aSMatt Spinler * @brief Generates the filename to use for the PEL ID and BCDTime. 12089fa082aSMatt Spinler * 12189fa082aSMatt Spinler * @param[in] pelID - the PEL ID 12289fa082aSMatt Spinler * @param[in] time - the BCD time 12389fa082aSMatt Spinler * 12489fa082aSMatt Spinler * @return string - A filename string of <BCD_time>_<pelID> 12589fa082aSMatt Spinler */ 12689fa082aSMatt Spinler static std::string getPELFilename(uint32_t pelID, const BCDTime& time); 12789fa082aSMatt Spinler 128475e574dSMatt Spinler /** 129475e574dSMatt Spinler * @brief Returns true if the PEL with the specified ID is in the repo. 130475e574dSMatt Spinler * 131475e574dSMatt Spinler * @param[in] id - the ID (either the pel ID, OBMC ID, or both) 132475e574dSMatt Spinler * @return bool - true if that PEL is present 133475e574dSMatt Spinler */ 134475e574dSMatt Spinler inline bool hasPEL(const LogID& id) 135475e574dSMatt Spinler { 136475e574dSMatt Spinler return findPEL(id) != _idsToPELs.end(); 137475e574dSMatt Spinler } 138475e574dSMatt Spinler 139*2813f36dSMatt Spinler /** 140*2813f36dSMatt Spinler * @brief Returns the PEL data based on its ID. 141*2813f36dSMatt Spinler * 142*2813f36dSMatt Spinler * If the data can't be found for that ID, then the optional object 143*2813f36dSMatt Spinler * will be empty. 144*2813f36dSMatt Spinler * 145*2813f36dSMatt Spinler * @param[in] id - the LogID to get the PEL for, which can be either a 146*2813f36dSMatt Spinler * PEL ID or OpenBMC log ID. 147*2813f36dSMatt Spinler * @return std::optional<std::vector<uint8_t>> - the PEL data 148*2813f36dSMatt Spinler */ 149*2813f36dSMatt Spinler std::optional<std::vector<uint8_t>> getPELData(const LogID& id); 150*2813f36dSMatt Spinler 15189fa082aSMatt Spinler private: 15289fa082aSMatt Spinler /** 153475e574dSMatt Spinler * @brief Finds an entry in the _idsToPELs map. 154475e574dSMatt Spinler * 155475e574dSMatt Spinler * @param[in] id - the ID (either the pel ID, OBMC ID, or both) 156475e574dSMatt Spinler * 157475e574dSMatt Spinler * @return an iterator to the entry 158475e574dSMatt Spinler */ 159475e574dSMatt Spinler std::map<LogID, std::filesystem::path>::iterator findPEL(const LogID& id) 160475e574dSMatt Spinler { 161475e574dSMatt Spinler return std::find_if(_idsToPELs.begin(), _idsToPELs.end(), 162475e574dSMatt Spinler [&id](const auto& i) { return i.first == id; }); 163475e574dSMatt Spinler } 164475e574dSMatt Spinler 165475e574dSMatt Spinler /** 166475e574dSMatt Spinler * @brief Restores the _idsToPELs map on startup based on the existing 167475e574dSMatt Spinler * PEL data files. 168475e574dSMatt Spinler */ 169475e574dSMatt Spinler void restore(); 170475e574dSMatt Spinler 171475e574dSMatt Spinler /** 17289fa082aSMatt Spinler * @brief The filesystem path to the PEL logs. 17389fa082aSMatt Spinler */ 17489fa082aSMatt Spinler const std::filesystem::path _logPath; 175475e574dSMatt Spinler 176475e574dSMatt Spinler /** 177475e574dSMatt Spinler * @brief A map of the PEL/OBMC IDs to the PEL data files. 178475e574dSMatt Spinler */ 179475e574dSMatt Spinler std::map<LogID, std::filesystem::path> _idsToPELs; 18089fa082aSMatt Spinler }; 18189fa082aSMatt Spinler 18289fa082aSMatt Spinler } // namespace pels 18389fa082aSMatt Spinler } // namespace openpower 184