1 #pragma once
2 #include "bcd_time.hpp"
3 #include "pel.hpp"
4 
5 #include <algorithm>
6 #include <filesystem>
7 #include <map>
8 
9 namespace openpower
10 {
11 namespace pels
12 {
13 
14 /**
15  * @class Repository
16  *
17  * The class handles saving and retrieving PELs on the BMC.
18  */
19 class Repository
20 {
21   public:
22     /**
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 
88     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     /**
112      * @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     /**
119      * @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 
128     /**
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 
139     /**
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 
151   private:
152     /**
153      * @brief Finds an entry in the _idsToPELs map.
154      *
155      * @param[in] id - the ID (either the pel ID, OBMC ID, or both)
156      *
157      * @return an iterator to the entry
158      */
159     std::map<LogID, std::filesystem::path>::iterator findPEL(const LogID& id)
160     {
161         return std::find_if(_idsToPELs.begin(), _idsToPELs.end(),
162                             [&id](const auto& i) { return i.first == id; });
163     }
164 
165     /**
166      * @brief Restores the _idsToPELs map on startup based on the existing
167      *        PEL data files.
168      */
169     void restore();
170 
171     /**
172      * @brief The filesystem path to the PEL logs.
173      */
174     const std::filesystem::path _logPath;
175 
176     /**
177      * @brief A map of the PEL/OBMC IDs to the PEL data files.
178      */
179     std::map<LogID, std::filesystem::path> _idsToPELs;
180 };
181 
182 } // namespace pels
183 } // namespace openpower
184