xref: /openbmc/phosphor-logging/extensions/openpower-pels/repository.cpp (revision d0ccda3c2a36625d30a6c3b70ed0216694102fed)
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 
2189fa082aSMatt Spinler #include <phosphor-logging/log.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 using namespace phosphor::logging;
3389fa082aSMatt Spinler namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
3489fa082aSMatt Spinler 
357e727a39SMatt Spinler constexpr size_t warningPercentage = 95;
367e727a39SMatt Spinler 
37dd325c32SMatt Spinler /**
38dd325c32SMatt Spinler  * @brief Returns the amount of space the file uses on disk.
39dd325c32SMatt Spinler  *
40dd325c32SMatt Spinler  * This is different than just the regular size of the file.
41dd325c32SMatt Spinler  *
42dd325c32SMatt Spinler  * @param[in] file - The file to get the size of
43dd325c32SMatt Spinler  *
44dd325c32SMatt Spinler  * @return size_t The disk space the file uses
45dd325c32SMatt Spinler  */
46dd325c32SMatt Spinler size_t getFileDiskSize(const std::filesystem::path& file)
47dd325c32SMatt Spinler {
48dd325c32SMatt Spinler     constexpr size_t statBlockSize = 512;
49dd325c32SMatt Spinler     struct stat statData;
50dd325c32SMatt Spinler     auto rc = stat(file.c_str(), &statData);
51dd325c32SMatt Spinler     if (rc != 0)
52dd325c32SMatt Spinler     {
53dd325c32SMatt Spinler         auto e = errno;
54dd325c32SMatt Spinler         std::string msg = "call to stat() failed on " + file.native() +
55dd325c32SMatt Spinler                           " with errno " + std::to_string(e);
56dd325c32SMatt Spinler         log<level::ERR>(msg.c_str());
57dd325c32SMatt Spinler         abort();
58dd325c32SMatt Spinler     }
59dd325c32SMatt Spinler 
60dd325c32SMatt Spinler     return statData.st_blocks * statBlockSize;
61dd325c32SMatt Spinler }
62dd325c32SMatt Spinler 
638d5f3a2bSMatt Spinler Repository::Repository(const std::filesystem::path& basePath, size_t repoSize,
648d5f3a2bSMatt Spinler                        size_t maxNumPELs) :
658d5f3a2bSMatt Spinler     _logPath(basePath / "logs"),
661d8835bbSSumit Kumar     _maxRepoSize(repoSize), _maxNumPELs(maxNumPELs),
671d8835bbSSumit Kumar     _archivePath(basePath / "logs" / "archive")
6889fa082aSMatt Spinler {
6989fa082aSMatt Spinler     if (!fs::exists(_logPath))
7089fa082aSMatt Spinler     {
7189fa082aSMatt Spinler         fs::create_directories(_logPath);
7289fa082aSMatt Spinler     }
73475e574dSMatt Spinler 
741d8835bbSSumit Kumar     if (!fs::exists(_archivePath))
751d8835bbSSumit Kumar     {
761d8835bbSSumit Kumar         fs::create_directories(_archivePath);
771d8835bbSSumit Kumar     }
781d8835bbSSumit Kumar 
79475e574dSMatt Spinler     restore();
80475e574dSMatt Spinler }
81475e574dSMatt Spinler 
82475e574dSMatt Spinler void Repository::restore()
83475e574dSMatt Spinler {
84475e574dSMatt Spinler     for (auto& dirEntry : fs::directory_iterator(_logPath))
85475e574dSMatt Spinler     {
86475e574dSMatt Spinler         try
87475e574dSMatt Spinler         {
88475e574dSMatt Spinler             if (!fs::is_regular_file(dirEntry.path()))
89475e574dSMatt Spinler             {
90475e574dSMatt Spinler                 continue;
91475e574dSMatt Spinler             }
92475e574dSMatt Spinler 
93475e574dSMatt Spinler             std::ifstream file{dirEntry.path()};
94475e574dSMatt Spinler             std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
95475e574dSMatt Spinler                                       std::istreambuf_iterator<char>()};
96475e574dSMatt Spinler             file.close();
97475e574dSMatt Spinler 
9807eefc54SMatt Spinler             PEL pel{data};
99475e574dSMatt Spinler             if (pel.valid())
100475e574dSMatt Spinler             {
101a3c12a48SMatt Spinler                 // If the host hasn't acked it, reset the host state so
102a3c12a48SMatt Spinler                 // it will get sent up again.
103a3c12a48SMatt Spinler                 if (pel.hostTransmissionState() == TransmissionState::sent)
104a3c12a48SMatt Spinler                 {
105a3c12a48SMatt Spinler                     pel.setHostTransmissionState(TransmissionState::newPEL);
106a3c12a48SMatt Spinler                     try
107a3c12a48SMatt Spinler                     {
108a3c12a48SMatt Spinler                         write(pel, dirEntry.path());
109a3c12a48SMatt Spinler                     }
11066491c61SPatrick Williams                     catch (const std::exception& e)
111a3c12a48SMatt Spinler                     {
112a3c12a48SMatt Spinler                         log<level::ERR>(
113a3c12a48SMatt Spinler                             "Failed to save PEL after updating host state",
114a3c12a48SMatt Spinler                             entry("PELID=0x%X", pel.id()));
115a3c12a48SMatt Spinler                     }
116a3c12a48SMatt Spinler                 }
117a3c12a48SMatt Spinler 
1188e65f4eaSMatt Spinler                 PELAttributes attributes{
1198e65f4eaSMatt Spinler                     dirEntry.path(),
120dd325c32SMatt Spinler                     getFileDiskSize(dirEntry.path()),
121dd325c32SMatt Spinler                     pel.privateHeader().creatorID(),
122afb1b46fSVijay Lobo                     pel.userHeader().subsystem(),
123dd325c32SMatt Spinler                     pel.userHeader().severity(),
124dd325c32SMatt Spinler                     pel.userHeader().actionFlags(),
125dd325c32SMatt Spinler                     pel.hostTransmissionState(),
1268e65f4eaSMatt Spinler                     pel.hmcTransmissionState(),
1278e65f4eaSMatt Spinler                     pel.plid(),
1288e65f4eaSMatt Spinler                     pel.getDeconfigFlag(),
1298e65f4eaSMatt Spinler                     pel.getGuardFlag(),
1308e65f4eaSMatt Spinler                     getMillisecondsSinceEpoch(
1318e65f4eaSMatt Spinler                         pel.privateHeader().createTimestamp())};
1320ff00485SMatt Spinler 
133475e574dSMatt Spinler                 using pelID = LogID::Pel;
134475e574dSMatt Spinler                 using obmcID = LogID::Obmc;
1350ff00485SMatt Spinler                 _pelAttributes.emplace(
136475e574dSMatt Spinler                     LogID(pelID(pel.id()), obmcID(pel.obmcLogID())),
1370ff00485SMatt Spinler                     attributes);
138b188f78aSMatt Spinler 
139b188f78aSMatt Spinler                 updateRepoStats(attributes, true);
140475e574dSMatt Spinler             }
141475e574dSMatt Spinler             else
142475e574dSMatt Spinler             {
143475e574dSMatt Spinler                 log<level::ERR>(
144475e574dSMatt Spinler                     "Found invalid PEL file while restoring.  Removing.",
145475e574dSMatt Spinler                     entry("FILENAME=%s", dirEntry.path().c_str()));
146475e574dSMatt Spinler                 fs::remove(dirEntry.path());
147475e574dSMatt Spinler             }
148475e574dSMatt Spinler         }
14966491c61SPatrick Williams         catch (const std::exception& e)
150475e574dSMatt Spinler         {
151475e574dSMatt Spinler             log<level::ERR>("Hit exception while restoring PEL File",
152475e574dSMatt Spinler                             entry("FILENAME=%s", dirEntry.path().c_str()),
153475e574dSMatt Spinler                             entry("ERROR=%s", e.what()));
154475e574dSMatt Spinler         }
155475e574dSMatt Spinler     }
1561d8835bbSSumit Kumar 
1571d8835bbSSumit Kumar     // Get size of archive folder
1581d8835bbSSumit Kumar     for (auto& dirEntry : fs::directory_iterator(_archivePath))
1591d8835bbSSumit Kumar     {
1601d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(dirEntry);
1611d8835bbSSumit Kumar     }
16289fa082aSMatt Spinler }
16389fa082aSMatt Spinler 
16489fa082aSMatt Spinler std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
16589fa082aSMatt Spinler {
16689fa082aSMatt Spinler     char name[50];
16789fa082aSMatt Spinler     sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", time.yearMSB,
16889fa082aSMatt Spinler             time.yearLSB, time.month, time.day, time.hour, time.minutes,
16989fa082aSMatt Spinler             time.seconds, time.hundredths, pelID);
17089fa082aSMatt Spinler     return std::string{name};
17189fa082aSMatt Spinler }
17289fa082aSMatt Spinler 
17389fa082aSMatt Spinler void Repository::add(std::unique_ptr<PEL>& pel)
17489fa082aSMatt Spinler {
175df43a305SMatt Spinler     pel->setHostTransmissionState(TransmissionState::newPEL);
176df43a305SMatt Spinler     pel->setHMCTransmissionState(TransmissionState::newPEL);
177df43a305SMatt Spinler 
17889fa082aSMatt Spinler     auto path = _logPath / getPELFilename(pel->id(), pel->commitTime());
179ab1b97feSMatt Spinler 
180ab1b97feSMatt Spinler     write(*(pel.get()), path);
181ab1b97feSMatt Spinler 
1828e65f4eaSMatt Spinler     PELAttributes attributes{
1838e65f4eaSMatt Spinler         path,
184dd325c32SMatt Spinler         getFileDiskSize(path),
185dd325c32SMatt Spinler         pel->privateHeader().creatorID(),
186afb1b46fSVijay Lobo         pel->userHeader().subsystem(),
187dd325c32SMatt Spinler         pel->userHeader().severity(),
188dd325c32SMatt Spinler         pel->userHeader().actionFlags(),
189346f99a1SMatt Spinler         pel->hostTransmissionState(),
1908e65f4eaSMatt Spinler         pel->hmcTransmissionState(),
1918e65f4eaSMatt Spinler         pel->plid(),
1928e65f4eaSMatt Spinler         pel->getDeconfigFlag(),
1938e65f4eaSMatt Spinler         pel->getGuardFlag(),
1948e65f4eaSMatt Spinler         getMillisecondsSinceEpoch(pel->privateHeader().createTimestamp())};
195ab1b97feSMatt Spinler 
196ab1b97feSMatt Spinler     using pelID = LogID::Pel;
197ab1b97feSMatt Spinler     using obmcID = LogID::Obmc;
198ab1b97feSMatt Spinler     _pelAttributes.emplace(LogID(pelID(pel->id()), obmcID(pel->obmcLogID())),
199ab1b97feSMatt Spinler                            attributes);
200ab1b97feSMatt Spinler 
20144893cc9SMatt Spinler     _lastPelID = pel->id();
20244893cc9SMatt Spinler 
203b188f78aSMatt Spinler     updateRepoStats(attributes, true);
204b188f78aSMatt Spinler 
205ab1b97feSMatt Spinler     processAddCallbacks(*pel);
206ab1b97feSMatt Spinler }
207ab1b97feSMatt Spinler 
208ab1b97feSMatt Spinler void Repository::write(const PEL& pel, const fs::path& path)
209ab1b97feSMatt Spinler {
21089fa082aSMatt Spinler     std::ofstream file{path, std::ios::binary};
21189fa082aSMatt Spinler 
21289fa082aSMatt Spinler     if (!file.good())
21389fa082aSMatt Spinler     {
21489fa082aSMatt Spinler         // If this fails, the filesystem is probably full so it isn't like
21589fa082aSMatt Spinler         // we could successfully create yet another error log here.
21689fa082aSMatt Spinler         auto e = errno;
21789fa082aSMatt Spinler         fs::remove(path);
21889fa082aSMatt Spinler         log<level::ERR>("Unable to open PEL file for writing",
21989fa082aSMatt Spinler                         entry("ERRNO=%d", e), entry("PATH=%s", path.c_str()));
22089fa082aSMatt Spinler         throw file_error::Open();
22189fa082aSMatt Spinler     }
22289fa082aSMatt Spinler 
223ab1b97feSMatt Spinler     auto data = pel.data();
22489fa082aSMatt Spinler     file.write(reinterpret_cast<const char*>(data.data()), data.size());
22589fa082aSMatt Spinler 
22689fa082aSMatt Spinler     if (file.fail())
22789fa082aSMatt Spinler     {
22889fa082aSMatt Spinler         // Same note as above about not being able to create an error log
22989fa082aSMatt Spinler         // for this case even if we wanted.
23089fa082aSMatt Spinler         auto e = errno;
23189fa082aSMatt Spinler         file.close();
23289fa082aSMatt Spinler         fs::remove(path);
23389fa082aSMatt Spinler         log<level::ERR>("Unable to write PEL file", entry("ERRNO=%d", e),
23489fa082aSMatt Spinler                         entry("PATH=%s", path.c_str()));
23589fa082aSMatt Spinler         throw file_error::Write();
23689fa082aSMatt Spinler     }
237475e574dSMatt Spinler }
238475e574dSMatt Spinler 
23952602e35SMatt Spinler std::optional<Repository::LogID> Repository::remove(const LogID& id)
240475e574dSMatt Spinler {
241475e574dSMatt Spinler     auto pel = findPEL(id);
242ff6b598bSPatrick Williams     if (pel == _pelAttributes.end())
243475e574dSMatt Spinler     {
244ff6b598bSPatrick Williams         return std::nullopt;
245ff6b598bSPatrick Williams     }
246ff6b598bSPatrick Williams 
247ff6b598bSPatrick Williams     LogID actualID = pel->first;
248b188f78aSMatt Spinler     updateRepoStats(pel->second, false);
249b188f78aSMatt Spinler 
2505f5352e5SMatt Spinler     log<level::DEBUG>("Removing PEL from repository",
251ff6b598bSPatrick Williams                       entry("PEL_ID=0x%X", actualID.pelID.id),
252ff6b598bSPatrick Williams                       entry("OBMC_LOG_ID=%d", actualID.obmcID.id));
2531d8835bbSSumit Kumar 
2541d8835bbSSumit Kumar     if (fs::exists(pel->second.path))
2551d8835bbSSumit Kumar     {
2561d8835bbSSumit Kumar         // Check for existense of new archive folder
2571d8835bbSSumit Kumar         if (!fs::exists(_archivePath))
2581d8835bbSSumit Kumar         {
2591d8835bbSSumit Kumar             fs::create_directories(_archivePath);
2601d8835bbSSumit Kumar         }
2611d8835bbSSumit Kumar 
2621d8835bbSSumit Kumar         // Move log file to archive folder
2631d8835bbSSumit Kumar         auto fileName = _archivePath / pel->second.path.filename();
2641d8835bbSSumit Kumar         fs::rename(pel->second.path, fileName);
2651d8835bbSSumit Kumar 
2661d8835bbSSumit Kumar         // Update size of file
2671d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(fileName);
2681d8835bbSSumit Kumar     }
2691d8835bbSSumit Kumar 
2700ff00485SMatt Spinler     _pelAttributes.erase(pel);
271421f6531SMatt Spinler 
272ff6b598bSPatrick Williams     processDeleteCallbacks(actualID.pelID.id);
27352602e35SMatt Spinler 
27452602e35SMatt Spinler     return actualID;
27589fa082aSMatt Spinler }
27689fa082aSMatt Spinler 
2772813f36dSMatt Spinler std::optional<std::vector<uint8_t>> Repository::getPELData(const LogID& id)
2782813f36dSMatt Spinler {
2792813f36dSMatt Spinler     auto pel = findPEL(id);
2800ff00485SMatt Spinler     if (pel != _pelAttributes.end())
2812813f36dSMatt Spinler     {
2820ff00485SMatt Spinler         std::ifstream file{pel->second.path.c_str()};
2832813f36dSMatt Spinler         if (!file.good())
2842813f36dSMatt Spinler         {
2852813f36dSMatt Spinler             auto e = errno;
2862813f36dSMatt Spinler             log<level::ERR>("Unable to open PEL file", entry("ERRNO=%d", e),
2870ff00485SMatt Spinler                             entry("PATH=%s", pel->second.path.c_str()));
2882813f36dSMatt Spinler             throw file_error::Open();
2892813f36dSMatt Spinler         }
2902813f36dSMatt Spinler 
2912813f36dSMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
2922813f36dSMatt Spinler                                   std::istreambuf_iterator<char>()};
2932813f36dSMatt Spinler         return data;
2942813f36dSMatt Spinler     }
2952813f36dSMatt Spinler 
2962813f36dSMatt Spinler     return std::nullopt;
2972813f36dSMatt Spinler }
2982813f36dSMatt Spinler 
2996d51224bSMatt Spinler std::optional<sdbusplus::message::unix_fd> Repository::getPELFD(const LogID& id)
3006d51224bSMatt Spinler {
3016d51224bSMatt Spinler     auto pel = findPEL(id);
3026d51224bSMatt Spinler     if (pel != _pelAttributes.end())
3036d51224bSMatt Spinler     {
30432a6df6cSMatt Spinler         int fd = open(pel->second.path.c_str(), O_RDONLY | O_NONBLOCK);
30532a6df6cSMatt Spinler         if (fd == -1)
3066d51224bSMatt Spinler         {
3076d51224bSMatt Spinler             auto e = errno;
3086d51224bSMatt Spinler             log<level::ERR>("Unable to open PEL File", entry("ERRNO=%d", e),
3096d51224bSMatt Spinler                             entry("PATH=%s", pel->second.path.c_str()));
3106d51224bSMatt Spinler             throw file_error::Open();
3116d51224bSMatt Spinler         }
3126d51224bSMatt Spinler 
3136d51224bSMatt Spinler         // Must leave the file open here.  It will be closed by sdbusplus
3146d51224bSMatt Spinler         // when it sends it back over D-Bus.
31532a6df6cSMatt Spinler         return fd;
3166d51224bSMatt Spinler     }
3176d51224bSMatt Spinler     return std::nullopt;
3186d51224bSMatt Spinler }
3196d51224bSMatt Spinler 
3201ea78801SMatt Spinler void Repository::for_each(ForEachFunc func) const
3211ea78801SMatt Spinler {
3220ff00485SMatt Spinler     for (const auto& [id, attributes] : _pelAttributes)
3231ea78801SMatt Spinler     {
3240ff00485SMatt Spinler         std::ifstream file{attributes.path};
3251ea78801SMatt Spinler 
3261ea78801SMatt Spinler         if (!file.good())
3271ea78801SMatt Spinler         {
3281ea78801SMatt Spinler             auto e = errno;
3291ea78801SMatt Spinler             log<level::ERR>("Repository::for_each: Unable to open PEL file",
3301ea78801SMatt Spinler                             entry("ERRNO=%d", e),
3310ff00485SMatt Spinler                             entry("PATH=%s", attributes.path.c_str()));
3321ea78801SMatt Spinler             continue;
3331ea78801SMatt Spinler         }
3341ea78801SMatt Spinler 
3351ea78801SMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
3361ea78801SMatt Spinler                                   std::istreambuf_iterator<char>()};
3371ea78801SMatt Spinler         file.close();
3381ea78801SMatt Spinler 
3391ea78801SMatt Spinler         PEL pel{data};
3401ea78801SMatt Spinler 
3411ea78801SMatt Spinler         try
3421ea78801SMatt Spinler         {
3431ea78801SMatt Spinler             if (func(pel))
3441ea78801SMatt Spinler             {
3451ea78801SMatt Spinler                 break;
3461ea78801SMatt Spinler             }
3471ea78801SMatt Spinler         }
34866491c61SPatrick Williams         catch (const std::exception& e)
3491ea78801SMatt Spinler         {
3501ea78801SMatt Spinler             log<level::ERR>("Repository::for_each function exception",
3511ea78801SMatt Spinler                             entry("ERROR=%s", e.what()));
3521ea78801SMatt Spinler         }
3531ea78801SMatt Spinler     }
3541ea78801SMatt Spinler }
3551ea78801SMatt Spinler 
356421f6531SMatt Spinler void Repository::processAddCallbacks(const PEL& pel) const
357421f6531SMatt Spinler {
358421f6531SMatt Spinler     for (auto& [name, func] : _addSubscriptions)
359421f6531SMatt Spinler     {
360421f6531SMatt Spinler         try
361421f6531SMatt Spinler         {
362421f6531SMatt Spinler             func(pel);
363421f6531SMatt Spinler         }
36466491c61SPatrick Williams         catch (const std::exception& e)
365421f6531SMatt Spinler         {
366421f6531SMatt Spinler             log<level::ERR>("PEL Repository add callback exception",
367421f6531SMatt Spinler                             entry("NAME=%s", name.c_str()),
368421f6531SMatt Spinler                             entry("ERROR=%s", e.what()));
369421f6531SMatt Spinler         }
370421f6531SMatt Spinler     }
371421f6531SMatt Spinler }
372421f6531SMatt Spinler 
373421f6531SMatt Spinler void Repository::processDeleteCallbacks(uint32_t id) const
374421f6531SMatt Spinler {
375421f6531SMatt Spinler     for (auto& [name, func] : _deleteSubscriptions)
376421f6531SMatt Spinler     {
377421f6531SMatt Spinler         try
378421f6531SMatt Spinler         {
379421f6531SMatt Spinler             func(id);
380421f6531SMatt Spinler         }
38166491c61SPatrick Williams         catch (const std::exception& e)
382421f6531SMatt Spinler         {
383421f6531SMatt Spinler             log<level::ERR>("PEL Repository delete callback exception",
384421f6531SMatt Spinler                             entry("NAME=%s", name.c_str()),
385421f6531SMatt Spinler                             entry("ERROR=%s", e.what()));
386421f6531SMatt Spinler         }
387421f6531SMatt Spinler     }
388421f6531SMatt Spinler }
389421f6531SMatt Spinler 
3900ff00485SMatt Spinler std::optional<std::reference_wrapper<const Repository::PELAttributes>>
3910ff00485SMatt Spinler     Repository::getPELAttributes(const LogID& id) const
3920ff00485SMatt Spinler {
3930ff00485SMatt Spinler     auto pel = findPEL(id);
3940ff00485SMatt Spinler     if (pel != _pelAttributes.end())
3950ff00485SMatt Spinler     {
3960ff00485SMatt Spinler         return pel->second;
3970ff00485SMatt Spinler     }
3980ff00485SMatt Spinler 
3990ff00485SMatt Spinler     return std::nullopt;
4000ff00485SMatt Spinler }
4010ff00485SMatt Spinler 
40229d18c11SMatt Spinler void Repository::setPELHostTransState(uint32_t pelID, TransmissionState state)
40329d18c11SMatt Spinler {
40429d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
40529d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
40629d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
40729d18c11SMatt Spinler 
40829d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hostState != state))
40929d18c11SMatt Spinler     {
41029d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
41129d18c11SMatt Spinler             pel.setHostTransmissionState(state);
412*d0ccda3cSMatt Spinler             return true;
41329d18c11SMatt Spinler         };
41429d18c11SMatt Spinler 
41529d18c11SMatt Spinler         try
41629d18c11SMatt Spinler         {
41729d18c11SMatt Spinler             updatePEL(attr->second.path, func);
41829d18c11SMatt Spinler         }
41966491c61SPatrick Williams         catch (const std::exception& e)
42029d18c11SMatt Spinler         {
42129d18c11SMatt Spinler             log<level::ERR>("Unable to update PEL host transmission state",
42229d18c11SMatt Spinler                             entry("PATH=%s", attr->second.path.c_str()),
42329d18c11SMatt Spinler                             entry("ERROR=%s", e.what()));
42429d18c11SMatt Spinler         }
42529d18c11SMatt Spinler     }
42629d18c11SMatt Spinler }
42729d18c11SMatt Spinler 
42829d18c11SMatt Spinler void Repository::setPELHMCTransState(uint32_t pelID, TransmissionState state)
42929d18c11SMatt Spinler {
43029d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
43129d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
43229d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
43329d18c11SMatt Spinler 
43429d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hmcState != state))
43529d18c11SMatt Spinler     {
43629d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
43729d18c11SMatt Spinler             pel.setHMCTransmissionState(state);
438*d0ccda3cSMatt Spinler             return true;
43929d18c11SMatt Spinler         };
44029d18c11SMatt Spinler 
44129d18c11SMatt Spinler         try
44229d18c11SMatt Spinler         {
44329d18c11SMatt Spinler             updatePEL(attr->second.path, func);
44429d18c11SMatt Spinler         }
44566491c61SPatrick Williams         catch (const std::exception& e)
44629d18c11SMatt Spinler         {
44729d18c11SMatt Spinler             log<level::ERR>("Unable to update PEL HMC transmission state",
44829d18c11SMatt Spinler                             entry("PATH=%s", attr->second.path.c_str()),
44929d18c11SMatt Spinler                             entry("ERROR=%s", e.what()));
45029d18c11SMatt Spinler         }
45129d18c11SMatt Spinler     }
45229d18c11SMatt Spinler }
45329d18c11SMatt Spinler 
45429d18c11SMatt Spinler void Repository::updatePEL(const fs::path& path, PELUpdateFunc updateFunc)
45529d18c11SMatt Spinler {
45629d18c11SMatt Spinler     std::ifstream file{path};
45729d18c11SMatt Spinler     std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
45829d18c11SMatt Spinler                               std::istreambuf_iterator<char>()};
45929d18c11SMatt Spinler     file.close();
46029d18c11SMatt Spinler 
46129d18c11SMatt Spinler     PEL pel{data};
46229d18c11SMatt Spinler 
46329d18c11SMatt Spinler     if (pel.valid())
46429d18c11SMatt Spinler     {
465*d0ccda3cSMatt Spinler         if (updateFunc(pel))
466*d0ccda3cSMatt Spinler         {
467*d0ccda3cSMatt Spinler             // Three attribute fields can change post creation from
468*d0ccda3cSMatt Spinler             // an updatePEL call:
469*d0ccda3cSMatt Spinler             //  - hmcTransmissionState - When HMC acks a PEL
470*d0ccda3cSMatt Spinler             //  - hostTransmissionState - When host acks a PEL
471*d0ccda3cSMatt Spinler             //  - deconfig flag - Can be cleared for PELs that call out
472*d0ccda3cSMatt Spinler             //                    hotplugged FRUs.
473*d0ccda3cSMatt Spinler             // Make sure they're up to date.
474*d0ccda3cSMatt Spinler             LogID id{LogID::Pel(pel.id())};
475*d0ccda3cSMatt Spinler             auto attr =
476*d0ccda3cSMatt Spinler                 std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
477*d0ccda3cSMatt Spinler                              [&id](const auto& a) { return a.first == id; });
478*d0ccda3cSMatt Spinler             if (attr != _pelAttributes.end())
479*d0ccda3cSMatt Spinler             {
480*d0ccda3cSMatt Spinler                 attr->second.hmcState = pel.hmcTransmissionState();
481*d0ccda3cSMatt Spinler                 attr->second.hostState = pel.hostTransmissionState();
482*d0ccda3cSMatt Spinler                 attr->second.deconfig = pel.getDeconfigFlag();
483*d0ccda3cSMatt Spinler             }
48429d18c11SMatt Spinler 
48529d18c11SMatt Spinler             write(pel, path);
48629d18c11SMatt Spinler         }
487*d0ccda3cSMatt Spinler     }
48829d18c11SMatt Spinler     else
48929d18c11SMatt Spinler     {
49029d18c11SMatt Spinler         throw std::runtime_error(
49129d18c11SMatt Spinler             "Unable to read a valid PEL when trying to update it");
49229d18c11SMatt Spinler     }
49329d18c11SMatt Spinler }
49429d18c11SMatt Spinler 
495b188f78aSMatt Spinler bool Repository::isServiceableSev(const PELAttributes& pel)
496b188f78aSMatt Spinler {
497b188f78aSMatt Spinler     auto sevType = static_cast<SeverityType>(pel.severity & 0xF0);
4982544b419SPatrick Williams     auto sevPVEntry = pel_values::findByValue(pel.severity,
4992544b419SPatrick Williams                                               pel_values::severityValues);
500b188f78aSMatt Spinler     std::string sevName = std::get<pel_values::registryNamePos>(*sevPVEntry);
501b188f78aSMatt Spinler 
502b188f78aSMatt Spinler     bool check1 = (sevType == SeverityType::predictive) ||
503b188f78aSMatt Spinler                   (sevType == SeverityType::unrecoverable) ||
504b188f78aSMatt Spinler                   (sevType == SeverityType::critical);
505b188f78aSMatt Spinler 
506b188f78aSMatt Spinler     bool check2 = ((sevType == SeverityType::recovered) ||
507b188f78aSMatt Spinler                    (sevName == "symptom_recovered")) &&
508b188f78aSMatt Spinler                   !pel.actionFlags.test(hiddenFlagBit);
509b188f78aSMatt Spinler 
510b188f78aSMatt Spinler     bool check3 = (sevName == "symptom_predictive") ||
511b188f78aSMatt Spinler                   (sevName == "symptom_unrecoverable") ||
512b188f78aSMatt Spinler                   (sevName == "symptom_critical");
513b188f78aSMatt Spinler 
514b188f78aSMatt Spinler     return check1 || check2 || check3;
515b188f78aSMatt Spinler }
516b188f78aSMatt Spinler 
517b188f78aSMatt Spinler void Repository::updateRepoStats(const PELAttributes& pel, bool pelAdded)
518b188f78aSMatt Spinler {
519b188f78aSMatt Spinler     auto isServiceable = Repository::isServiceableSev(pel);
520b188f78aSMatt Spinler     auto bmcPEL = CreatorID::openBMC == static_cast<CreatorID>(pel.creator);
521b188f78aSMatt Spinler 
522b188f78aSMatt Spinler     auto adjustSize = [pelAdded, &pel](auto& runningSize) {
523b188f78aSMatt Spinler         if (pelAdded)
524b188f78aSMatt Spinler         {
525b188f78aSMatt Spinler             runningSize += pel.sizeOnDisk;
526b188f78aSMatt Spinler         }
527b188f78aSMatt Spinler         else
528b188f78aSMatt Spinler         {
529b188f78aSMatt Spinler             runningSize = std::max(static_cast<int64_t>(runningSize) -
530b188f78aSMatt Spinler                                        static_cast<int64_t>(pel.sizeOnDisk),
531b188f78aSMatt Spinler                                    static_cast<int64_t>(0));
532b188f78aSMatt Spinler         }
533b188f78aSMatt Spinler     };
534b188f78aSMatt Spinler 
535b188f78aSMatt Spinler     adjustSize(_sizes.total);
536b188f78aSMatt Spinler 
537b188f78aSMatt Spinler     if (bmcPEL)
538b188f78aSMatt Spinler     {
539b188f78aSMatt Spinler         adjustSize(_sizes.bmc);
540b188f78aSMatt Spinler         if (isServiceable)
541b188f78aSMatt Spinler         {
542b188f78aSMatt Spinler             adjustSize(_sizes.bmcServiceable);
543b188f78aSMatt Spinler         }
544b188f78aSMatt Spinler         else
545b188f78aSMatt Spinler         {
546b188f78aSMatt Spinler             adjustSize(_sizes.bmcInfo);
547b188f78aSMatt Spinler         }
548b188f78aSMatt Spinler     }
549b188f78aSMatt Spinler     else
550b188f78aSMatt Spinler     {
551b188f78aSMatt Spinler         adjustSize(_sizes.nonBMC);
552b188f78aSMatt Spinler         if (isServiceable)
553b188f78aSMatt Spinler         {
554b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCServiceable);
555b188f78aSMatt Spinler         }
556b188f78aSMatt Spinler         else
557b188f78aSMatt Spinler         {
558b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCInfo);
559b188f78aSMatt Spinler         }
560b188f78aSMatt Spinler     }
561b188f78aSMatt Spinler }
562b188f78aSMatt Spinler 
563c296692bSSumit Kumar bool Repository::sizeWarning()
5647e727a39SMatt Spinler {
565c296692bSSumit Kumar     std::error_code ec;
566c296692bSSumit Kumar 
5671d8835bbSSumit Kumar     if ((_archiveSize > 0) && ((_sizes.total + _archiveSize) >
5681d8835bbSSumit Kumar                                ((_maxRepoSize * warningPercentage) / 100)))
5691d8835bbSSumit Kumar     {
5701d8835bbSSumit Kumar         log<level::INFO>(
5711d8835bbSSumit Kumar             "Repository::sizeWarning function:Deleting the files in archive");
5721d8835bbSSumit Kumar 
573c296692bSSumit Kumar         for (const auto& dirEntry : fs::directory_iterator(_archivePath))
5741d8835bbSSumit Kumar         {
575c296692bSSumit Kumar             fs::remove(dirEntry.path(), ec);
576c296692bSSumit Kumar             if (ec)
577c296692bSSumit Kumar             {
578c296692bSSumit Kumar                 log<level::INFO>(
579c296692bSSumit Kumar                     "Repository::sizeWarning function:Could not delete "
580c296692bSSumit Kumar                     "a file in PEL archive",
581c296692bSSumit Kumar                     entry("FILENAME=%s", dirEntry.path().c_str()));
5821d8835bbSSumit Kumar             }
5831d8835bbSSumit Kumar         }
5841d8835bbSSumit Kumar 
585c296692bSSumit Kumar         _archiveSize = 0;
586c296692bSSumit Kumar     }
587c296692bSSumit Kumar 
5887e727a39SMatt Spinler     return (_sizes.total > (_maxRepoSize * warningPercentage / 100)) ||
5897e727a39SMatt Spinler            (_pelAttributes.size() > _maxNumPELs);
5907e727a39SMatt Spinler }
5917e727a39SMatt Spinler 
592b0a8df5bSMatt Spinler std::vector<Repository::AttributesReference>
593b0a8df5bSMatt Spinler     Repository::getAllPELAttributes(SortOrder order) const
594b0a8df5bSMatt Spinler {
595b0a8df5bSMatt Spinler     std::vector<Repository::AttributesReference> attributes;
596b0a8df5bSMatt Spinler 
597ac1ba3f2SPatrick Williams     std::for_each(_pelAttributes.begin(), _pelAttributes.end(),
598ac1ba3f2SPatrick Williams                   [&attributes](auto& pelEntry) {
599ac1ba3f2SPatrick Williams         attributes.push_back(pelEntry);
600ac1ba3f2SPatrick Williams     });
601b0a8df5bSMatt Spinler 
602b0a8df5bSMatt Spinler     std::sort(attributes.begin(), attributes.end(),
603b0a8df5bSMatt Spinler               [order](const auto& left, const auto& right) {
604b0a8df5bSMatt Spinler         if (order == SortOrder::ascending)
605b0a8df5bSMatt Spinler         {
606b0a8df5bSMatt Spinler             return left.get().second.path < right.get().second.path;
607b0a8df5bSMatt Spinler         }
608b0a8df5bSMatt Spinler         return left.get().second.path > right.get().second.path;
609b0a8df5bSMatt Spinler     });
610b0a8df5bSMatt Spinler 
611b0a8df5bSMatt Spinler     return attributes;
612b0a8df5bSMatt Spinler }
613b0a8df5bSMatt Spinler 
614027bf285SSumit Kumar std::vector<uint32_t>
615027bf285SSumit Kumar     Repository::prune(const std::vector<uint32_t>& idsWithHwIsoEntry)
616b0a8df5bSMatt Spinler {
617b0a8df5bSMatt Spinler     std::vector<uint32_t> obmcLogIDs;
618b0a8df5bSMatt Spinler     std::string msg = "Pruning PEL repository that takes up " +
619b0a8df5bSMatt Spinler                       std::to_string(_sizes.total) + " bytes and has " +
620b0a8df5bSMatt Spinler                       std::to_string(_pelAttributes.size()) + " PELs";
621b0a8df5bSMatt Spinler     log<level::INFO>(msg.c_str());
622b0a8df5bSMatt Spinler 
623b0a8df5bSMatt Spinler     // Set up the 5 functions to check if the PEL category
624b0a8df5bSMatt Spinler     // is still over its limits.
625b0a8df5bSMatt Spinler 
626b0a8df5bSMatt Spinler     // BMC informational PELs should only take up 15%
627b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCInfoLimit = [this]() {
628b0a8df5bSMatt Spinler         return _sizes.bmcInfo > _maxRepoSize * 15 / 100;
629b0a8df5bSMatt Spinler     };
630b0a8df5bSMatt Spinler 
631b0a8df5bSMatt Spinler     // BMC non informational PELs should only take up 30%
632b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCNonInfoLimit = [this]() {
633b0a8df5bSMatt Spinler         return _sizes.bmcServiceable > _maxRepoSize * 30 / 100;
634b0a8df5bSMatt Spinler     };
635b0a8df5bSMatt Spinler 
636b0a8df5bSMatt Spinler     // Non BMC informational PELs should only take up 15%
637b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCInfoLimit = [this]() {
638b0a8df5bSMatt Spinler         return _sizes.nonBMCInfo > _maxRepoSize * 15 / 100;
639b0a8df5bSMatt Spinler     };
640b0a8df5bSMatt Spinler 
641b0a8df5bSMatt Spinler     // Non BMC non informational PELs should only take up 15%
642b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCNonInfoLimit = [this]() {
643b0a8df5bSMatt Spinler         return _sizes.nonBMCServiceable > _maxRepoSize * 30 / 100;
644b0a8df5bSMatt Spinler     };
645b0a8df5bSMatt Spinler 
646b0a8df5bSMatt Spinler     // Bring the total number of PELs down to 80% of the max
647b0a8df5bSMatt Spinler     IsOverLimitFunc tooManyPELsLimit = [this]() {
648b0a8df5bSMatt Spinler         return _pelAttributes.size() > _maxNumPELs * 80 / 100;
649b0a8df5bSMatt Spinler     };
650b0a8df5bSMatt Spinler 
651b0a8df5bSMatt Spinler     // Set up the functions to determine which category a PEL is in.
652b0a8df5bSMatt Spinler     // TODO: Return false in these functions if a PEL caused a guard record.
653b0a8df5bSMatt Spinler 
654b0a8df5bSMatt Spinler     // A BMC informational PEL
655b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCInfo = [](const PELAttributes& pel) {
656b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
657b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
658b0a8df5bSMatt Spinler     };
659b0a8df5bSMatt Spinler 
660b0a8df5bSMatt Spinler     // A BMC non informational PEL
661b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCNonInfo = [](const PELAttributes& pel) {
662b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
663b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
664b0a8df5bSMatt Spinler     };
665b0a8df5bSMatt Spinler 
666b0a8df5bSMatt Spinler     // A non BMC informational PEL
667b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCInfo = [](const PELAttributes& pel) {
668b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
669b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
670b0a8df5bSMatt Spinler     };
671b0a8df5bSMatt Spinler 
672b0a8df5bSMatt Spinler     // A non BMC non informational PEL
673b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCNonInfo = [](const PELAttributes& pel) {
674b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
675b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
676b0a8df5bSMatt Spinler     };
677b0a8df5bSMatt Spinler 
678b0a8df5bSMatt Spinler     // When counting PELs, count every PEL
679d26fa3e7SPatrick Williams     IsPELTypeFunc isAnyPEL = [](const PELAttributes& /*pel*/) { return true; };
680b0a8df5bSMatt Spinler 
681b0a8df5bSMatt Spinler     // Check all 4 categories, which will result in at most 90%
682b0a8df5bSMatt Spinler     // usage (15 + 30 + 15 + 30).
683027bf285SSumit Kumar     removePELs(overBMCInfoLimit, isBMCInfo, idsWithHwIsoEntry, obmcLogIDs);
684027bf285SSumit Kumar     removePELs(overBMCNonInfoLimit, isBMCNonInfo, idsWithHwIsoEntry,
685027bf285SSumit Kumar                obmcLogIDs);
686027bf285SSumit Kumar     removePELs(overNonBMCInfoLimit, isNonBMCInfo, idsWithHwIsoEntry,
687027bf285SSumit Kumar                obmcLogIDs);
688027bf285SSumit Kumar     removePELs(overNonBMCNonInfoLimit, isNonBMCNonInfo, idsWithHwIsoEntry,
689027bf285SSumit Kumar                obmcLogIDs);
690b0a8df5bSMatt Spinler 
691b0a8df5bSMatt Spinler     // After the above pruning check if there are still too many PELs,
692b0a8df5bSMatt Spinler     // which can happen depending on PEL sizes.
693b0a8df5bSMatt Spinler     if (_pelAttributes.size() > _maxNumPELs)
694b0a8df5bSMatt Spinler     {
695027bf285SSumit Kumar         removePELs(tooManyPELsLimit, isAnyPEL, idsWithHwIsoEntry, obmcLogIDs);
696b0a8df5bSMatt Spinler     }
697b0a8df5bSMatt Spinler 
698b0a8df5bSMatt Spinler     if (!obmcLogIDs.empty())
699b0a8df5bSMatt Spinler     {
70045796e82SMatt Spinler         std::string m = "Number of PELs removed to save space: " +
701b0a8df5bSMatt Spinler                         std::to_string(obmcLogIDs.size());
70245796e82SMatt Spinler         log<level::INFO>(m.c_str());
703b0a8df5bSMatt Spinler     }
704b0a8df5bSMatt Spinler 
705b0a8df5bSMatt Spinler     return obmcLogIDs;
706b0a8df5bSMatt Spinler }
707b0a8df5bSMatt Spinler 
70845796e82SMatt Spinler void Repository::removePELs(const IsOverLimitFunc& isOverLimit,
70945796e82SMatt Spinler                             const IsPELTypeFunc& isPELType,
710027bf285SSumit Kumar                             const std::vector<uint32_t>& idsWithHwIsoEntry,
711b0a8df5bSMatt Spinler                             std::vector<uint32_t>& removedBMCLogIDs)
712b0a8df5bSMatt Spinler {
713b0a8df5bSMatt Spinler     if (!isOverLimit())
714b0a8df5bSMatt Spinler     {
715b0a8df5bSMatt Spinler         return;
716b0a8df5bSMatt Spinler     }
717b0a8df5bSMatt Spinler 
718b0a8df5bSMatt Spinler     auto attributes = getAllPELAttributes(SortOrder::ascending);
719b0a8df5bSMatt Spinler 
720b0a8df5bSMatt Spinler     // Make 4 passes on the PELs, stopping as soon as isOverLimit
721b0a8df5bSMatt Spinler     // returns false.
722b0a8df5bSMatt Spinler     //   Pass 1: only delete HMC acked PELs
723b0a8df5bSMatt Spinler     //   Pass 2: only delete OS acked PELs
724b0a8df5bSMatt Spinler     //   Pass 3: only delete PHYP sent PELs
725b0a8df5bSMatt Spinler     //   Pass 4: delete all PELs
726b0a8df5bSMatt Spinler     static const std::vector<std::function<bool(const PELAttributes& pel)>>
727b0a8df5bSMatt Spinler         stateChecks{[](const auto& pel) {
728b0a8df5bSMatt Spinler         return pel.hmcState == TransmissionState::acked;
729b0a8df5bSMatt Spinler                     },
730b0a8df5bSMatt Spinler 
731b0a8df5bSMatt Spinler                     [](const auto& pel) {
732b0a8df5bSMatt Spinler         return pel.hostState == TransmissionState::acked;
733b0a8df5bSMatt Spinler         },
734b0a8df5bSMatt Spinler 
735b0a8df5bSMatt Spinler         [](const auto& pel) {
736b0a8df5bSMatt Spinler         return pel.hostState == TransmissionState::sent;
737b0a8df5bSMatt Spinler         },
738b0a8df5bSMatt Spinler 
739d26fa3e7SPatrick Williams         [](const auto& /*pel*/) { return true; }};
740b0a8df5bSMatt Spinler 
741b0a8df5bSMatt Spinler     for (const auto& stateCheck : stateChecks)
742b0a8df5bSMatt Spinler     {
743b0a8df5bSMatt Spinler         for (auto it = attributes.begin(); it != attributes.end();)
744b0a8df5bSMatt Spinler         {
745b0a8df5bSMatt Spinler             const auto& pel = it->get();
746b0a8df5bSMatt Spinler             if (isPELType(pel.second) && stateCheck(pel.second))
747b0a8df5bSMatt Spinler             {
748b0a8df5bSMatt Spinler                 auto removedID = pel.first.obmcID.id;
749027bf285SSumit Kumar 
750027bf285SSumit Kumar                 auto idFound = std::find(idsWithHwIsoEntry.begin(),
751027bf285SSumit Kumar                                          idsWithHwIsoEntry.end(), removedID);
752027bf285SSumit Kumar                 if (idFound != idsWithHwIsoEntry.end())
753027bf285SSumit Kumar                 {
754027bf285SSumit Kumar                     ++it;
755027bf285SSumit Kumar                     continue;
756027bf285SSumit Kumar                 }
757027bf285SSumit Kumar 
758b0a8df5bSMatt Spinler                 remove(pel.first);
759b0a8df5bSMatt Spinler 
760b0a8df5bSMatt Spinler                 removedBMCLogIDs.push_back(removedID);
761b0a8df5bSMatt Spinler 
762b0a8df5bSMatt Spinler                 attributes.erase(it);
763b0a8df5bSMatt Spinler 
764b0a8df5bSMatt Spinler                 if (!isOverLimit())
765b0a8df5bSMatt Spinler                 {
766b0a8df5bSMatt Spinler                     break;
767b0a8df5bSMatt Spinler                 }
768b0a8df5bSMatt Spinler             }
769b0a8df5bSMatt Spinler             else
770b0a8df5bSMatt Spinler             {
771b0a8df5bSMatt Spinler                 ++it;
772b0a8df5bSMatt Spinler             }
773b0a8df5bSMatt Spinler         }
774b0a8df5bSMatt Spinler 
775b0a8df5bSMatt Spinler         if (!isOverLimit())
776b0a8df5bSMatt Spinler         {
777b0a8df5bSMatt Spinler             break;
778b0a8df5bSMatt Spinler         }
779b0a8df5bSMatt Spinler     }
780b0a8df5bSMatt Spinler }
781b0a8df5bSMatt Spinler 
7822ccdcef9SSumit Kumar void Repository::archivePEL(const PEL& pel)
7832ccdcef9SSumit Kumar {
7842ccdcef9SSumit Kumar     if (pel.valid())
7852ccdcef9SSumit Kumar     {
7862ccdcef9SSumit Kumar         auto path = _archivePath / getPELFilename(pel.id(), pel.commitTime());
7872ccdcef9SSumit Kumar 
7882ccdcef9SSumit Kumar         write(pel, path);
7892ccdcef9SSumit Kumar 
7902ccdcef9SSumit Kumar         _archiveSize += getFileDiskSize(path);
7912ccdcef9SSumit Kumar     }
7922ccdcef9SSumit Kumar }
7932ccdcef9SSumit Kumar 
79489fa082aSMatt Spinler } // namespace pels
79589fa082aSMatt Spinler } // namespace openpower
796