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