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