1cb65ffceSJayanth Othayoth #include "config.h"
2cb65ffceSJayanth Othayoth 
3cb65ffceSJayanth Othayoth #include "elog_watch.hpp"
4cb65ffceSJayanth Othayoth 
5cb65ffceSJayanth Othayoth #include "dump_serialize.hpp"
6aa0937f9SDhruvaraj Subhashchandran #include "dump_types.hpp"
7cb65ffceSJayanth Othayoth #include "xyz/openbmc_project/Dump/Create/error.hpp"
8cb65ffceSJayanth Othayoth 
931085974SVishwanatha Subbanna #include <cereal/cereal.hpp>
10d0f0064eSJayanth Othayoth #include <phosphor-logging/elog.hpp>
11d1f670feSDhruvaraj Subhashchandran #include <phosphor-logging/lg2.hpp>
1215cd3ce7SWilliam A. Kennington III #include <sdbusplus/exception.hpp>
13*1615b824SDhruvaraj Subhashchandran #include <xyz/openbmc_project/Dump/Create/common.hpp>
14d0f0064eSJayanth Othayoth 
150af74a5eSJayanth Othayoth #include <fstream>
160af74a5eSJayanth Othayoth 
1731085974SVishwanatha Subbanna // Register class version with Cereal
18bb410df7SRamesh Iyyar CEREAL_CLASS_VERSION(phosphor::dump::elog::Watch, CLASS_VERSION)
19d0f0064eSJayanth Othayoth 
20d0f0064eSJayanth Othayoth namespace phosphor
21d0f0064eSJayanth Othayoth {
22d0f0064eSJayanth Othayoth namespace dump
23d0f0064eSJayanth Othayoth {
24d0f0064eSJayanth Othayoth namespace elog
25d0f0064eSJayanth Othayoth {
26d0f0064eSJayanth Othayoth 
27d0f0064eSJayanth Othayoth constexpr auto LOG_PATH = "/xyz/openbmc_project/logging";
28d0f0064eSJayanth Othayoth using Message = std::string;
29984a98f7SPatrick Williams using Attributes = std::variant<Message>;
30d0f0064eSJayanth Othayoth using AttributeName = std::string;
31d0f0064eSJayanth Othayoth using AttributeMap = std::map<AttributeName, Attributes>;
32d0f0064eSJayanth Othayoth using PropertyName = std::string;
33d0f0064eSJayanth Othayoth using PropertyMap = std::map<PropertyName, AttributeMap>;
34d0f0064eSJayanth Othayoth 
Watch(sdbusplus::bus_t & bus,Mgr & mgr)35e4350f93SDhruvaraj Subhashchandran Watch::Watch(sdbusplus::bus_t& bus, Mgr& mgr) :
36e4350f93SDhruvaraj Subhashchandran     mgr(mgr),
37cb65ffceSJayanth Othayoth     addMatch(bus,
382496482aSJayanth Othayoth              sdbusplus::bus::match::rules::interfacesAdded() +
39cb65ffceSJayanth Othayoth                  sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING),
40cb65ffceSJayanth Othayoth              std::bind(std::mem_fn(&Watch::addCallback), this,
41cb65ffceSJayanth Othayoth                        std::placeholders::_1)),
42cb65ffceSJayanth Othayoth     delMatch(bus,
432496482aSJayanth Othayoth              sdbusplus::bus::match::rules::interfacesRemoved() +
44cb65ffceSJayanth Othayoth                  sdbusplus::bus::match::rules::path_namespace(OBJ_LOGGING),
45cb65ffceSJayanth Othayoth              std::bind(std::mem_fn(&Watch::delCallback), this,
46cb65ffceSJayanth Othayoth                        std::placeholders::_1))
472496482aSJayanth Othayoth {
483fc6df48SJayanth Othayoth     std::filesystem::path file(ELOG_ID_PERSIST_PATH);
493fc6df48SJayanth Othayoth     if (std::filesystem::exists(file))
502496482aSJayanth Othayoth     {
512496482aSJayanth Othayoth         if (!deserialize(ELOG_ID_PERSIST_PATH, elogList))
522496482aSJayanth Othayoth         {
53d1f670feSDhruvaraj Subhashchandran             lg2::error("Error occurred during error id deserialize");
542496482aSJayanth Othayoth         }
552496482aSJayanth Othayoth     }
562496482aSJayanth Othayoth }
572496482aSJayanth Othayoth 
addCallback(sdbusplus::message_t & msg)589b18bf2dSPatrick Williams void Watch::addCallback(sdbusplus::message_t& msg)
59d0f0064eSJayanth Othayoth {
60d0f0064eSJayanth Othayoth     using QuotaExceeded =
61d0f0064eSJayanth Othayoth         sdbusplus::xyz::openbmc_project::Dump::Create::Error::QuotaExceeded;
62d0f0064eSJayanth Othayoth 
6390d147a1SWilliam A. Kennington III     sdbusplus::message::object_path objectPath;
6490d147a1SWilliam A. Kennington III     PropertyMap propertyMap;
6515cd3ce7SWilliam A. Kennington III     try
6615cd3ce7SWilliam A. Kennington III     {
6790d147a1SWilliam A. Kennington III         msg.read(objectPath, propertyMap);
6815cd3ce7SWilliam A. Kennington III     }
699b18bf2dSPatrick Williams     catch (const sdbusplus::exception_t& e)
7015cd3ce7SWilliam A. Kennington III     {
71d1f670feSDhruvaraj Subhashchandran         lg2::error("Failed to parse elog add signal, errormsg: {ERROR}, "
72d1f670feSDhruvaraj Subhashchandran                    "REPLY_SIG: {REPLY_SIG}",
73d1f670feSDhruvaraj Subhashchandran                    "ERROR", e, "REPLY_SIG", msg.get_signature());
7415cd3ce7SWilliam A. Kennington III         return;
7515cd3ce7SWilliam A. Kennington III     }
76d0f0064eSJayanth Othayoth 
7790d147a1SWilliam A. Kennington III     std::size_t found = objectPath.str.find("entry");
78d0f0064eSJayanth Othayoth     if (found == std::string::npos)
79d0f0064eSJayanth Othayoth     {
80d0f0064eSJayanth Othayoth         // Not a new error entry skip
81d0f0064eSJayanth Othayoth         return;
82d0f0064eSJayanth Othayoth     }
83d0f0064eSJayanth Othayoth 
842496482aSJayanth Othayoth     auto eId = getEid(objectPath);
852496482aSJayanth Othayoth 
862496482aSJayanth Othayoth     auto search = elogList.find(eId);
872496482aSJayanth Othayoth     if (search != elogList.end())
882496482aSJayanth Othayoth     {
892496482aSJayanth Othayoth         // elog exists in the list, Skip the dump
902496482aSJayanth Othayoth         return;
912496482aSJayanth Othayoth     }
922496482aSJayanth Othayoth 
9390d147a1SWilliam A. Kennington III     auto iter = propertyMap.find("xyz.openbmc_project.Logging.Entry");
9490d147a1SWilliam A. Kennington III     if (iter == propertyMap.end())
95d0f0064eSJayanth Othayoth     {
96d0f0064eSJayanth Othayoth         return;
97d0f0064eSJayanth Othayoth     }
98d0f0064eSJayanth Othayoth 
99d0f0064eSJayanth Othayoth     auto attr = iter->second.find("Message");
100d0f0064eSJayanth Othayoth     if (attr == iter->second.end())
101d0f0064eSJayanth Othayoth     {
102d0f0064eSJayanth Othayoth         return;
103d0f0064eSJayanth Othayoth     }
104d0f0064eSJayanth Othayoth 
10507f0f465SPatrick Williams     auto& data = std::get<PropertyName>(attr->second);
106d0f0064eSJayanth Othayoth     if (data.empty())
107d0f0064eSJayanth Othayoth     {
108d0f0064eSJayanth Othayoth         // No Message skip
109d0f0064eSJayanth Othayoth         return;
110d0f0064eSJayanth Othayoth     }
111d0f0064eSJayanth Othayoth 
112aa0937f9SDhruvaraj Subhashchandran     auto etype = findErrorType(data);
113aa0937f9SDhruvaraj Subhashchandran     if (!etype.has_value())
114d0f0064eSJayanth Othayoth     {
1150deb287cSMarri Devender Rao         // error not supported in the configuration
116d0f0064eSJayanth Othayoth         return;
117d0f0064eSJayanth Othayoth     }
118d0f0064eSJayanth Othayoth 
119aa0937f9SDhruvaraj Subhashchandran     auto errorType = etype.value();
120aa0937f9SDhruvaraj Subhashchandran 
121e4350f93SDhruvaraj Subhashchandran     DumpCreateParams params;
122e4350f93SDhruvaraj Subhashchandran     using DumpIntr = sdbusplus::common::xyz::openbmc_project::dump::Create;
123e4350f93SDhruvaraj Subhashchandran     using CreateParameters =
124e4350f93SDhruvaraj Subhashchandran         sdbusplus::common::xyz::openbmc_project::dump::Create::CreateParameters;
125e4350f93SDhruvaraj Subhashchandran     using DumpType =
126e4350f93SDhruvaraj Subhashchandran         sdbusplus::common::xyz::openbmc_project::dump::Create::DumpType;
127e4350f93SDhruvaraj Subhashchandran     params[DumpIntr::convertCreateParametersToString(
128e4350f93SDhruvaraj Subhashchandran         CreateParameters::FilePath)] = objectPath;
129e4350f93SDhruvaraj Subhashchandran     params[DumpIntr::convertCreateParametersToString(
130e4350f93SDhruvaraj Subhashchandran         CreateParameters::DumpType)] =
131e4350f93SDhruvaraj Subhashchandran         DumpIntr::convertDumpTypeToString(DumpType::ErrorLog);
132e4350f93SDhruvaraj Subhashchandran     params[DumpIntr::convertCreateParametersToString(
133e4350f93SDhruvaraj Subhashchandran         CreateParameters::ErrorType)] = errorType;
134d0f0064eSJayanth Othayoth     try
135d0f0064eSJayanth Othayoth     {
1362496482aSJayanth Othayoth         // Save the elog information. This is to avoid dump requests
1372496482aSJayanth Othayoth         // in elog restore path.
1382496482aSJayanth Othayoth         elogList.insert(eId);
1392496482aSJayanth Othayoth 
1402496482aSJayanth Othayoth         phosphor::dump::elog::serialize(elogList);
141e4350f93SDhruvaraj Subhashchandran         mgr.Mgr::createDump(params);
142d0f0064eSJayanth Othayoth     }
1439d2d7226SPatrick Williams     catch (const QuotaExceeded& e)
144d0f0064eSJayanth Othayoth     {
145d0f0064eSJayanth Othayoth         // No action now
146d0f0064eSJayanth Othayoth     }
147d0f0064eSJayanth Othayoth     return;
148d0f0064eSJayanth Othayoth }
149d0f0064eSJayanth Othayoth 
delCallback(sdbusplus::message_t & msg)1509b18bf2dSPatrick Williams void Watch::delCallback(sdbusplus::message_t& msg)
1512496482aSJayanth Othayoth {
15290d147a1SWilliam A. Kennington III     sdbusplus::message::object_path objectPath;
15315cd3ce7SWilliam A. Kennington III     try
15415cd3ce7SWilliam A. Kennington III     {
15590d147a1SWilliam A. Kennington III         msg.read(objectPath);
15615cd3ce7SWilliam A. Kennington III     }
1579b18bf2dSPatrick Williams     catch (const sdbusplus::exception_t& e)
15815cd3ce7SWilliam A. Kennington III     {
159d1f670feSDhruvaraj Subhashchandran         lg2::error("Failed to parse elog del signal, errormsg: {ERROR}, "
160d1f670feSDhruvaraj Subhashchandran                    "REPLY_SIG: {REPLY_SIG}",
161d1f670feSDhruvaraj Subhashchandran                    "ERROR", e, "REPLY_SIG", msg.get_signature());
16215cd3ce7SWilliam A. Kennington III         return;
16315cd3ce7SWilliam A. Kennington III     }
1642496482aSJayanth Othayoth 
165638b43f5SAndrew Geissler     std::size_t found = objectPath.str.find("entry");
166638b43f5SAndrew Geissler     if (found == std::string::npos)
167638b43f5SAndrew Geissler     {
168638b43f5SAndrew Geissler         // Not a error entry so skip
169638b43f5SAndrew Geissler         return;
170638b43f5SAndrew Geissler     }
171638b43f5SAndrew Geissler 
1722496482aSJayanth Othayoth     // Get elog id
1732496482aSJayanth Othayoth     auto eId = getEid(objectPath);
1742496482aSJayanth Othayoth 
1752496482aSJayanth Othayoth     // Delete the elog entry from the list and serialize
1762496482aSJayanth Othayoth     auto search = elogList.find(eId);
1772496482aSJayanth Othayoth     if (search != elogList.end())
1782496482aSJayanth Othayoth     {
1792496482aSJayanth Othayoth         elogList.erase(search);
1802496482aSJayanth Othayoth         phosphor::dump::elog::serialize(elogList);
1812496482aSJayanth Othayoth     }
1822496482aSJayanth Othayoth }
1832496482aSJayanth Othayoth 
184d0f0064eSJayanth Othayoth } // namespace elog
185d0f0064eSJayanth Othayoth } // namespace dump
186d0f0064eSJayanth Othayoth } // namespace phosphor
187