xref: /openbmc/phosphor-debug-collector/dump_entry.cpp (revision 93f064102cc060d913e7492f32d60757b6f100a4)
1224882b0SJayanth Othayoth #include "dump_entry.hpp"
2cb65ffceSJayanth Othayoth 
3a320c7caSJayanth Othayoth #include "dump_manager.hpp"
4a320c7caSJayanth Othayoth 
564f8da9eSDhruvaraj Subhashchandran #include <fcntl.h>
664f8da9eSDhruvaraj Subhashchandran 
7*93f06410SDhruvaraj Subhashchandran #include <nlohmann/json.hpp>
864f8da9eSDhruvaraj Subhashchandran #include <phosphor-logging/elog-errors.hpp>
964f8da9eSDhruvaraj Subhashchandran #include <phosphor-logging/elog.hpp>
1064f8da9eSDhruvaraj Subhashchandran #include <phosphor-logging/lg2.hpp>
1164f8da9eSDhruvaraj Subhashchandran #include <sdeventplus/event.hpp>
1264f8da9eSDhruvaraj Subhashchandran #include <sdeventplus/source/event.hpp>
1364f8da9eSDhruvaraj Subhashchandran #include <xyz/openbmc_project/Common/File/error.hpp>
1464f8da9eSDhruvaraj Subhashchandran #include <xyz/openbmc_project/Common/error.hpp>
1564f8da9eSDhruvaraj Subhashchandran 
1664f8da9eSDhruvaraj Subhashchandran #include <cstring>
1764f8da9eSDhruvaraj Subhashchandran 
18224882b0SJayanth Othayoth namespace phosphor
19224882b0SJayanth Othayoth {
20224882b0SJayanth Othayoth namespace dump
21224882b0SJayanth Othayoth {
22224882b0SJayanth Othayoth 
2364f8da9eSDhruvaraj Subhashchandran using namespace phosphor::logging;
2464f8da9eSDhruvaraj Subhashchandran 
delete_()25224882b0SJayanth Othayoth void Entry::delete_()
26224882b0SJayanth Othayoth {
27a320c7caSJayanth Othayoth     // Remove Dump entry D-bus object
28a320c7caSJayanth Othayoth     parent.erase(id);
29224882b0SJayanth Othayoth }
30224882b0SJayanth Othayoth 
getFileHandle()3164f8da9eSDhruvaraj Subhashchandran sdbusplus::message::unix_fd Entry::getFileHandle()
3264f8da9eSDhruvaraj Subhashchandran {
3364f8da9eSDhruvaraj Subhashchandran     using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
3464f8da9eSDhruvaraj Subhashchandran     using metadata = xyz::openbmc_project::Common::File::Open;
3564f8da9eSDhruvaraj Subhashchandran     if (file.empty())
3664f8da9eSDhruvaraj Subhashchandran     {
3764f8da9eSDhruvaraj Subhashchandran         lg2::error("Failed to get file handle: File path is empty.");
3864f8da9eSDhruvaraj Subhashchandran         elog<sdbusplus::xyz::openbmc_project::Common::Error::Unavailable>();
3964f8da9eSDhruvaraj Subhashchandran     }
4064f8da9eSDhruvaraj Subhashchandran 
4164f8da9eSDhruvaraj Subhashchandran     if (fdCloseEventSource)
4264f8da9eSDhruvaraj Subhashchandran     {
4364f8da9eSDhruvaraj Subhashchandran         // Return the existing file descriptor
4464f8da9eSDhruvaraj Subhashchandran         return fdCloseEventSource->first;
4564f8da9eSDhruvaraj Subhashchandran     }
4664f8da9eSDhruvaraj Subhashchandran 
4764f8da9eSDhruvaraj Subhashchandran     int fd = open(file.c_str(), O_RDONLY | O_NONBLOCK);
4864f8da9eSDhruvaraj Subhashchandran     if (fd == -1)
4964f8da9eSDhruvaraj Subhashchandran     {
5064f8da9eSDhruvaraj Subhashchandran         auto err = errno;
5164f8da9eSDhruvaraj Subhashchandran         lg2::error("Failed to open dump file: id: {ID} error: {ERRNO}", "ID",
5264f8da9eSDhruvaraj Subhashchandran                    id, "ERRNO", std::strerror(errno));
5364f8da9eSDhruvaraj Subhashchandran         elog<Open>(metadata::ERRNO(err), metadata::PATH(file.c_str()));
5464f8da9eSDhruvaraj Subhashchandran     }
5564f8da9eSDhruvaraj Subhashchandran 
5664f8da9eSDhruvaraj Subhashchandran     // Create a new Defer event source for closing this fd
5764f8da9eSDhruvaraj Subhashchandran     sdeventplus::Event event = sdeventplus::Event::get_default();
5864f8da9eSDhruvaraj Subhashchandran     auto eventSource = std::make_unique<sdeventplus::source::Defer>(
5964f8da9eSDhruvaraj Subhashchandran         event, [this](auto& /*source*/) { closeFD(); });
6064f8da9eSDhruvaraj Subhashchandran 
6164f8da9eSDhruvaraj Subhashchandran     // Store the file descriptor and event source in the optional pair
6264f8da9eSDhruvaraj Subhashchandran     fdCloseEventSource = std::make_pair(fd, std::move(eventSource));
6364f8da9eSDhruvaraj Subhashchandran 
6464f8da9eSDhruvaraj Subhashchandran     return fd;
6564f8da9eSDhruvaraj Subhashchandran }
6664f8da9eSDhruvaraj Subhashchandran 
serialize()67*93f06410SDhruvaraj Subhashchandran void Entry::serialize()
68*93f06410SDhruvaraj Subhashchandran {
69*93f06410SDhruvaraj Subhashchandran     // Folder for serialized entry
70*93f06410SDhruvaraj Subhashchandran     std::filesystem::path dir = file.parent_path() / PRESERVE;
71*93f06410SDhruvaraj Subhashchandran 
72*93f06410SDhruvaraj Subhashchandran     // Serialized entry file
73*93f06410SDhruvaraj Subhashchandran     std::filesystem::path serializePath = dir / SERIAL_FILE;
74*93f06410SDhruvaraj Subhashchandran     try
75*93f06410SDhruvaraj Subhashchandran     {
76*93f06410SDhruvaraj Subhashchandran         if (!std::filesystem::exists(dir))
77*93f06410SDhruvaraj Subhashchandran         {
78*93f06410SDhruvaraj Subhashchandran             std::filesystem::create_directories(dir);
79*93f06410SDhruvaraj Subhashchandran         }
80*93f06410SDhruvaraj Subhashchandran 
81*93f06410SDhruvaraj Subhashchandran         std::ofstream os(serializePath, std::ios::binary);
82*93f06410SDhruvaraj Subhashchandran         if (!os.is_open())
83*93f06410SDhruvaraj Subhashchandran         {
84*93f06410SDhruvaraj Subhashchandran             lg2::error("Failed to open file for serialization: {PATH} ", "PATH",
85*93f06410SDhruvaraj Subhashchandran                        serializePath);
86*93f06410SDhruvaraj Subhashchandran             return;
87*93f06410SDhruvaraj Subhashchandran         }
88*93f06410SDhruvaraj Subhashchandran         nlohmann::json j;
89*93f06410SDhruvaraj Subhashchandran         j["version"] = CLASS_SERIALIZATION_VERSION;
90*93f06410SDhruvaraj Subhashchandran         j["dumpId"] = id;
91*93f06410SDhruvaraj Subhashchandran         j["originatorId"] = originatorId();
92*93f06410SDhruvaraj Subhashchandran         j["originatorType"] = originatorType();
93*93f06410SDhruvaraj Subhashchandran         j["startTime"] = startTime();
94*93f06410SDhruvaraj Subhashchandran 
95*93f06410SDhruvaraj Subhashchandran         os << j.dump();
96*93f06410SDhruvaraj Subhashchandran     }
97*93f06410SDhruvaraj Subhashchandran     catch (const std::exception& e)
98*93f06410SDhruvaraj Subhashchandran     {
99*93f06410SDhruvaraj Subhashchandran         lg2::error("Serialization error: {PATH} {ERROR} ", "PATH",
100*93f06410SDhruvaraj Subhashchandran                    serializePath, "ERROR", e);
101*93f06410SDhruvaraj Subhashchandran 
102*93f06410SDhruvaraj Subhashchandran         // Remove the serialization folder if that got created
103*93f06410SDhruvaraj Subhashchandran         // Ignore the error since folder may not be created
104*93f06410SDhruvaraj Subhashchandran         std::error_code ec;
105*93f06410SDhruvaraj Subhashchandran         std::filesystem::remove_all(dir, ec);
106*93f06410SDhruvaraj Subhashchandran     }
107*93f06410SDhruvaraj Subhashchandran }
108*93f06410SDhruvaraj Subhashchandran 
deserialize(const std::filesystem::path & dumpPath)109*93f06410SDhruvaraj Subhashchandran void Entry::deserialize(const std::filesystem::path& dumpPath)
110*93f06410SDhruvaraj Subhashchandran {
111*93f06410SDhruvaraj Subhashchandran     try
112*93f06410SDhruvaraj Subhashchandran     {
113*93f06410SDhruvaraj Subhashchandran         // .preserve folder
114*93f06410SDhruvaraj Subhashchandran         std::filesystem::path dir = dumpPath / PRESERVE;
115*93f06410SDhruvaraj Subhashchandran         if (!std::filesystem::exists(dir))
116*93f06410SDhruvaraj Subhashchandran         {
117*93f06410SDhruvaraj Subhashchandran             lg2::info("Serialization directory: {SERIAL_DIR} doesnt exist, "
118*93f06410SDhruvaraj Subhashchandran                       "skip deserialization",
119*93f06410SDhruvaraj Subhashchandran                       "SERIAL_DIR", dir);
120*93f06410SDhruvaraj Subhashchandran             return;
121*93f06410SDhruvaraj Subhashchandran         }
122*93f06410SDhruvaraj Subhashchandran 
123*93f06410SDhruvaraj Subhashchandran         // Serialized entry
124*93f06410SDhruvaraj Subhashchandran         std::filesystem::path serializePath = dir / SERIAL_FILE;
125*93f06410SDhruvaraj Subhashchandran         std::ifstream is(serializePath, std::ios::binary);
126*93f06410SDhruvaraj Subhashchandran         if (!is.is_open())
127*93f06410SDhruvaraj Subhashchandran         {
128*93f06410SDhruvaraj Subhashchandran             lg2::error("Failed to open file for deserialization: {PATH}",
129*93f06410SDhruvaraj Subhashchandran                        "PATH", serializePath);
130*93f06410SDhruvaraj Subhashchandran             return;
131*93f06410SDhruvaraj Subhashchandran         }
132*93f06410SDhruvaraj Subhashchandran         nlohmann::json j;
133*93f06410SDhruvaraj Subhashchandran         is >> j;
134*93f06410SDhruvaraj Subhashchandran 
135*93f06410SDhruvaraj Subhashchandran         uint32_t version;
136*93f06410SDhruvaraj Subhashchandran         j.at("version").get_to(version);
137*93f06410SDhruvaraj Subhashchandran         if (version == CLASS_SERIALIZATION_VERSION)
138*93f06410SDhruvaraj Subhashchandran         {
139*93f06410SDhruvaraj Subhashchandran             uint32_t storedId;
140*93f06410SDhruvaraj Subhashchandran             j.at("dumpId").get_to(storedId);
141*93f06410SDhruvaraj Subhashchandran             if (storedId == id)
142*93f06410SDhruvaraj Subhashchandran             {
143*93f06410SDhruvaraj Subhashchandran                 originatorId(j["originatorId"].get<std::string>());
144*93f06410SDhruvaraj Subhashchandran                 originatorType(j["originatorType"].get<originatorTypes>());
145*93f06410SDhruvaraj Subhashchandran                 startTime(j["startTime"].get<uint64_t>());
146*93f06410SDhruvaraj Subhashchandran             }
147*93f06410SDhruvaraj Subhashchandran             else
148*93f06410SDhruvaraj Subhashchandran             {
149*93f06410SDhruvaraj Subhashchandran                 lg2::error("The id ({ID_IN_FILE}) is not matching the dump id "
150*93f06410SDhruvaraj Subhashchandran                            "({DUMPID}); skipping deserialization.",
151*93f06410SDhruvaraj Subhashchandran                            "ID_IN_FILE", storedId, "DUMPID", id);
152*93f06410SDhruvaraj Subhashchandran 
153*93f06410SDhruvaraj Subhashchandran                 // Id is not matching, this could be due to file corruption
154*93f06410SDhruvaraj Subhashchandran                 // deleting the .preserve folder.
155*93f06410SDhruvaraj Subhashchandran                 // Attempt to delete the folder and ignore any error.
156*93f06410SDhruvaraj Subhashchandran                 std::error_code ec;
157*93f06410SDhruvaraj Subhashchandran                 std::filesystem::remove_all(dir, ec);
158*93f06410SDhruvaraj Subhashchandran             }
159*93f06410SDhruvaraj Subhashchandran         }
160*93f06410SDhruvaraj Subhashchandran         else
161*93f06410SDhruvaraj Subhashchandran         {
162*93f06410SDhruvaraj Subhashchandran             lg2::error("The serialized file version and current class version"
163*93f06410SDhruvaraj Subhashchandran                        "doesnt match, skip deserialization {VERSION}",
164*93f06410SDhruvaraj Subhashchandran                        "VERSION", version);
165*93f06410SDhruvaraj Subhashchandran         }
166*93f06410SDhruvaraj Subhashchandran     }
167*93f06410SDhruvaraj Subhashchandran     catch (const std::exception& e)
168*93f06410SDhruvaraj Subhashchandran     {
169*93f06410SDhruvaraj Subhashchandran         lg2::error("Deserialization error: {PATH}, {ERROR}", "PATH", dumpPath,
170*93f06410SDhruvaraj Subhashchandran                    "ERROR", e);
171*93f06410SDhruvaraj Subhashchandran     }
172*93f06410SDhruvaraj Subhashchandran }
173*93f06410SDhruvaraj Subhashchandran 
174224882b0SJayanth Othayoth } // namespace dump
175cb65ffceSJayanth Othayoth } // namespace phosphor
176