xref: /openbmc/phosphor-logging/extensions/openpower-pels/repository.cpp (revision db3f27988ed72a53203860641bd5f4a4190b4e4b)
1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler  * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler  *
4711d51d8SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler  * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler  * You may obtain a copy of the License at
7711d51d8SMatt Spinler  *
8711d51d8SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler  *
10711d51d8SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler  * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler  * limitations under the License.
15711d51d8SMatt Spinler  */
1689fa082aSMatt Spinler #include "repository.hpp"
1789fa082aSMatt Spinler 
1832a6df6cSMatt Spinler #include <fcntl.h>
19dd325c32SMatt Spinler #include <sys/stat.h>
20dd325c32SMatt Spinler 
21*db3f2798SMatt Spinler #include <phosphor-logging/lg2.hpp>
2289fa082aSMatt Spinler #include <xyz/openbmc_project/Common/File/error.hpp>
2389fa082aSMatt Spinler 
242544b419SPatrick Williams #include <fstream>
252544b419SPatrick Williams 
2689fa082aSMatt Spinler namespace openpower
2789fa082aSMatt Spinler {
2889fa082aSMatt Spinler namespace pels
2989fa082aSMatt Spinler {
3089fa082aSMatt Spinler 
3189fa082aSMatt Spinler namespace fs = std::filesystem;
3289fa082aSMatt Spinler namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
3389fa082aSMatt Spinler 
347e727a39SMatt Spinler constexpr size_t warningPercentage = 95;
357e727a39SMatt Spinler 
36dd325c32SMatt Spinler /**
37dd325c32SMatt Spinler  * @brief Returns the amount of space the file uses on disk.
38dd325c32SMatt Spinler  *
39dd325c32SMatt Spinler  * This is different than just the regular size of the file.
40dd325c32SMatt Spinler  *
41dd325c32SMatt Spinler  * @param[in] file - The file to get the size of
42dd325c32SMatt Spinler  *
43dd325c32SMatt Spinler  * @return size_t The disk space the file uses
44dd325c32SMatt Spinler  */
45dd325c32SMatt Spinler size_t getFileDiskSize(const std::filesystem::path& file)
46dd325c32SMatt Spinler {
47dd325c32SMatt Spinler     constexpr size_t statBlockSize = 512;
48dd325c32SMatt Spinler     struct stat statData;
49dd325c32SMatt Spinler     auto rc = stat(file.c_str(), &statData);
50dd325c32SMatt Spinler     if (rc != 0)
51dd325c32SMatt Spinler     {
52dd325c32SMatt Spinler         auto e = errno;
53*db3f2798SMatt Spinler         lg2::error("Call to stat() failed on {FILE} with errno {ERRNO}", "FILE",
54*db3f2798SMatt Spinler                    file.native(), "ERRNO", e);
55dd325c32SMatt Spinler         abort();
56dd325c32SMatt Spinler     }
57dd325c32SMatt Spinler 
58dd325c32SMatt Spinler     return statData.st_blocks * statBlockSize;
59dd325c32SMatt Spinler }
60dd325c32SMatt Spinler 
618d5f3a2bSMatt Spinler Repository::Repository(const std::filesystem::path& basePath, size_t repoSize,
628d5f3a2bSMatt Spinler                        size_t maxNumPELs) :
638d5f3a2bSMatt Spinler     _logPath(basePath / "logs"),
641d8835bbSSumit Kumar     _maxRepoSize(repoSize), _maxNumPELs(maxNumPELs),
651d8835bbSSumit Kumar     _archivePath(basePath / "logs" / "archive")
6689fa082aSMatt Spinler {
6789fa082aSMatt Spinler     if (!fs::exists(_logPath))
6889fa082aSMatt Spinler     {
6989fa082aSMatt Spinler         fs::create_directories(_logPath);
7089fa082aSMatt Spinler     }
71475e574dSMatt Spinler 
721d8835bbSSumit Kumar     if (!fs::exists(_archivePath))
731d8835bbSSumit Kumar     {
741d8835bbSSumit Kumar         fs::create_directories(_archivePath);
751d8835bbSSumit Kumar     }
761d8835bbSSumit Kumar 
77475e574dSMatt Spinler     restore();
78475e574dSMatt Spinler }
79475e574dSMatt Spinler 
80475e574dSMatt Spinler void Repository::restore()
81475e574dSMatt Spinler {
82475e574dSMatt Spinler     for (auto& dirEntry : fs::directory_iterator(_logPath))
83475e574dSMatt Spinler     {
84475e574dSMatt Spinler         try
85475e574dSMatt Spinler         {
86475e574dSMatt Spinler             if (!fs::is_regular_file(dirEntry.path()))
87475e574dSMatt Spinler             {
88475e574dSMatt Spinler                 continue;
89475e574dSMatt Spinler             }
90475e574dSMatt Spinler 
91475e574dSMatt Spinler             std::ifstream file{dirEntry.path()};
92475e574dSMatt Spinler             std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
93475e574dSMatt Spinler                                       std::istreambuf_iterator<char>()};
94475e574dSMatt Spinler             file.close();
95475e574dSMatt Spinler 
9607eefc54SMatt Spinler             PEL pel{data};
97475e574dSMatt Spinler             if (pel.valid())
98475e574dSMatt Spinler             {
99a3c12a48SMatt Spinler                 // If the host hasn't acked it, reset the host state so
100a3c12a48SMatt Spinler                 // it will get sent up again.
101a3c12a48SMatt Spinler                 if (pel.hostTransmissionState() == TransmissionState::sent)
102a3c12a48SMatt Spinler                 {
103a3c12a48SMatt Spinler                     pel.setHostTransmissionState(TransmissionState::newPEL);
104a3c12a48SMatt Spinler                     try
105a3c12a48SMatt Spinler                     {
106a3c12a48SMatt Spinler                         write(pel, dirEntry.path());
107a3c12a48SMatt Spinler                     }
10866491c61SPatrick Williams                     catch (const std::exception& e)
109a3c12a48SMatt Spinler                     {
110*db3f2798SMatt Spinler                         lg2::error(
111*db3f2798SMatt Spinler                             "Failed to save PEL after updating host state, PEL ID = {ID}",
112*db3f2798SMatt Spinler                             "ID", lg2::hex, pel.id());
113a3c12a48SMatt Spinler                     }
114a3c12a48SMatt Spinler                 }
115a3c12a48SMatt Spinler 
1168e65f4eaSMatt Spinler                 PELAttributes attributes{
1178e65f4eaSMatt Spinler                     dirEntry.path(),
118dd325c32SMatt Spinler                     getFileDiskSize(dirEntry.path()),
119dd325c32SMatt Spinler                     pel.privateHeader().creatorID(),
120afb1b46fSVijay Lobo                     pel.userHeader().subsystem(),
121dd325c32SMatt Spinler                     pel.userHeader().severity(),
122dd325c32SMatt Spinler                     pel.userHeader().actionFlags(),
123dd325c32SMatt Spinler                     pel.hostTransmissionState(),
1248e65f4eaSMatt Spinler                     pel.hmcTransmissionState(),
1258e65f4eaSMatt Spinler                     pel.plid(),
1268e65f4eaSMatt Spinler                     pel.getDeconfigFlag(),
1278e65f4eaSMatt Spinler                     pel.getGuardFlag(),
1288e65f4eaSMatt Spinler                     getMillisecondsSinceEpoch(
1298e65f4eaSMatt Spinler                         pel.privateHeader().createTimestamp())};
1300ff00485SMatt Spinler 
131475e574dSMatt Spinler                 using pelID = LogID::Pel;
132475e574dSMatt Spinler                 using obmcID = LogID::Obmc;
1330ff00485SMatt Spinler                 _pelAttributes.emplace(
134475e574dSMatt Spinler                     LogID(pelID(pel.id()), obmcID(pel.obmcLogID())),
1350ff00485SMatt Spinler                     attributes);
136b188f78aSMatt Spinler 
137b188f78aSMatt Spinler                 updateRepoStats(attributes, true);
138475e574dSMatt Spinler             }
139475e574dSMatt Spinler             else
140475e574dSMatt Spinler             {
141*db3f2798SMatt Spinler                 lg2::error(
142*db3f2798SMatt Spinler                     "Found invalid PEL file {FILE} while restoring.  Removing.",
143*db3f2798SMatt Spinler                     "FILE", dirEntry.path());
144475e574dSMatt Spinler                 fs::remove(dirEntry.path());
145475e574dSMatt Spinler             }
146475e574dSMatt Spinler         }
14766491c61SPatrick Williams         catch (const std::exception& e)
148475e574dSMatt Spinler         {
149*db3f2798SMatt Spinler             lg2::error("Hit exception while restoring PEL file {FILE}: {ERROR}",
150*db3f2798SMatt Spinler                        "FILE", dirEntry.path(), "ERROR", e);
151475e574dSMatt Spinler         }
152475e574dSMatt Spinler     }
1531d8835bbSSumit Kumar 
1541d8835bbSSumit Kumar     // Get size of archive folder
1551d8835bbSSumit Kumar     for (auto& dirEntry : fs::directory_iterator(_archivePath))
1561d8835bbSSumit Kumar     {
1571d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(dirEntry);
1581d8835bbSSumit Kumar     }
15989fa082aSMatt Spinler }
16089fa082aSMatt Spinler 
16189fa082aSMatt Spinler std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
16289fa082aSMatt Spinler {
16389fa082aSMatt Spinler     char name[50];
16489fa082aSMatt Spinler     sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", time.yearMSB,
16589fa082aSMatt Spinler             time.yearLSB, time.month, time.day, time.hour, time.minutes,
16689fa082aSMatt Spinler             time.seconds, time.hundredths, pelID);
16789fa082aSMatt Spinler     return std::string{name};
16889fa082aSMatt Spinler }
16989fa082aSMatt Spinler 
17089fa082aSMatt Spinler void Repository::add(std::unique_ptr<PEL>& pel)
17189fa082aSMatt Spinler {
172df43a305SMatt Spinler     pel->setHostTransmissionState(TransmissionState::newPEL);
173df43a305SMatt Spinler     pel->setHMCTransmissionState(TransmissionState::newPEL);
174df43a305SMatt Spinler 
17589fa082aSMatt Spinler     auto path = _logPath / getPELFilename(pel->id(), pel->commitTime());
176ab1b97feSMatt Spinler 
177ab1b97feSMatt Spinler     write(*(pel.get()), path);
178ab1b97feSMatt Spinler 
1798e65f4eaSMatt Spinler     PELAttributes attributes{
1808e65f4eaSMatt Spinler         path,
181dd325c32SMatt Spinler         getFileDiskSize(path),
182dd325c32SMatt Spinler         pel->privateHeader().creatorID(),
183afb1b46fSVijay Lobo         pel->userHeader().subsystem(),
184dd325c32SMatt Spinler         pel->userHeader().severity(),
185dd325c32SMatt Spinler         pel->userHeader().actionFlags(),
186346f99a1SMatt Spinler         pel->hostTransmissionState(),
1878e65f4eaSMatt Spinler         pel->hmcTransmissionState(),
1888e65f4eaSMatt Spinler         pel->plid(),
1898e65f4eaSMatt Spinler         pel->getDeconfigFlag(),
1908e65f4eaSMatt Spinler         pel->getGuardFlag(),
1918e65f4eaSMatt Spinler         getMillisecondsSinceEpoch(pel->privateHeader().createTimestamp())};
192ab1b97feSMatt Spinler 
193ab1b97feSMatt Spinler     using pelID = LogID::Pel;
194ab1b97feSMatt Spinler     using obmcID = LogID::Obmc;
195ab1b97feSMatt Spinler     _pelAttributes.emplace(LogID(pelID(pel->id()), obmcID(pel->obmcLogID())),
196ab1b97feSMatt Spinler                            attributes);
197ab1b97feSMatt Spinler 
19844893cc9SMatt Spinler     _lastPelID = pel->id();
19944893cc9SMatt Spinler 
200b188f78aSMatt Spinler     updateRepoStats(attributes, true);
201b188f78aSMatt Spinler 
202ab1b97feSMatt Spinler     processAddCallbacks(*pel);
203ab1b97feSMatt Spinler }
204ab1b97feSMatt Spinler 
205ab1b97feSMatt Spinler void Repository::write(const PEL& pel, const fs::path& path)
206ab1b97feSMatt Spinler {
20789fa082aSMatt Spinler     std::ofstream file{path, std::ios::binary};
20889fa082aSMatt Spinler 
20989fa082aSMatt Spinler     if (!file.good())
21089fa082aSMatt Spinler     {
21189fa082aSMatt Spinler         // If this fails, the filesystem is probably full so it isn't like
21289fa082aSMatt Spinler         // we could successfully create yet another error log here.
21389fa082aSMatt Spinler         auto e = errno;
21489fa082aSMatt Spinler         fs::remove(path);
215*db3f2798SMatt Spinler         lg2::error(
216*db3f2798SMatt Spinler             "Unable to open PEL file {FILE} for writing, errno = {ERRNO}",
217*db3f2798SMatt Spinler             "FILE", path, "ERRNO", e);
21889fa082aSMatt Spinler         throw file_error::Open();
21989fa082aSMatt Spinler     }
22089fa082aSMatt Spinler 
221ab1b97feSMatt Spinler     auto data = pel.data();
22289fa082aSMatt Spinler     file.write(reinterpret_cast<const char*>(data.data()), data.size());
22389fa082aSMatt Spinler 
22489fa082aSMatt Spinler     if (file.fail())
22589fa082aSMatt Spinler     {
22689fa082aSMatt Spinler         // Same note as above about not being able to create an error log
22789fa082aSMatt Spinler         // for this case even if we wanted.
22889fa082aSMatt Spinler         auto e = errno;
22989fa082aSMatt Spinler         file.close();
23089fa082aSMatt Spinler         fs::remove(path);
231*db3f2798SMatt Spinler         lg2::error("Unable to write PEL file {FILE}, errno = {ERRNO}", "FILE",
232*db3f2798SMatt Spinler                    path, "ERRNO", e);
23389fa082aSMatt Spinler         throw file_error::Write();
23489fa082aSMatt Spinler     }
235475e574dSMatt Spinler }
236475e574dSMatt Spinler 
23752602e35SMatt Spinler std::optional<Repository::LogID> Repository::remove(const LogID& id)
238475e574dSMatt Spinler {
239475e574dSMatt Spinler     auto pel = findPEL(id);
240ff6b598bSPatrick Williams     if (pel == _pelAttributes.end())
241475e574dSMatt Spinler     {
242ff6b598bSPatrick Williams         return std::nullopt;
243ff6b598bSPatrick Williams     }
244ff6b598bSPatrick Williams 
245ff6b598bSPatrick Williams     LogID actualID = pel->first;
246b188f78aSMatt Spinler     updateRepoStats(pel->second, false);
247b188f78aSMatt Spinler 
248*db3f2798SMatt Spinler     lg2::debug(
249*db3f2798SMatt Spinler         "Removing PEL from repository, PEL ID = {PEL_ID}, BMC log ID = {BMC_ID}",
250*db3f2798SMatt Spinler         "PEL_ID", lg2::hex, actualID.pelID.id, "BMC_ID", actualID.obmcID.id);
2511d8835bbSSumit Kumar 
2521d8835bbSSumit Kumar     if (fs::exists(pel->second.path))
2531d8835bbSSumit Kumar     {
2541d8835bbSSumit Kumar         // Check for existense of new archive folder
2551d8835bbSSumit Kumar         if (!fs::exists(_archivePath))
2561d8835bbSSumit Kumar         {
2571d8835bbSSumit Kumar             fs::create_directories(_archivePath);
2581d8835bbSSumit Kumar         }
2591d8835bbSSumit Kumar 
2601d8835bbSSumit Kumar         // Move log file to archive folder
2611d8835bbSSumit Kumar         auto fileName = _archivePath / pel->second.path.filename();
2621d8835bbSSumit Kumar         fs::rename(pel->second.path, fileName);
2631d8835bbSSumit Kumar 
2641d8835bbSSumit Kumar         // Update size of file
2651d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(fileName);
2661d8835bbSSumit Kumar     }
2671d8835bbSSumit Kumar 
2680ff00485SMatt Spinler     _pelAttributes.erase(pel);
269421f6531SMatt Spinler 
270ff6b598bSPatrick Williams     processDeleteCallbacks(actualID.pelID.id);
27152602e35SMatt Spinler 
27252602e35SMatt Spinler     return actualID;
27389fa082aSMatt Spinler }
27489fa082aSMatt Spinler 
2752813f36dSMatt Spinler std::optional<std::vector<uint8_t>> Repository::getPELData(const LogID& id)
2762813f36dSMatt Spinler {
2772813f36dSMatt Spinler     auto pel = findPEL(id);
2780ff00485SMatt Spinler     if (pel != _pelAttributes.end())
2792813f36dSMatt Spinler     {
2800ff00485SMatt Spinler         std::ifstream file{pel->second.path.c_str()};
2812813f36dSMatt Spinler         if (!file.good())
2822813f36dSMatt Spinler         {
2832813f36dSMatt Spinler             auto e = errno;
284*db3f2798SMatt Spinler             lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
285*db3f2798SMatt Spinler                        "FILE", pel->second.path, "ERRNO", e);
2862813f36dSMatt Spinler             throw file_error::Open();
2872813f36dSMatt Spinler         }
2882813f36dSMatt Spinler 
2892813f36dSMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
2902813f36dSMatt Spinler                                   std::istreambuf_iterator<char>()};
2912813f36dSMatt Spinler         return data;
2922813f36dSMatt Spinler     }
2932813f36dSMatt Spinler 
2942813f36dSMatt Spinler     return std::nullopt;
2952813f36dSMatt Spinler }
2962813f36dSMatt Spinler 
2976d51224bSMatt Spinler std::optional<sdbusplus::message::unix_fd> Repository::getPELFD(const LogID& id)
2986d51224bSMatt Spinler {
2996d51224bSMatt Spinler     auto pel = findPEL(id);
3006d51224bSMatt Spinler     if (pel != _pelAttributes.end())
3016d51224bSMatt Spinler     {
30232a6df6cSMatt Spinler         int fd = open(pel->second.path.c_str(), O_RDONLY | O_NONBLOCK);
30332a6df6cSMatt Spinler         if (fd == -1)
3046d51224bSMatt Spinler         {
3056d51224bSMatt Spinler             auto e = errno;
306*db3f2798SMatt Spinler             lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
307*db3f2798SMatt Spinler                        "FILE", pel->second.path, "ERRNO", e);
3086d51224bSMatt Spinler             throw file_error::Open();
3096d51224bSMatt Spinler         }
3106d51224bSMatt Spinler 
3116d51224bSMatt Spinler         // Must leave the file open here.  It will be closed by sdbusplus
3126d51224bSMatt Spinler         // when it sends it back over D-Bus.
31332a6df6cSMatt Spinler         return fd;
3146d51224bSMatt Spinler     }
3156d51224bSMatt Spinler     return std::nullopt;
3166d51224bSMatt Spinler }
3176d51224bSMatt Spinler 
3181ea78801SMatt Spinler void Repository::for_each(ForEachFunc func) const
3191ea78801SMatt Spinler {
3200ff00485SMatt Spinler     for (const auto& [id, attributes] : _pelAttributes)
3211ea78801SMatt Spinler     {
3220ff00485SMatt Spinler         std::ifstream file{attributes.path};
3231ea78801SMatt Spinler 
3241ea78801SMatt Spinler         if (!file.good())
3251ea78801SMatt Spinler         {
3261ea78801SMatt Spinler             auto e = errno;
327*db3f2798SMatt Spinler             lg2::error(
328*db3f2798SMatt Spinler                 "Repository::for_each: Unable to open PEL file {FILE}, errno = {ERRNO}",
329*db3f2798SMatt Spinler                 "FILE", attributes.path, "ERRNO", e);
3301ea78801SMatt Spinler             continue;
3311ea78801SMatt Spinler         }
3321ea78801SMatt Spinler 
3331ea78801SMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
3341ea78801SMatt Spinler                                   std::istreambuf_iterator<char>()};
3351ea78801SMatt Spinler         file.close();
3361ea78801SMatt Spinler 
3371ea78801SMatt Spinler         PEL pel{data};
3381ea78801SMatt Spinler 
3391ea78801SMatt Spinler         try
3401ea78801SMatt Spinler         {
3411ea78801SMatt Spinler             if (func(pel))
3421ea78801SMatt Spinler             {
3431ea78801SMatt Spinler                 break;
3441ea78801SMatt Spinler             }
3451ea78801SMatt Spinler         }
34666491c61SPatrick Williams         catch (const std::exception& e)
3471ea78801SMatt Spinler         {
348*db3f2798SMatt Spinler             lg2::error("Repository::for_each function exception: {ERROR}",
349*db3f2798SMatt Spinler                        "ERROR", e);
3501ea78801SMatt Spinler         }
3511ea78801SMatt Spinler     }
3521ea78801SMatt Spinler }
3531ea78801SMatt Spinler 
354421f6531SMatt Spinler void Repository::processAddCallbacks(const PEL& pel) const
355421f6531SMatt Spinler {
356421f6531SMatt Spinler     for (auto& [name, func] : _addSubscriptions)
357421f6531SMatt Spinler     {
358421f6531SMatt Spinler         try
359421f6531SMatt Spinler         {
360421f6531SMatt Spinler             func(pel);
361421f6531SMatt Spinler         }
36266491c61SPatrick Williams         catch (const std::exception& e)
363421f6531SMatt Spinler         {
364*db3f2798SMatt Spinler             lg2::error(
365*db3f2798SMatt Spinler                 "PEL Repository add callback exception. Name = {NAME}, Error = {ERROR}",
366*db3f2798SMatt Spinler                 "NAME", name, "ERROR", e);
367421f6531SMatt Spinler         }
368421f6531SMatt Spinler     }
369421f6531SMatt Spinler }
370421f6531SMatt Spinler 
371421f6531SMatt Spinler void Repository::processDeleteCallbacks(uint32_t id) const
372421f6531SMatt Spinler {
373421f6531SMatt Spinler     for (auto& [name, func] : _deleteSubscriptions)
374421f6531SMatt Spinler     {
375421f6531SMatt Spinler         try
376421f6531SMatt Spinler         {
377421f6531SMatt Spinler             func(id);
378421f6531SMatt Spinler         }
37966491c61SPatrick Williams         catch (const std::exception& e)
380421f6531SMatt Spinler         {
381*db3f2798SMatt Spinler             lg2::error(
382*db3f2798SMatt Spinler                 "PEL Repository delete callback exception. Name = {NAME}, Error = {ERROR}",
383*db3f2798SMatt Spinler                 "NAME", name, "ERROR", e);
384421f6531SMatt Spinler         }
385421f6531SMatt Spinler     }
386421f6531SMatt Spinler }
387421f6531SMatt Spinler 
3880ff00485SMatt Spinler std::optional<std::reference_wrapper<const Repository::PELAttributes>>
3890ff00485SMatt Spinler     Repository::getPELAttributes(const LogID& id) const
3900ff00485SMatt Spinler {
3910ff00485SMatt Spinler     auto pel = findPEL(id);
3920ff00485SMatt Spinler     if (pel != _pelAttributes.end())
3930ff00485SMatt Spinler     {
3940ff00485SMatt Spinler         return pel->second;
3950ff00485SMatt Spinler     }
3960ff00485SMatt Spinler 
3970ff00485SMatt Spinler     return std::nullopt;
3980ff00485SMatt Spinler }
3990ff00485SMatt Spinler 
40029d18c11SMatt Spinler void Repository::setPELHostTransState(uint32_t pelID, TransmissionState state)
40129d18c11SMatt Spinler {
40229d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
40329d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
40429d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
40529d18c11SMatt Spinler 
40629d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hostState != state))
40729d18c11SMatt Spinler     {
40829d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
40929d18c11SMatt Spinler             pel.setHostTransmissionState(state);
410d0ccda3cSMatt Spinler             return true;
41129d18c11SMatt Spinler         };
41229d18c11SMatt Spinler 
41329d18c11SMatt Spinler         try
41429d18c11SMatt Spinler         {
41529d18c11SMatt Spinler             updatePEL(attr->second.path, func);
41629d18c11SMatt Spinler         }
41766491c61SPatrick Williams         catch (const std::exception& e)
41829d18c11SMatt Spinler         {
419*db3f2798SMatt Spinler             lg2::error(
420*db3f2798SMatt Spinler                 "Unable to update PEL host transmission state. Path = {PATH}, Error = {ERROR}",
421*db3f2798SMatt Spinler                 "PATH", attr->second.path, "ERROR", e);
42229d18c11SMatt Spinler         }
42329d18c11SMatt Spinler     }
42429d18c11SMatt Spinler }
42529d18c11SMatt Spinler 
42629d18c11SMatt Spinler void Repository::setPELHMCTransState(uint32_t pelID, TransmissionState state)
42729d18c11SMatt Spinler {
42829d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
42929d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
43029d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
43129d18c11SMatt Spinler 
43229d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hmcState != state))
43329d18c11SMatt Spinler     {
43429d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
43529d18c11SMatt Spinler             pel.setHMCTransmissionState(state);
436d0ccda3cSMatt Spinler             return true;
43729d18c11SMatt Spinler         };
43829d18c11SMatt Spinler 
43929d18c11SMatt Spinler         try
44029d18c11SMatt Spinler         {
44129d18c11SMatt Spinler             updatePEL(attr->second.path, func);
44229d18c11SMatt Spinler         }
44366491c61SPatrick Williams         catch (const std::exception& e)
44429d18c11SMatt Spinler         {
445*db3f2798SMatt Spinler             lg2::error(
446*db3f2798SMatt Spinler                 "Unable to update PEL HMC transmission state. Path = {PATH}, Error = {ERROR}",
447*db3f2798SMatt Spinler                 "PATH", attr->second.path, "ERROR", e);
44829d18c11SMatt Spinler         }
44929d18c11SMatt Spinler     }
45029d18c11SMatt Spinler }
45129d18c11SMatt Spinler 
45229d18c11SMatt Spinler void Repository::updatePEL(const fs::path& path, PELUpdateFunc updateFunc)
45329d18c11SMatt Spinler {
45429d18c11SMatt Spinler     std::ifstream file{path};
45529d18c11SMatt Spinler     std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
45629d18c11SMatt Spinler                               std::istreambuf_iterator<char>()};
45729d18c11SMatt Spinler     file.close();
45829d18c11SMatt Spinler 
45929d18c11SMatt Spinler     PEL pel{data};
46029d18c11SMatt Spinler 
46129d18c11SMatt Spinler     if (pel.valid())
46229d18c11SMatt Spinler     {
463d0ccda3cSMatt Spinler         if (updateFunc(pel))
464d0ccda3cSMatt Spinler         {
465d0ccda3cSMatt Spinler             // Three attribute fields can change post creation from
466d0ccda3cSMatt Spinler             // an updatePEL call:
467d0ccda3cSMatt Spinler             //  - hmcTransmissionState - When HMC acks a PEL
468d0ccda3cSMatt Spinler             //  - hostTransmissionState - When host acks a PEL
469d0ccda3cSMatt Spinler             //  - deconfig flag - Can be cleared for PELs that call out
470d0ccda3cSMatt Spinler             //                    hotplugged FRUs.
471d0ccda3cSMatt Spinler             // Make sure they're up to date.
472d0ccda3cSMatt Spinler             LogID id{LogID::Pel(pel.id())};
473d0ccda3cSMatt Spinler             auto attr =
474d0ccda3cSMatt Spinler                 std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
475d0ccda3cSMatt Spinler                              [&id](const auto& a) { return a.first == id; });
476d0ccda3cSMatt Spinler             if (attr != _pelAttributes.end())
477d0ccda3cSMatt Spinler             {
478d0ccda3cSMatt Spinler                 attr->second.hmcState = pel.hmcTransmissionState();
479d0ccda3cSMatt Spinler                 attr->second.hostState = pel.hostTransmissionState();
480d0ccda3cSMatt Spinler                 attr->second.deconfig = pel.getDeconfigFlag();
481d0ccda3cSMatt Spinler             }
48229d18c11SMatt Spinler 
48329d18c11SMatt Spinler             write(pel, path);
48429d18c11SMatt Spinler         }
485d0ccda3cSMatt Spinler     }
48629d18c11SMatt Spinler     else
48729d18c11SMatt Spinler     {
48829d18c11SMatt Spinler         throw std::runtime_error(
48929d18c11SMatt Spinler             "Unable to read a valid PEL when trying to update it");
49029d18c11SMatt Spinler     }
49129d18c11SMatt Spinler }
49229d18c11SMatt Spinler 
493b188f78aSMatt Spinler bool Repository::isServiceableSev(const PELAttributes& pel)
494b188f78aSMatt Spinler {
495b188f78aSMatt Spinler     auto sevType = static_cast<SeverityType>(pel.severity & 0xF0);
4962544b419SPatrick Williams     auto sevPVEntry = pel_values::findByValue(pel.severity,
4972544b419SPatrick Williams                                               pel_values::severityValues);
498b188f78aSMatt Spinler     std::string sevName = std::get<pel_values::registryNamePos>(*sevPVEntry);
499b188f78aSMatt Spinler 
500b188f78aSMatt Spinler     bool check1 = (sevType == SeverityType::predictive) ||
501b188f78aSMatt Spinler                   (sevType == SeverityType::unrecoverable) ||
502b188f78aSMatt Spinler                   (sevType == SeverityType::critical);
503b188f78aSMatt Spinler 
504b188f78aSMatt Spinler     bool check2 = ((sevType == SeverityType::recovered) ||
505b188f78aSMatt Spinler                    (sevName == "symptom_recovered")) &&
506b188f78aSMatt Spinler                   !pel.actionFlags.test(hiddenFlagBit);
507b188f78aSMatt Spinler 
508b188f78aSMatt Spinler     bool check3 = (sevName == "symptom_predictive") ||
509b188f78aSMatt Spinler                   (sevName == "symptom_unrecoverable") ||
510b188f78aSMatt Spinler                   (sevName == "symptom_critical");
511b188f78aSMatt Spinler 
512b188f78aSMatt Spinler     return check1 || check2 || check3;
513b188f78aSMatt Spinler }
514b188f78aSMatt Spinler 
515b188f78aSMatt Spinler void Repository::updateRepoStats(const PELAttributes& pel, bool pelAdded)
516b188f78aSMatt Spinler {
517b188f78aSMatt Spinler     auto isServiceable = Repository::isServiceableSev(pel);
518b188f78aSMatt Spinler     auto bmcPEL = CreatorID::openBMC == static_cast<CreatorID>(pel.creator);
519b188f78aSMatt Spinler 
520b188f78aSMatt Spinler     auto adjustSize = [pelAdded, &pel](auto& runningSize) {
521b188f78aSMatt Spinler         if (pelAdded)
522b188f78aSMatt Spinler         {
523b188f78aSMatt Spinler             runningSize += pel.sizeOnDisk;
524b188f78aSMatt Spinler         }
525b188f78aSMatt Spinler         else
526b188f78aSMatt Spinler         {
527b188f78aSMatt Spinler             runningSize = std::max(static_cast<int64_t>(runningSize) -
528b188f78aSMatt Spinler                                        static_cast<int64_t>(pel.sizeOnDisk),
529b188f78aSMatt Spinler                                    static_cast<int64_t>(0));
530b188f78aSMatt Spinler         }
531b188f78aSMatt Spinler     };
532b188f78aSMatt Spinler 
533b188f78aSMatt Spinler     adjustSize(_sizes.total);
534b188f78aSMatt Spinler 
535b188f78aSMatt Spinler     if (bmcPEL)
536b188f78aSMatt Spinler     {
537b188f78aSMatt Spinler         adjustSize(_sizes.bmc);
538b188f78aSMatt Spinler         if (isServiceable)
539b188f78aSMatt Spinler         {
540b188f78aSMatt Spinler             adjustSize(_sizes.bmcServiceable);
541b188f78aSMatt Spinler         }
542b188f78aSMatt Spinler         else
543b188f78aSMatt Spinler         {
544b188f78aSMatt Spinler             adjustSize(_sizes.bmcInfo);
545b188f78aSMatt Spinler         }
546b188f78aSMatt Spinler     }
547b188f78aSMatt Spinler     else
548b188f78aSMatt Spinler     {
549b188f78aSMatt Spinler         adjustSize(_sizes.nonBMC);
550b188f78aSMatt Spinler         if (isServiceable)
551b188f78aSMatt Spinler         {
552b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCServiceable);
553b188f78aSMatt Spinler         }
554b188f78aSMatt Spinler         else
555b188f78aSMatt Spinler         {
556b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCInfo);
557b188f78aSMatt Spinler         }
558b188f78aSMatt Spinler     }
559b188f78aSMatt Spinler }
560b188f78aSMatt Spinler 
561c296692bSSumit Kumar bool Repository::sizeWarning()
5627e727a39SMatt Spinler {
563c296692bSSumit Kumar     std::error_code ec;
564c296692bSSumit Kumar 
5651d8835bbSSumit Kumar     if ((_archiveSize > 0) && ((_sizes.total + _archiveSize) >
5661d8835bbSSumit Kumar                                ((_maxRepoSize * warningPercentage) / 100)))
5671d8835bbSSumit Kumar     {
568*db3f2798SMatt Spinler         lg2::info(
5691d8835bbSSumit Kumar             "Repository::sizeWarning function:Deleting the files in archive");
5701d8835bbSSumit Kumar 
571c296692bSSumit Kumar         for (const auto& dirEntry : fs::directory_iterator(_archivePath))
5721d8835bbSSumit Kumar         {
573c296692bSSumit Kumar             fs::remove(dirEntry.path(), ec);
574c296692bSSumit Kumar             if (ec)
575c296692bSSumit Kumar             {
576*db3f2798SMatt Spinler                 lg2::info("Repository::sizeWarning: Could not delete "
577*db3f2798SMatt Spinler                           "file {FILE} in PEL archive",
578*db3f2798SMatt Spinler                           "FILE", dirEntry.path());
5791d8835bbSSumit Kumar             }
5801d8835bbSSumit Kumar         }
5811d8835bbSSumit Kumar 
582c296692bSSumit Kumar         _archiveSize = 0;
583c296692bSSumit Kumar     }
584c296692bSSumit Kumar 
5857e727a39SMatt Spinler     return (_sizes.total > (_maxRepoSize * warningPercentage / 100)) ||
5867e727a39SMatt Spinler            (_pelAttributes.size() > _maxNumPELs);
5877e727a39SMatt Spinler }
5887e727a39SMatt Spinler 
589b0a8df5bSMatt Spinler std::vector<Repository::AttributesReference>
590b0a8df5bSMatt Spinler     Repository::getAllPELAttributes(SortOrder order) const
591b0a8df5bSMatt Spinler {
592b0a8df5bSMatt Spinler     std::vector<Repository::AttributesReference> attributes;
593b0a8df5bSMatt Spinler 
594ac1ba3f2SPatrick Williams     std::for_each(_pelAttributes.begin(), _pelAttributes.end(),
595ac1ba3f2SPatrick Williams                   [&attributes](auto& pelEntry) {
596ac1ba3f2SPatrick Williams         attributes.push_back(pelEntry);
597ac1ba3f2SPatrick Williams     });
598b0a8df5bSMatt Spinler 
599b0a8df5bSMatt Spinler     std::sort(attributes.begin(), attributes.end(),
600b0a8df5bSMatt Spinler               [order](const auto& left, const auto& right) {
601b0a8df5bSMatt Spinler         if (order == SortOrder::ascending)
602b0a8df5bSMatt Spinler         {
603b0a8df5bSMatt Spinler             return left.get().second.path < right.get().second.path;
604b0a8df5bSMatt Spinler         }
605b0a8df5bSMatt Spinler         return left.get().second.path > right.get().second.path;
606b0a8df5bSMatt Spinler     });
607b0a8df5bSMatt Spinler 
608b0a8df5bSMatt Spinler     return attributes;
609b0a8df5bSMatt Spinler }
610b0a8df5bSMatt Spinler 
611027bf285SSumit Kumar std::vector<uint32_t>
612027bf285SSumit Kumar     Repository::prune(const std::vector<uint32_t>& idsWithHwIsoEntry)
613b0a8df5bSMatt Spinler {
614b0a8df5bSMatt Spinler     std::vector<uint32_t> obmcLogIDs;
615*db3f2798SMatt Spinler     lg2::info("Pruning PEL repository that takes up {TOTAL} bytes and has "
616*db3f2798SMatt Spinler               "{NUM_PELS} PELs",
617*db3f2798SMatt Spinler               "TOTAL", _sizes.total, "NUM_PELS", _pelAttributes.size());
618b0a8df5bSMatt Spinler 
619b0a8df5bSMatt Spinler     // Set up the 5 functions to check if the PEL category
620b0a8df5bSMatt Spinler     // is still over its limits.
621b0a8df5bSMatt Spinler 
622b0a8df5bSMatt Spinler     // BMC informational PELs should only take up 15%
623b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCInfoLimit = [this]() {
624b0a8df5bSMatt Spinler         return _sizes.bmcInfo > _maxRepoSize * 15 / 100;
625b0a8df5bSMatt Spinler     };
626b0a8df5bSMatt Spinler 
627b0a8df5bSMatt Spinler     // BMC non informational PELs should only take up 30%
628b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCNonInfoLimit = [this]() {
629b0a8df5bSMatt Spinler         return _sizes.bmcServiceable > _maxRepoSize * 30 / 100;
630b0a8df5bSMatt Spinler     };
631b0a8df5bSMatt Spinler 
632b0a8df5bSMatt Spinler     // Non BMC informational PELs should only take up 15%
633b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCInfoLimit = [this]() {
634b0a8df5bSMatt Spinler         return _sizes.nonBMCInfo > _maxRepoSize * 15 / 100;
635b0a8df5bSMatt Spinler     };
636b0a8df5bSMatt Spinler 
637b0a8df5bSMatt Spinler     // Non BMC non informational PELs should only take up 15%
638b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCNonInfoLimit = [this]() {
639b0a8df5bSMatt Spinler         return _sizes.nonBMCServiceable > _maxRepoSize * 30 / 100;
640b0a8df5bSMatt Spinler     };
641b0a8df5bSMatt Spinler 
642b0a8df5bSMatt Spinler     // Bring the total number of PELs down to 80% of the max
643b0a8df5bSMatt Spinler     IsOverLimitFunc tooManyPELsLimit = [this]() {
644b0a8df5bSMatt Spinler         return _pelAttributes.size() > _maxNumPELs * 80 / 100;
645b0a8df5bSMatt Spinler     };
646b0a8df5bSMatt Spinler 
647b0a8df5bSMatt Spinler     // Set up the functions to determine which category a PEL is in.
648b0a8df5bSMatt Spinler     // TODO: Return false in these functions if a PEL caused a guard record.
649b0a8df5bSMatt Spinler 
650b0a8df5bSMatt Spinler     // A BMC informational PEL
651b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCInfo = [](const PELAttributes& pel) {
652b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
653b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
654b0a8df5bSMatt Spinler     };
655b0a8df5bSMatt Spinler 
656b0a8df5bSMatt Spinler     // A BMC non informational PEL
657b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCNonInfo = [](const PELAttributes& pel) {
658b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
659b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
660b0a8df5bSMatt Spinler     };
661b0a8df5bSMatt Spinler 
662b0a8df5bSMatt Spinler     // A non BMC informational PEL
663b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCInfo = [](const PELAttributes& pel) {
664b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
665b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
666b0a8df5bSMatt Spinler     };
667b0a8df5bSMatt Spinler 
668b0a8df5bSMatt Spinler     // A non BMC non informational PEL
669b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCNonInfo = [](const PELAttributes& pel) {
670b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
671b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
672b0a8df5bSMatt Spinler     };
673b0a8df5bSMatt Spinler 
674b0a8df5bSMatt Spinler     // When counting PELs, count every PEL
675d26fa3e7SPatrick Williams     IsPELTypeFunc isAnyPEL = [](const PELAttributes& /*pel*/) { return true; };
676b0a8df5bSMatt Spinler 
677b0a8df5bSMatt Spinler     // Check all 4 categories, which will result in at most 90%
678b0a8df5bSMatt Spinler     // usage (15 + 30 + 15 + 30).
679027bf285SSumit Kumar     removePELs(overBMCInfoLimit, isBMCInfo, idsWithHwIsoEntry, obmcLogIDs);
680027bf285SSumit Kumar     removePELs(overBMCNonInfoLimit, isBMCNonInfo, idsWithHwIsoEntry,
681027bf285SSumit Kumar                obmcLogIDs);
682027bf285SSumit Kumar     removePELs(overNonBMCInfoLimit, isNonBMCInfo, idsWithHwIsoEntry,
683027bf285SSumit Kumar                obmcLogIDs);
684027bf285SSumit Kumar     removePELs(overNonBMCNonInfoLimit, isNonBMCNonInfo, idsWithHwIsoEntry,
685027bf285SSumit Kumar                obmcLogIDs);
686b0a8df5bSMatt Spinler 
687b0a8df5bSMatt Spinler     // After the above pruning check if there are still too many PELs,
688b0a8df5bSMatt Spinler     // which can happen depending on PEL sizes.
689b0a8df5bSMatt Spinler     if (_pelAttributes.size() > _maxNumPELs)
690b0a8df5bSMatt Spinler     {
691027bf285SSumit Kumar         removePELs(tooManyPELsLimit, isAnyPEL, idsWithHwIsoEntry, obmcLogIDs);
692b0a8df5bSMatt Spinler     }
693b0a8df5bSMatt Spinler 
694b0a8df5bSMatt Spinler     if (!obmcLogIDs.empty())
695b0a8df5bSMatt Spinler     {
696*db3f2798SMatt Spinler         lg2::info("Number of PELs removed to save space: {NUM_PELS}",
697*db3f2798SMatt Spinler                   "NUM_PELS", obmcLogIDs.size());
698b0a8df5bSMatt Spinler     }
699b0a8df5bSMatt Spinler 
700b0a8df5bSMatt Spinler     return obmcLogIDs;
701b0a8df5bSMatt Spinler }
702b0a8df5bSMatt Spinler 
70345796e82SMatt Spinler void Repository::removePELs(const IsOverLimitFunc& isOverLimit,
70445796e82SMatt Spinler                             const IsPELTypeFunc& isPELType,
705027bf285SSumit Kumar                             const std::vector<uint32_t>& idsWithHwIsoEntry,
706b0a8df5bSMatt Spinler                             std::vector<uint32_t>& removedBMCLogIDs)
707b0a8df5bSMatt Spinler {
708b0a8df5bSMatt Spinler     if (!isOverLimit())
709b0a8df5bSMatt Spinler     {
710b0a8df5bSMatt Spinler         return;
711b0a8df5bSMatt Spinler     }
712b0a8df5bSMatt Spinler 
713b0a8df5bSMatt Spinler     auto attributes = getAllPELAttributes(SortOrder::ascending);
714b0a8df5bSMatt Spinler 
715b0a8df5bSMatt Spinler     // Make 4 passes on the PELs, stopping as soon as isOverLimit
716b0a8df5bSMatt Spinler     // returns false.
717b0a8df5bSMatt Spinler     //   Pass 1: only delete HMC acked PELs
718b0a8df5bSMatt Spinler     //   Pass 2: only delete OS acked PELs
719b0a8df5bSMatt Spinler     //   Pass 3: only delete PHYP sent PELs
720b0a8df5bSMatt Spinler     //   Pass 4: delete all PELs
721b0a8df5bSMatt Spinler     static const std::vector<std::function<bool(const PELAttributes& pel)>>
722b0a8df5bSMatt Spinler         stateChecks{[](const auto& pel) {
723b0a8df5bSMatt Spinler         return pel.hmcState == TransmissionState::acked;
724b0a8df5bSMatt Spinler                     },
725b0a8df5bSMatt Spinler 
726b0a8df5bSMatt Spinler                     [](const auto& pel) {
727b0a8df5bSMatt Spinler         return pel.hostState == TransmissionState::acked;
728b0a8df5bSMatt Spinler         },
729b0a8df5bSMatt Spinler 
730b0a8df5bSMatt Spinler         [](const auto& pel) {
731b0a8df5bSMatt Spinler         return pel.hostState == TransmissionState::sent;
732b0a8df5bSMatt Spinler         },
733b0a8df5bSMatt Spinler 
734d26fa3e7SPatrick Williams         [](const auto& /*pel*/) { return true; }};
735b0a8df5bSMatt Spinler 
736b0a8df5bSMatt Spinler     for (const auto& stateCheck : stateChecks)
737b0a8df5bSMatt Spinler     {
738b0a8df5bSMatt Spinler         for (auto it = attributes.begin(); it != attributes.end();)
739b0a8df5bSMatt Spinler         {
740b0a8df5bSMatt Spinler             const auto& pel = it->get();
741b0a8df5bSMatt Spinler             if (isPELType(pel.second) && stateCheck(pel.second))
742b0a8df5bSMatt Spinler             {
743b0a8df5bSMatt Spinler                 auto removedID = pel.first.obmcID.id;
744027bf285SSumit Kumar 
745027bf285SSumit Kumar                 auto idFound = std::find(idsWithHwIsoEntry.begin(),
746027bf285SSumit Kumar                                          idsWithHwIsoEntry.end(), removedID);
747027bf285SSumit Kumar                 if (idFound != idsWithHwIsoEntry.end())
748027bf285SSumit Kumar                 {
749027bf285SSumit Kumar                     ++it;
750027bf285SSumit Kumar                     continue;
751027bf285SSumit Kumar                 }
752027bf285SSumit Kumar 
753b0a8df5bSMatt Spinler                 remove(pel.first);
754b0a8df5bSMatt Spinler 
755b0a8df5bSMatt Spinler                 removedBMCLogIDs.push_back(removedID);
756b0a8df5bSMatt Spinler 
757b0a8df5bSMatt Spinler                 attributes.erase(it);
758b0a8df5bSMatt Spinler 
759b0a8df5bSMatt Spinler                 if (!isOverLimit())
760b0a8df5bSMatt Spinler                 {
761b0a8df5bSMatt Spinler                     break;
762b0a8df5bSMatt Spinler                 }
763b0a8df5bSMatt Spinler             }
764b0a8df5bSMatt Spinler             else
765b0a8df5bSMatt Spinler             {
766b0a8df5bSMatt Spinler                 ++it;
767b0a8df5bSMatt Spinler             }
768b0a8df5bSMatt Spinler         }
769b0a8df5bSMatt Spinler 
770b0a8df5bSMatt Spinler         if (!isOverLimit())
771b0a8df5bSMatt Spinler         {
772b0a8df5bSMatt Spinler             break;
773b0a8df5bSMatt Spinler         }
774b0a8df5bSMatt Spinler     }
775b0a8df5bSMatt Spinler }
776b0a8df5bSMatt Spinler 
7772ccdcef9SSumit Kumar void Repository::archivePEL(const PEL& pel)
7782ccdcef9SSumit Kumar {
7792ccdcef9SSumit Kumar     if (pel.valid())
7802ccdcef9SSumit Kumar     {
7812ccdcef9SSumit Kumar         auto path = _archivePath / getPELFilename(pel.id(), pel.commitTime());
7822ccdcef9SSumit Kumar 
7832ccdcef9SSumit Kumar         write(pel, path);
7842ccdcef9SSumit Kumar 
7852ccdcef9SSumit Kumar         _archiveSize += getFileDiskSize(path);
7862ccdcef9SSumit Kumar     }
7872ccdcef9SSumit Kumar }
7882ccdcef9SSumit Kumar 
78989fa082aSMatt Spinler } // namespace pels
79089fa082aSMatt Spinler } // namespace openpower
791