xref: /openbmc/phosphor-logging/extensions/openpower-pels/repository.cpp (revision 075c79237505ea3b810a461f5f514e4d520a0c44)
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 
21db3f2798SMatt 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  */
getFileDiskSize(const std::filesystem::path & file)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;
53db3f2798SMatt Spinler         lg2::error("Call to stat() failed on {FILE} with errno {ERRNO}", "FILE",
54db3f2798SMatt Spinler                    file.native(), "ERRNO", e);
55dd325c32SMatt Spinler         abort();
56dd325c32SMatt Spinler     }
57dd325c32SMatt Spinler 
58dd325c32SMatt Spinler     return statData.st_blocks * statBlockSize;
59dd325c32SMatt Spinler }
60dd325c32SMatt Spinler 
Repository(const std::filesystem::path & basePath,size_t repoSize,size_t maxNumPELs)618d5f3a2bSMatt Spinler Repository::Repository(const std::filesystem::path& basePath, size_t repoSize,
628d5f3a2bSMatt Spinler                        size_t maxNumPELs) :
63*075c7923SPatrick Williams     _logPath(basePath / "logs"), _maxRepoSize(repoSize),
64*075c7923SPatrick Williams     _maxNumPELs(maxNumPELs), _archivePath(basePath / "logs" / "archive")
6589fa082aSMatt Spinler {
6689fa082aSMatt Spinler     if (!fs::exists(_logPath))
6789fa082aSMatt Spinler     {
6889fa082aSMatt Spinler         fs::create_directories(_logPath);
6989fa082aSMatt Spinler     }
70475e574dSMatt Spinler 
711d8835bbSSumit Kumar     if (!fs::exists(_archivePath))
721d8835bbSSumit Kumar     {
731d8835bbSSumit Kumar         fs::create_directories(_archivePath);
741d8835bbSSumit Kumar     }
751d8835bbSSumit Kumar 
76475e574dSMatt Spinler     restore();
77475e574dSMatt Spinler }
78475e574dSMatt Spinler 
restore()79475e574dSMatt Spinler void Repository::restore()
80475e574dSMatt Spinler {
81475e574dSMatt Spinler     for (auto& dirEntry : fs::directory_iterator(_logPath))
82475e574dSMatt Spinler     {
83475e574dSMatt Spinler         try
84475e574dSMatt Spinler         {
85475e574dSMatt Spinler             if (!fs::is_regular_file(dirEntry.path()))
86475e574dSMatt Spinler             {
87475e574dSMatt Spinler                 continue;
88475e574dSMatt Spinler             }
89475e574dSMatt Spinler 
90475e574dSMatt Spinler             std::ifstream file{dirEntry.path()};
91475e574dSMatt Spinler             std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
92475e574dSMatt Spinler                                       std::istreambuf_iterator<char>()};
93475e574dSMatt Spinler             file.close();
94475e574dSMatt Spinler 
9507eefc54SMatt Spinler             PEL pel{data};
96475e574dSMatt Spinler             if (pel.valid())
97475e574dSMatt Spinler             {
98a3c12a48SMatt Spinler                 // If the host hasn't acked it, reset the host state so
99a3c12a48SMatt Spinler                 // it will get sent up again.
100a3c12a48SMatt Spinler                 if (pel.hostTransmissionState() == TransmissionState::sent)
101a3c12a48SMatt Spinler                 {
102a3c12a48SMatt Spinler                     pel.setHostTransmissionState(TransmissionState::newPEL);
103a3c12a48SMatt Spinler                     try
104a3c12a48SMatt Spinler                     {
105a3c12a48SMatt Spinler                         write(pel, dirEntry.path());
106a3c12a48SMatt Spinler                     }
10766491c61SPatrick Williams                     catch (const std::exception& e)
108a3c12a48SMatt Spinler                     {
109db3f2798SMatt Spinler                         lg2::error(
110db3f2798SMatt Spinler                             "Failed to save PEL after updating host state, PEL ID = {ID}",
111db3f2798SMatt Spinler                             "ID", lg2::hex, pel.id());
112a3c12a48SMatt Spinler                     }
113a3c12a48SMatt Spinler                 }
114a3c12a48SMatt Spinler 
1158e65f4eaSMatt Spinler                 PELAttributes attributes{
1168e65f4eaSMatt Spinler                     dirEntry.path(),
117dd325c32SMatt Spinler                     getFileDiskSize(dirEntry.path()),
118dd325c32SMatt Spinler                     pel.privateHeader().creatorID(),
119afb1b46fSVijay Lobo                     pel.userHeader().subsystem(),
120dd325c32SMatt Spinler                     pel.userHeader().severity(),
121dd325c32SMatt Spinler                     pel.userHeader().actionFlags(),
122dd325c32SMatt Spinler                     pel.hostTransmissionState(),
1238e65f4eaSMatt Spinler                     pel.hmcTransmissionState(),
1248e65f4eaSMatt Spinler                     pel.plid(),
1258e65f4eaSMatt Spinler                     pel.getDeconfigFlag(),
1268e65f4eaSMatt Spinler                     pel.getGuardFlag(),
1278e65f4eaSMatt Spinler                     getMillisecondsSinceEpoch(
1288e65f4eaSMatt Spinler                         pel.privateHeader().createTimestamp())};
1290ff00485SMatt Spinler 
130475e574dSMatt Spinler                 using pelID = LogID::Pel;
131475e574dSMatt Spinler                 using obmcID = LogID::Obmc;
1320ff00485SMatt Spinler                 _pelAttributes.emplace(
133475e574dSMatt Spinler                     LogID(pelID(pel.id()), obmcID(pel.obmcLogID())),
1340ff00485SMatt Spinler                     attributes);
135b188f78aSMatt Spinler 
136b188f78aSMatt Spinler                 updateRepoStats(attributes, true);
137475e574dSMatt Spinler             }
138475e574dSMatt Spinler             else
139475e574dSMatt Spinler             {
140db3f2798SMatt Spinler                 lg2::error(
141db3f2798SMatt Spinler                     "Found invalid PEL file {FILE} while restoring.  Removing.",
142db3f2798SMatt Spinler                     "FILE", dirEntry.path());
143475e574dSMatt Spinler                 fs::remove(dirEntry.path());
144475e574dSMatt Spinler             }
145475e574dSMatt Spinler         }
14666491c61SPatrick Williams         catch (const std::exception& e)
147475e574dSMatt Spinler         {
148db3f2798SMatt Spinler             lg2::error("Hit exception while restoring PEL file {FILE}: {ERROR}",
149db3f2798SMatt Spinler                        "FILE", dirEntry.path(), "ERROR", e);
150475e574dSMatt Spinler         }
151475e574dSMatt Spinler     }
1521d8835bbSSumit Kumar 
1531d8835bbSSumit Kumar     // Get size of archive folder
1541d8835bbSSumit Kumar     for (auto& dirEntry : fs::directory_iterator(_archivePath))
1551d8835bbSSumit Kumar     {
1561d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(dirEntry);
1571d8835bbSSumit Kumar     }
15889fa082aSMatt Spinler }
15989fa082aSMatt Spinler 
getPELFilename(uint32_t pelID,const BCDTime & time)16089fa082aSMatt Spinler std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
16189fa082aSMatt Spinler {
16289fa082aSMatt Spinler     char name[50];
16389fa082aSMatt Spinler     sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", time.yearMSB,
16489fa082aSMatt Spinler             time.yearLSB, time.month, time.day, time.hour, time.minutes,
16589fa082aSMatt Spinler             time.seconds, time.hundredths, pelID);
16689fa082aSMatt Spinler     return std::string{name};
16789fa082aSMatt Spinler }
16889fa082aSMatt Spinler 
add(std::unique_ptr<PEL> & pel)16989fa082aSMatt Spinler void Repository::add(std::unique_ptr<PEL>& pel)
17089fa082aSMatt Spinler {
171df43a305SMatt Spinler     pel->setHostTransmissionState(TransmissionState::newPEL);
172df43a305SMatt Spinler     pel->setHMCTransmissionState(TransmissionState::newPEL);
173df43a305SMatt Spinler 
17489fa082aSMatt Spinler     auto path = _logPath / getPELFilename(pel->id(), pel->commitTime());
175ab1b97feSMatt Spinler 
176ab1b97feSMatt Spinler     write(*(pel.get()), path);
177ab1b97feSMatt Spinler 
1788e65f4eaSMatt Spinler     PELAttributes attributes{
1798e65f4eaSMatt Spinler         path,
180dd325c32SMatt Spinler         getFileDiskSize(path),
181dd325c32SMatt Spinler         pel->privateHeader().creatorID(),
182afb1b46fSVijay Lobo         pel->userHeader().subsystem(),
183dd325c32SMatt Spinler         pel->userHeader().severity(),
184dd325c32SMatt Spinler         pel->userHeader().actionFlags(),
185346f99a1SMatt Spinler         pel->hostTransmissionState(),
1868e65f4eaSMatt Spinler         pel->hmcTransmissionState(),
1878e65f4eaSMatt Spinler         pel->plid(),
1888e65f4eaSMatt Spinler         pel->getDeconfigFlag(),
1898e65f4eaSMatt Spinler         pel->getGuardFlag(),
1908e65f4eaSMatt Spinler         getMillisecondsSinceEpoch(pel->privateHeader().createTimestamp())};
191ab1b97feSMatt Spinler 
192ab1b97feSMatt Spinler     using pelID = LogID::Pel;
193ab1b97feSMatt Spinler     using obmcID = LogID::Obmc;
194ab1b97feSMatt Spinler     _pelAttributes.emplace(LogID(pelID(pel->id()), obmcID(pel->obmcLogID())),
195ab1b97feSMatt Spinler                            attributes);
196ab1b97feSMatt Spinler 
19744893cc9SMatt Spinler     _lastPelID = pel->id();
19844893cc9SMatt Spinler 
199b188f78aSMatt Spinler     updateRepoStats(attributes, true);
200b188f78aSMatt Spinler 
201ab1b97feSMatt Spinler     processAddCallbacks(*pel);
202ab1b97feSMatt Spinler }
203ab1b97feSMatt Spinler 
write(const PEL & pel,const fs::path & path)204ab1b97feSMatt Spinler void Repository::write(const PEL& pel, const fs::path& path)
205ab1b97feSMatt Spinler {
20689fa082aSMatt Spinler     std::ofstream file{path, std::ios::binary};
20789fa082aSMatt Spinler 
20889fa082aSMatt Spinler     if (!file.good())
20989fa082aSMatt Spinler     {
21089fa082aSMatt Spinler         // If this fails, the filesystem is probably full so it isn't like
21189fa082aSMatt Spinler         // we could successfully create yet another error log here.
21289fa082aSMatt Spinler         auto e = errno;
21389fa082aSMatt Spinler         fs::remove(path);
214db3f2798SMatt Spinler         lg2::error(
215db3f2798SMatt Spinler             "Unable to open PEL file {FILE} for writing, errno = {ERRNO}",
216db3f2798SMatt Spinler             "FILE", path, "ERRNO", e);
21789fa082aSMatt Spinler         throw file_error::Open();
21889fa082aSMatt Spinler     }
21989fa082aSMatt Spinler 
220ab1b97feSMatt Spinler     auto data = pel.data();
22189fa082aSMatt Spinler     file.write(reinterpret_cast<const char*>(data.data()), data.size());
22289fa082aSMatt Spinler 
22389fa082aSMatt Spinler     if (file.fail())
22489fa082aSMatt Spinler     {
22589fa082aSMatt Spinler         // Same note as above about not being able to create an error log
22689fa082aSMatt Spinler         // for this case even if we wanted.
22789fa082aSMatt Spinler         auto e = errno;
22889fa082aSMatt Spinler         file.close();
22989fa082aSMatt Spinler         fs::remove(path);
230db3f2798SMatt Spinler         lg2::error("Unable to write PEL file {FILE}, errno = {ERRNO}", "FILE",
231db3f2798SMatt Spinler                    path, "ERRNO", e);
23289fa082aSMatt Spinler         throw file_error::Write();
23389fa082aSMatt Spinler     }
234475e574dSMatt Spinler }
235475e574dSMatt Spinler 
remove(const LogID & id)23652602e35SMatt Spinler std::optional<Repository::LogID> Repository::remove(const LogID& id)
237475e574dSMatt Spinler {
238475e574dSMatt Spinler     auto pel = findPEL(id);
239ff6b598bSPatrick Williams     if (pel == _pelAttributes.end())
240475e574dSMatt Spinler     {
241ff6b598bSPatrick Williams         return std::nullopt;
242ff6b598bSPatrick Williams     }
243ff6b598bSPatrick Williams 
244ff6b598bSPatrick Williams     LogID actualID = pel->first;
245b188f78aSMatt Spinler     updateRepoStats(pel->second, false);
246b188f78aSMatt Spinler 
247db3f2798SMatt Spinler     lg2::debug(
248db3f2798SMatt Spinler         "Removing PEL from repository, PEL ID = {PEL_ID}, BMC log ID = {BMC_ID}",
249db3f2798SMatt Spinler         "PEL_ID", lg2::hex, actualID.pelID.id, "BMC_ID", actualID.obmcID.id);
2501d8835bbSSumit Kumar 
2511d8835bbSSumit Kumar     if (fs::exists(pel->second.path))
2521d8835bbSSumit Kumar     {
2531d8835bbSSumit Kumar         // Check for existense of new archive folder
2541d8835bbSSumit Kumar         if (!fs::exists(_archivePath))
2551d8835bbSSumit Kumar         {
2561d8835bbSSumit Kumar             fs::create_directories(_archivePath);
2571d8835bbSSumit Kumar         }
2581d8835bbSSumit Kumar 
2591d8835bbSSumit Kumar         // Move log file to archive folder
2601d8835bbSSumit Kumar         auto fileName = _archivePath / pel->second.path.filename();
2611d8835bbSSumit Kumar         fs::rename(pel->second.path, fileName);
2621d8835bbSSumit Kumar 
2631d8835bbSSumit Kumar         // Update size of file
2641d8835bbSSumit Kumar         _archiveSize += getFileDiskSize(fileName);
2651d8835bbSSumit Kumar     }
2661d8835bbSSumit Kumar 
2670ff00485SMatt Spinler     _pelAttributes.erase(pel);
268421f6531SMatt Spinler 
269ff6b598bSPatrick Williams     processDeleteCallbacks(actualID.pelID.id);
27052602e35SMatt Spinler 
27152602e35SMatt Spinler     return actualID;
27289fa082aSMatt Spinler }
27389fa082aSMatt Spinler 
getPELData(const LogID & id)2742813f36dSMatt Spinler std::optional<std::vector<uint8_t>> Repository::getPELData(const LogID& id)
2752813f36dSMatt Spinler {
2762813f36dSMatt Spinler     auto pel = findPEL(id);
2770ff00485SMatt Spinler     if (pel != _pelAttributes.end())
2782813f36dSMatt Spinler     {
2790ff00485SMatt Spinler         std::ifstream file{pel->second.path.c_str()};
2802813f36dSMatt Spinler         if (!file.good())
2812813f36dSMatt Spinler         {
2822813f36dSMatt Spinler             auto e = errno;
283db3f2798SMatt Spinler             lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
284db3f2798SMatt Spinler                        "FILE", pel->second.path, "ERRNO", e);
2852813f36dSMatt Spinler             throw file_error::Open();
2862813f36dSMatt Spinler         }
2872813f36dSMatt Spinler 
2882813f36dSMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
2892813f36dSMatt Spinler                                   std::istreambuf_iterator<char>()};
2902813f36dSMatt Spinler         return data;
2912813f36dSMatt Spinler     }
2922813f36dSMatt Spinler 
2932813f36dSMatt Spinler     return std::nullopt;
2942813f36dSMatt Spinler }
2952813f36dSMatt Spinler 
getPELFD(const LogID & id)2966d51224bSMatt Spinler std::optional<sdbusplus::message::unix_fd> Repository::getPELFD(const LogID& id)
2976d51224bSMatt Spinler {
2986d51224bSMatt Spinler     auto pel = findPEL(id);
2996d51224bSMatt Spinler     if (pel != _pelAttributes.end())
3006d51224bSMatt Spinler     {
30132a6df6cSMatt Spinler         int fd = open(pel->second.path.c_str(), O_RDONLY | O_NONBLOCK);
30232a6df6cSMatt Spinler         if (fd == -1)
3036d51224bSMatt Spinler         {
3046d51224bSMatt Spinler             auto e = errno;
305db3f2798SMatt Spinler             lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
306db3f2798SMatt Spinler                        "FILE", pel->second.path, "ERRNO", e);
3076d51224bSMatt Spinler             throw file_error::Open();
3086d51224bSMatt Spinler         }
3096d51224bSMatt Spinler 
3106d51224bSMatt Spinler         // Must leave the file open here.  It will be closed by sdbusplus
3116d51224bSMatt Spinler         // when it sends it back over D-Bus.
31232a6df6cSMatt Spinler         return fd;
3136d51224bSMatt Spinler     }
3146d51224bSMatt Spinler     return std::nullopt;
3156d51224bSMatt Spinler }
3166d51224bSMatt Spinler 
for_each(ForEachFunc func) const3171ea78801SMatt Spinler void Repository::for_each(ForEachFunc func) const
3181ea78801SMatt Spinler {
3190ff00485SMatt Spinler     for (const auto& [id, attributes] : _pelAttributes)
3201ea78801SMatt Spinler     {
3210ff00485SMatt Spinler         std::ifstream file{attributes.path};
3221ea78801SMatt Spinler 
3231ea78801SMatt Spinler         if (!file.good())
3241ea78801SMatt Spinler         {
3251ea78801SMatt Spinler             auto e = errno;
326db3f2798SMatt Spinler             lg2::error(
327db3f2798SMatt Spinler                 "Repository::for_each: Unable to open PEL file {FILE}, errno = {ERRNO}",
328db3f2798SMatt Spinler                 "FILE", attributes.path, "ERRNO", e);
3291ea78801SMatt Spinler             continue;
3301ea78801SMatt Spinler         }
3311ea78801SMatt Spinler 
3321ea78801SMatt Spinler         std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
3331ea78801SMatt Spinler                                   std::istreambuf_iterator<char>()};
3341ea78801SMatt Spinler         file.close();
3351ea78801SMatt Spinler 
3361ea78801SMatt Spinler         PEL pel{data};
3371ea78801SMatt Spinler 
3381ea78801SMatt Spinler         try
3391ea78801SMatt Spinler         {
3401ea78801SMatt Spinler             if (func(pel))
3411ea78801SMatt Spinler             {
3421ea78801SMatt Spinler                 break;
3431ea78801SMatt Spinler             }
3441ea78801SMatt Spinler         }
34566491c61SPatrick Williams         catch (const std::exception& e)
3461ea78801SMatt Spinler         {
347db3f2798SMatt Spinler             lg2::error("Repository::for_each function exception: {ERROR}",
348db3f2798SMatt Spinler                        "ERROR", e);
3491ea78801SMatt Spinler         }
3501ea78801SMatt Spinler     }
3511ea78801SMatt Spinler }
3521ea78801SMatt Spinler 
processAddCallbacks(const PEL & pel) const353421f6531SMatt Spinler void Repository::processAddCallbacks(const PEL& pel) const
354421f6531SMatt Spinler {
355421f6531SMatt Spinler     for (auto& [name, func] : _addSubscriptions)
356421f6531SMatt Spinler     {
357421f6531SMatt Spinler         try
358421f6531SMatt Spinler         {
359421f6531SMatt Spinler             func(pel);
360421f6531SMatt Spinler         }
36166491c61SPatrick Williams         catch (const std::exception& e)
362421f6531SMatt Spinler         {
363db3f2798SMatt Spinler             lg2::error(
364db3f2798SMatt Spinler                 "PEL Repository add callback exception. Name = {NAME}, Error = {ERROR}",
365db3f2798SMatt Spinler                 "NAME", name, "ERROR", e);
366421f6531SMatt Spinler         }
367421f6531SMatt Spinler     }
368421f6531SMatt Spinler }
369421f6531SMatt Spinler 
processDeleteCallbacks(uint32_t id) const370421f6531SMatt Spinler void Repository::processDeleteCallbacks(uint32_t id) const
371421f6531SMatt Spinler {
372421f6531SMatt Spinler     for (auto& [name, func] : _deleteSubscriptions)
373421f6531SMatt Spinler     {
374421f6531SMatt Spinler         try
375421f6531SMatt Spinler         {
376421f6531SMatt Spinler             func(id);
377421f6531SMatt Spinler         }
37866491c61SPatrick Williams         catch (const std::exception& e)
379421f6531SMatt Spinler         {
380db3f2798SMatt Spinler             lg2::error(
381db3f2798SMatt Spinler                 "PEL Repository delete callback exception. Name = {NAME}, Error = {ERROR}",
382db3f2798SMatt Spinler                 "NAME", name, "ERROR", e);
383421f6531SMatt Spinler         }
384421f6531SMatt Spinler     }
385421f6531SMatt Spinler }
386421f6531SMatt Spinler 
3870ff00485SMatt Spinler std::optional<std::reference_wrapper<const Repository::PELAttributes>>
getPELAttributes(const LogID & id) const3880ff00485SMatt Spinler     Repository::getPELAttributes(const LogID& id) const
3890ff00485SMatt Spinler {
3900ff00485SMatt Spinler     auto pel = findPEL(id);
3910ff00485SMatt Spinler     if (pel != _pelAttributes.end())
3920ff00485SMatt Spinler     {
3930ff00485SMatt Spinler         return pel->second;
3940ff00485SMatt Spinler     }
3950ff00485SMatt Spinler 
3960ff00485SMatt Spinler     return std::nullopt;
3970ff00485SMatt Spinler }
3980ff00485SMatt Spinler 
setPELHostTransState(uint32_t pelID,TransmissionState state)39929d18c11SMatt Spinler void Repository::setPELHostTransState(uint32_t pelID, TransmissionState state)
40029d18c11SMatt Spinler {
40129d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
40229d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
40329d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
40429d18c11SMatt Spinler 
40529d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hostState != state))
40629d18c11SMatt Spinler     {
40729d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
40829d18c11SMatt Spinler             pel.setHostTransmissionState(state);
409d0ccda3cSMatt Spinler             return true;
41029d18c11SMatt Spinler         };
41129d18c11SMatt Spinler 
41229d18c11SMatt Spinler         try
41329d18c11SMatt Spinler         {
41429d18c11SMatt Spinler             updatePEL(attr->second.path, func);
41529d18c11SMatt Spinler         }
41666491c61SPatrick Williams         catch (const std::exception& e)
41729d18c11SMatt Spinler         {
418db3f2798SMatt Spinler             lg2::error(
419db3f2798SMatt Spinler                 "Unable to update PEL host transmission state. Path = {PATH}, Error = {ERROR}",
420db3f2798SMatt Spinler                 "PATH", attr->second.path, "ERROR", e);
42129d18c11SMatt Spinler         }
42229d18c11SMatt Spinler     }
42329d18c11SMatt Spinler }
42429d18c11SMatt Spinler 
setPELHMCTransState(uint32_t pelID,TransmissionState state)42529d18c11SMatt Spinler void Repository::setPELHMCTransState(uint32_t pelID, TransmissionState state)
42629d18c11SMatt Spinler {
42729d18c11SMatt Spinler     LogID id{LogID::Pel{pelID}};
42829d18c11SMatt Spinler     auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
42929d18c11SMatt Spinler                              [&id](const auto& a) { return a.first == id; });
43029d18c11SMatt Spinler 
43129d18c11SMatt Spinler     if ((attr != _pelAttributes.end()) && (attr->second.hmcState != state))
43229d18c11SMatt Spinler     {
43329d18c11SMatt Spinler         PELUpdateFunc func = [state](PEL& pel) {
43429d18c11SMatt Spinler             pel.setHMCTransmissionState(state);
435d0ccda3cSMatt Spinler             return true;
43629d18c11SMatt Spinler         };
43729d18c11SMatt Spinler 
43829d18c11SMatt Spinler         try
43929d18c11SMatt Spinler         {
44029d18c11SMatt Spinler             updatePEL(attr->second.path, func);
44129d18c11SMatt Spinler         }
44266491c61SPatrick Williams         catch (const std::exception& e)
44329d18c11SMatt Spinler         {
444db3f2798SMatt Spinler             lg2::error(
445db3f2798SMatt Spinler                 "Unable to update PEL HMC transmission state. Path = {PATH}, Error = {ERROR}",
446db3f2798SMatt Spinler                 "PATH", attr->second.path, "ERROR", e);
44729d18c11SMatt Spinler         }
44829d18c11SMatt Spinler     }
44929d18c11SMatt Spinler }
45029d18c11SMatt Spinler 
updatePEL(const fs::path & path,PELUpdateFunc updateFunc)4511cb59f70SMatt Spinler bool Repository::updatePEL(const fs::path& path, PELUpdateFunc updateFunc)
45229d18c11SMatt Spinler {
45329d18c11SMatt Spinler     std::ifstream file{path};
45429d18c11SMatt Spinler     std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
45529d18c11SMatt Spinler                               std::istreambuf_iterator<char>()};
45629d18c11SMatt Spinler     file.close();
45729d18c11SMatt Spinler 
45829d18c11SMatt Spinler     PEL pel{data};
45929d18c11SMatt Spinler 
46029d18c11SMatt Spinler     if (pel.valid())
46129d18c11SMatt Spinler     {
462d0ccda3cSMatt Spinler         if (updateFunc(pel))
463d0ccda3cSMatt Spinler         {
464d0ccda3cSMatt Spinler             // Three attribute fields can change post creation from
465d0ccda3cSMatt Spinler             // an updatePEL call:
466d0ccda3cSMatt Spinler             //  - hmcTransmissionState - When HMC acks a PEL
467d0ccda3cSMatt Spinler             //  - hostTransmissionState - When host acks a PEL
468d0ccda3cSMatt Spinler             //  - deconfig flag - Can be cleared for PELs that call out
469d0ccda3cSMatt Spinler             //                    hotplugged FRUs.
470d0ccda3cSMatt Spinler             // Make sure they're up to date.
471d0ccda3cSMatt Spinler             LogID id{LogID::Pel(pel.id())};
472d0ccda3cSMatt Spinler             auto attr =
473d0ccda3cSMatt Spinler                 std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
474d0ccda3cSMatt Spinler                              [&id](const auto& a) { return a.first == id; });
475d0ccda3cSMatt Spinler             if (attr != _pelAttributes.end())
476d0ccda3cSMatt Spinler             {
477d0ccda3cSMatt Spinler                 attr->second.hmcState = pel.hmcTransmissionState();
478d0ccda3cSMatt Spinler                 attr->second.hostState = pel.hostTransmissionState();
479d0ccda3cSMatt Spinler                 attr->second.deconfig = pel.getDeconfigFlag();
480d0ccda3cSMatt Spinler             }
48129d18c11SMatt Spinler 
48229d18c11SMatt Spinler             write(pel, path);
4831cb59f70SMatt Spinler             return true;
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     }
4911cb59f70SMatt Spinler     return false;
49229d18c11SMatt Spinler }
49329d18c11SMatt Spinler 
isServiceableSev(const PELAttributes & pel)494b188f78aSMatt Spinler bool Repository::isServiceableSev(const PELAttributes& pel)
495b188f78aSMatt Spinler {
496b188f78aSMatt Spinler     auto sevType = static_cast<SeverityType>(pel.severity & 0xF0);
497*075c7923SPatrick Williams     auto sevPVEntry =
498*075c7923SPatrick Williams         pel_values::findByValue(pel.severity, pel_values::severityValues);
499b188f78aSMatt Spinler     std::string sevName = std::get<pel_values::registryNamePos>(*sevPVEntry);
500b188f78aSMatt Spinler 
501b188f78aSMatt Spinler     bool check1 = (sevType == SeverityType::predictive) ||
502b188f78aSMatt Spinler                   (sevType == SeverityType::unrecoverable) ||
503b188f78aSMatt Spinler                   (sevType == SeverityType::critical);
504b188f78aSMatt Spinler 
505b188f78aSMatt Spinler     bool check2 = ((sevType == SeverityType::recovered) ||
506b188f78aSMatt Spinler                    (sevName == "symptom_recovered")) &&
507b188f78aSMatt Spinler                   !pel.actionFlags.test(hiddenFlagBit);
508b188f78aSMatt Spinler 
509b188f78aSMatt Spinler     bool check3 = (sevName == "symptom_predictive") ||
510b188f78aSMatt Spinler                   (sevName == "symptom_unrecoverable") ||
511b188f78aSMatt Spinler                   (sevName == "symptom_critical");
512b188f78aSMatt Spinler 
513b188f78aSMatt Spinler     return check1 || check2 || check3;
514b188f78aSMatt Spinler }
515b188f78aSMatt Spinler 
updateRepoStats(const PELAttributes & pel,bool pelAdded)516b188f78aSMatt Spinler void Repository::updateRepoStats(const PELAttributes& pel, bool pelAdded)
517b188f78aSMatt Spinler {
518b188f78aSMatt Spinler     auto isServiceable = Repository::isServiceableSev(pel);
519b188f78aSMatt Spinler     auto bmcPEL = CreatorID::openBMC == static_cast<CreatorID>(pel.creator);
520b188f78aSMatt Spinler 
521b188f78aSMatt Spinler     auto adjustSize = [pelAdded, &pel](auto& runningSize) {
522b188f78aSMatt Spinler         if (pelAdded)
523b188f78aSMatt Spinler         {
524b188f78aSMatt Spinler             runningSize += pel.sizeOnDisk;
525b188f78aSMatt Spinler         }
526b188f78aSMatt Spinler         else
527b188f78aSMatt Spinler         {
528b188f78aSMatt Spinler             runningSize = std::max(static_cast<int64_t>(runningSize) -
529b188f78aSMatt Spinler                                        static_cast<int64_t>(pel.sizeOnDisk),
530b188f78aSMatt Spinler                                    static_cast<int64_t>(0));
531b188f78aSMatt Spinler         }
532b188f78aSMatt Spinler     };
533b188f78aSMatt Spinler 
534b188f78aSMatt Spinler     adjustSize(_sizes.total);
535b188f78aSMatt Spinler 
536b188f78aSMatt Spinler     if (bmcPEL)
537b188f78aSMatt Spinler     {
538b188f78aSMatt Spinler         adjustSize(_sizes.bmc);
539b188f78aSMatt Spinler         if (isServiceable)
540b188f78aSMatt Spinler         {
541b188f78aSMatt Spinler             adjustSize(_sizes.bmcServiceable);
542b188f78aSMatt Spinler         }
543b188f78aSMatt Spinler         else
544b188f78aSMatt Spinler         {
545b188f78aSMatt Spinler             adjustSize(_sizes.bmcInfo);
546b188f78aSMatt Spinler         }
547b188f78aSMatt Spinler     }
548b188f78aSMatt Spinler     else
549b188f78aSMatt Spinler     {
550b188f78aSMatt Spinler         adjustSize(_sizes.nonBMC);
551b188f78aSMatt Spinler         if (isServiceable)
552b188f78aSMatt Spinler         {
553b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCServiceable);
554b188f78aSMatt Spinler         }
555b188f78aSMatt Spinler         else
556b188f78aSMatt Spinler         {
557b188f78aSMatt Spinler             adjustSize(_sizes.nonBMCInfo);
558b188f78aSMatt Spinler         }
559b188f78aSMatt Spinler     }
560b188f78aSMatt Spinler }
561b188f78aSMatt Spinler 
sizeWarning()562c296692bSSumit Kumar bool Repository::sizeWarning()
5637e727a39SMatt Spinler {
564c296692bSSumit Kumar     std::error_code ec;
565c296692bSSumit Kumar 
5661d8835bbSSumit Kumar     if ((_archiveSize > 0) && ((_sizes.total + _archiveSize) >
5671d8835bbSSumit Kumar                                ((_maxRepoSize * warningPercentage) / 100)))
5681d8835bbSSumit Kumar     {
569db3f2798SMatt Spinler         lg2::info(
5701d8835bbSSumit Kumar             "Repository::sizeWarning function:Deleting the files in archive");
5711d8835bbSSumit Kumar 
572c296692bSSumit Kumar         for (const auto& dirEntry : fs::directory_iterator(_archivePath))
5731d8835bbSSumit Kumar         {
574c296692bSSumit Kumar             fs::remove(dirEntry.path(), ec);
575c296692bSSumit Kumar             if (ec)
576c296692bSSumit Kumar             {
577db3f2798SMatt Spinler                 lg2::info("Repository::sizeWarning: Could not delete "
578db3f2798SMatt Spinler                           "file {FILE} in PEL archive",
579db3f2798SMatt Spinler                           "FILE", dirEntry.path());
5801d8835bbSSumit Kumar             }
5811d8835bbSSumit Kumar         }
5821d8835bbSSumit Kumar 
583c296692bSSumit Kumar         _archiveSize = 0;
584c296692bSSumit Kumar     }
585c296692bSSumit Kumar 
5867e727a39SMatt Spinler     return (_sizes.total > (_maxRepoSize * warningPercentage / 100)) ||
5877e727a39SMatt Spinler            (_pelAttributes.size() > _maxNumPELs);
5887e727a39SMatt Spinler }
5897e727a39SMatt Spinler 
590b0a8df5bSMatt Spinler std::vector<Repository::AttributesReference>
getAllPELAttributes(SortOrder order) const591b0a8df5bSMatt Spinler     Repository::getAllPELAttributes(SortOrder order) const
592b0a8df5bSMatt Spinler {
593b0a8df5bSMatt Spinler     std::vector<Repository::AttributesReference> attributes;
594b0a8df5bSMatt Spinler 
595*075c7923SPatrick Williams     std::for_each(_pelAttributes.begin(), _pelAttributes.end(),
596*075c7923SPatrick Williams                   [&attributes](auto& pelEntry) {
597*075c7923SPatrick Williams                       attributes.push_back(pelEntry);
598*075c7923SPatrick Williams                   });
599b0a8df5bSMatt Spinler 
600b0a8df5bSMatt Spinler     std::sort(attributes.begin(), attributes.end(),
601b0a8df5bSMatt Spinler               [order](const auto& left, const auto& right) {
602b0a8df5bSMatt Spinler                   if (order == SortOrder::ascending)
603b0a8df5bSMatt Spinler                   {
604b0a8df5bSMatt Spinler                       return left.get().second.path < right.get().second.path;
605b0a8df5bSMatt Spinler                   }
606b0a8df5bSMatt Spinler                   return left.get().second.path > right.get().second.path;
607b0a8df5bSMatt Spinler               });
608b0a8df5bSMatt Spinler 
609b0a8df5bSMatt Spinler     return attributes;
610b0a8df5bSMatt Spinler }
611b0a8df5bSMatt Spinler 
612027bf285SSumit Kumar std::vector<uint32_t>
prune(const std::vector<uint32_t> & idsWithHwIsoEntry)613027bf285SSumit Kumar     Repository::prune(const std::vector<uint32_t>& idsWithHwIsoEntry)
614b0a8df5bSMatt Spinler {
615b0a8df5bSMatt Spinler     std::vector<uint32_t> obmcLogIDs;
616db3f2798SMatt Spinler     lg2::info("Pruning PEL repository that takes up {TOTAL} bytes and has "
617db3f2798SMatt Spinler               "{NUM_PELS} PELs",
618db3f2798SMatt Spinler               "TOTAL", _sizes.total, "NUM_PELS", _pelAttributes.size());
619b0a8df5bSMatt Spinler 
620b0a8df5bSMatt Spinler     // Set up the 5 functions to check if the PEL category
621b0a8df5bSMatt Spinler     // is still over its limits.
622b0a8df5bSMatt Spinler 
623b0a8df5bSMatt Spinler     // BMC informational PELs should only take up 15%
624b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCInfoLimit = [this]() {
625b0a8df5bSMatt Spinler         return _sizes.bmcInfo > _maxRepoSize * 15 / 100;
626b0a8df5bSMatt Spinler     };
627b0a8df5bSMatt Spinler 
628b0a8df5bSMatt Spinler     // BMC non informational PELs should only take up 30%
629b0a8df5bSMatt Spinler     IsOverLimitFunc overBMCNonInfoLimit = [this]() {
630b0a8df5bSMatt Spinler         return _sizes.bmcServiceable > _maxRepoSize * 30 / 100;
631b0a8df5bSMatt Spinler     };
632b0a8df5bSMatt Spinler 
633b0a8df5bSMatt Spinler     // Non BMC informational PELs should only take up 15%
634b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCInfoLimit = [this]() {
635b0a8df5bSMatt Spinler         return _sizes.nonBMCInfo > _maxRepoSize * 15 / 100;
636b0a8df5bSMatt Spinler     };
637b0a8df5bSMatt Spinler 
638b0a8df5bSMatt Spinler     // Non BMC non informational PELs should only take up 15%
639b0a8df5bSMatt Spinler     IsOverLimitFunc overNonBMCNonInfoLimit = [this]() {
640b0a8df5bSMatt Spinler         return _sizes.nonBMCServiceable > _maxRepoSize * 30 / 100;
641b0a8df5bSMatt Spinler     };
642b0a8df5bSMatt Spinler 
643b0a8df5bSMatt Spinler     // Bring the total number of PELs down to 80% of the max
644b0a8df5bSMatt Spinler     IsOverLimitFunc tooManyPELsLimit = [this]() {
645b0a8df5bSMatt Spinler         return _pelAttributes.size() > _maxNumPELs * 80 / 100;
646b0a8df5bSMatt Spinler     };
647b0a8df5bSMatt Spinler 
648b0a8df5bSMatt Spinler     // Set up the functions to determine which category a PEL is in.
649b0a8df5bSMatt Spinler     // TODO: Return false in these functions if a PEL caused a guard record.
650b0a8df5bSMatt Spinler 
651b0a8df5bSMatt Spinler     // A BMC informational PEL
652b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCInfo = [](const PELAttributes& pel) {
653b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
654b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
655b0a8df5bSMatt Spinler     };
656b0a8df5bSMatt Spinler 
657b0a8df5bSMatt Spinler     // A BMC non informational PEL
658b0a8df5bSMatt Spinler     IsPELTypeFunc isBMCNonInfo = [](const PELAttributes& pel) {
659b0a8df5bSMatt Spinler         return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
660b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
661b0a8df5bSMatt Spinler     };
662b0a8df5bSMatt Spinler 
663b0a8df5bSMatt Spinler     // A non BMC informational PEL
664b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCInfo = [](const PELAttributes& pel) {
665b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
666b0a8df5bSMatt Spinler                !Repository::isServiceableSev(pel);
667b0a8df5bSMatt Spinler     };
668b0a8df5bSMatt Spinler 
669b0a8df5bSMatt Spinler     // A non BMC non informational PEL
670b0a8df5bSMatt Spinler     IsPELTypeFunc isNonBMCNonInfo = [](const PELAttributes& pel) {
671b0a8df5bSMatt Spinler         return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
672b0a8df5bSMatt Spinler                Repository::isServiceableSev(pel);
673b0a8df5bSMatt Spinler     };
674b0a8df5bSMatt Spinler 
675b0a8df5bSMatt Spinler     // When counting PELs, count every PEL
676d26fa3e7SPatrick Williams     IsPELTypeFunc isAnyPEL = [](const PELAttributes& /*pel*/) { return true; };
677b0a8df5bSMatt Spinler 
678b0a8df5bSMatt Spinler     // Check all 4 categories, which will result in at most 90%
679b0a8df5bSMatt Spinler     // usage (15 + 30 + 15 + 30).
680027bf285SSumit Kumar     removePELs(overBMCInfoLimit, isBMCInfo, idsWithHwIsoEntry, obmcLogIDs);
681027bf285SSumit Kumar     removePELs(overBMCNonInfoLimit, isBMCNonInfo, idsWithHwIsoEntry,
682027bf285SSumit Kumar                obmcLogIDs);
683027bf285SSumit Kumar     removePELs(overNonBMCInfoLimit, isNonBMCInfo, idsWithHwIsoEntry,
684027bf285SSumit Kumar                obmcLogIDs);
685027bf285SSumit Kumar     removePELs(overNonBMCNonInfoLimit, isNonBMCNonInfo, idsWithHwIsoEntry,
686027bf285SSumit Kumar                obmcLogIDs);
687b0a8df5bSMatt Spinler 
688b0a8df5bSMatt Spinler     // After the above pruning check if there are still too many PELs,
689b0a8df5bSMatt Spinler     // which can happen depending on PEL sizes.
690b0a8df5bSMatt Spinler     if (_pelAttributes.size() > _maxNumPELs)
691b0a8df5bSMatt Spinler     {
692027bf285SSumit Kumar         removePELs(tooManyPELsLimit, isAnyPEL, idsWithHwIsoEntry, obmcLogIDs);
693b0a8df5bSMatt Spinler     }
694b0a8df5bSMatt Spinler 
695b0a8df5bSMatt Spinler     if (!obmcLogIDs.empty())
696b0a8df5bSMatt Spinler     {
697db3f2798SMatt Spinler         lg2::info("Number of PELs removed to save space: {NUM_PELS}",
698db3f2798SMatt Spinler                   "NUM_PELS", obmcLogIDs.size());
699b0a8df5bSMatt Spinler     }
700b0a8df5bSMatt Spinler 
701b0a8df5bSMatt Spinler     return obmcLogIDs;
702b0a8df5bSMatt Spinler }
703b0a8df5bSMatt Spinler 
removePELs(const IsOverLimitFunc & isOverLimit,const IsPELTypeFunc & isPELType,const std::vector<uint32_t> & idsWithHwIsoEntry,std::vector<uint32_t> & removedBMCLogIDs)70445796e82SMatt Spinler void Repository::removePELs(const IsOverLimitFunc& isOverLimit,
70545796e82SMatt Spinler                             const IsPELTypeFunc& isPELType,
706027bf285SSumit Kumar                             const std::vector<uint32_t>& idsWithHwIsoEntry,
707b0a8df5bSMatt Spinler                             std::vector<uint32_t>& removedBMCLogIDs)
708b0a8df5bSMatt Spinler {
709b0a8df5bSMatt Spinler     if (!isOverLimit())
710b0a8df5bSMatt Spinler     {
711b0a8df5bSMatt Spinler         return;
712b0a8df5bSMatt Spinler     }
713b0a8df5bSMatt Spinler 
714b0a8df5bSMatt Spinler     auto attributes = getAllPELAttributes(SortOrder::ascending);
715b0a8df5bSMatt Spinler 
716b0a8df5bSMatt Spinler     // Make 4 passes on the PELs, stopping as soon as isOverLimit
717b0a8df5bSMatt Spinler     // returns false.
718b0a8df5bSMatt Spinler     //   Pass 1: only delete HMC acked PELs
719b0a8df5bSMatt Spinler     //   Pass 2: only delete OS acked PELs
720b0a8df5bSMatt Spinler     //   Pass 3: only delete PHYP sent PELs
721b0a8df5bSMatt Spinler     //   Pass 4: delete all PELs
722b0a8df5bSMatt Spinler     static const std::vector<std::function<bool(const PELAttributes& pel)>>
723b0a8df5bSMatt Spinler         stateChecks{[](const auto& pel) {
724b0a8df5bSMatt Spinler                         return pel.hmcState == TransmissionState::acked;
725b0a8df5bSMatt Spinler                     },
726b0a8df5bSMatt Spinler 
727b0a8df5bSMatt Spinler                     [](const auto& pel) {
728b0a8df5bSMatt Spinler                         return pel.hostState == TransmissionState::acked;
729b0a8df5bSMatt Spinler                     },
730b0a8df5bSMatt Spinler 
731b0a8df5bSMatt Spinler                     [](const auto& pel) {
732b0a8df5bSMatt Spinler                         return pel.hostState == TransmissionState::sent;
733b0a8df5bSMatt Spinler                     },
734b0a8df5bSMatt Spinler 
735d26fa3e7SPatrick Williams                     [](const auto& /*pel*/) { return true; }};
736b0a8df5bSMatt Spinler 
737b0a8df5bSMatt Spinler     for (const auto& stateCheck : stateChecks)
738b0a8df5bSMatt Spinler     {
739b0a8df5bSMatt Spinler         for (auto it = attributes.begin(); it != attributes.end();)
740b0a8df5bSMatt Spinler         {
741b0a8df5bSMatt Spinler             const auto& pel = it->get();
742b0a8df5bSMatt Spinler             if (isPELType(pel.second) && stateCheck(pel.second))
743b0a8df5bSMatt Spinler             {
744b0a8df5bSMatt Spinler                 auto removedID = pel.first.obmcID.id;
745027bf285SSumit Kumar 
746027bf285SSumit Kumar                 auto idFound = std::find(idsWithHwIsoEntry.begin(),
747027bf285SSumit Kumar                                          idsWithHwIsoEntry.end(), removedID);
748027bf285SSumit Kumar                 if (idFound != idsWithHwIsoEntry.end())
749027bf285SSumit Kumar                 {
750027bf285SSumit Kumar                     ++it;
751027bf285SSumit Kumar                     continue;
752027bf285SSumit Kumar                 }
753027bf285SSumit Kumar 
754b0a8df5bSMatt Spinler                 remove(pel.first);
755b0a8df5bSMatt Spinler 
756b0a8df5bSMatt Spinler                 removedBMCLogIDs.push_back(removedID);
757b0a8df5bSMatt Spinler 
758b0a8df5bSMatt Spinler                 attributes.erase(it);
759b0a8df5bSMatt Spinler 
760b0a8df5bSMatt Spinler                 if (!isOverLimit())
761b0a8df5bSMatt Spinler                 {
762b0a8df5bSMatt Spinler                     break;
763b0a8df5bSMatt Spinler                 }
764b0a8df5bSMatt Spinler             }
765b0a8df5bSMatt Spinler             else
766b0a8df5bSMatt Spinler             {
767b0a8df5bSMatt Spinler                 ++it;
768b0a8df5bSMatt Spinler             }
769b0a8df5bSMatt Spinler         }
770b0a8df5bSMatt Spinler 
771b0a8df5bSMatt Spinler         if (!isOverLimit())
772b0a8df5bSMatt Spinler         {
773b0a8df5bSMatt Spinler             break;
774b0a8df5bSMatt Spinler         }
775b0a8df5bSMatt Spinler     }
776b0a8df5bSMatt Spinler }
777b0a8df5bSMatt Spinler 
archivePEL(const PEL & pel)7782ccdcef9SSumit Kumar void Repository::archivePEL(const PEL& pel)
7792ccdcef9SSumit Kumar {
7802ccdcef9SSumit Kumar     if (pel.valid())
7812ccdcef9SSumit Kumar     {
7822ccdcef9SSumit Kumar         auto path = _archivePath / getPELFilename(pel.id(), pel.commitTime());
7832ccdcef9SSumit Kumar 
7842ccdcef9SSumit Kumar         write(pel, path);
7852ccdcef9SSumit Kumar 
7862ccdcef9SSumit Kumar         _archiveSize += getFileDiskSize(path);
7872ccdcef9SSumit Kumar     }
7882ccdcef9SSumit Kumar }
7892ccdcef9SSumit Kumar 
79089fa082aSMatt Spinler } // namespace pels
79189fa082aSMatt Spinler } // namespace openpower
792