#pragma once #include "config.h" #include "file.hpp" #include "occ_errors.hpp" #include #include #include using FFDCFormat = sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat; using FFDCFiles = std::vector< std::tuple>; namespace open_power { namespace occ { /** @class FFDCFile * @brief Represents a single file that will get opened when created and * deleted when the object is destructed */ class FFDCFile { public: FFDCFile() = delete; FFDCFile(const FFDCFile&) = delete; FFDCFile& operator=(const FFDCFile&) = delete; FFDCFile(FFDCFile&&) = delete; FFDCFile& operator=(FFDCFile&&) = delete; /** * @brief Constructor * * Opens the file and saves the descriptor * * @param[in] name - The filename */ explicit FFDCFile(const std::filesystem::path& name); /** * @brief Destructor - Deletes the file */ ~FFDCFile() { std::filesystem::remove(_name); } /** * @brief Returns the file descriptor * * @return int - The descriptor */ int fd() { return _fd(); } private: /** * @brief The file descriptor holder */ FileDescriptor _fd; /** * @brief The filename */ const std::filesystem::path _name; }; /** @class FFDC * @brief Monitors for SBE FFDC availability */ class FFDC : public Error { public: FFDC() = delete; FFDC(const FFDC&) = delete; FFDC& operator=(const FFDC&) = delete; FFDC(FFDC&&) = default; FFDC& operator=(FFDC&&) = default; /** @brief Constructs the FFDC object * * @param[in] event - reference to sd_event unique_ptr * @param[in] file - File used by driver to communicate FFDC data * @param[in] instance - OCC instance number */ FFDC(EventPtr& event, const fs::path& file, unsigned int instance) : Error(event, file, nullptr), instance(instance) { // Nothing to do here. } ~FFDC() { for (auto&& it : temporaryFiles) { close(it.second); fs::remove(it.first); } } /** @brief Helper function to create a PEL with the OpenPower DBus * interface * * @param[in] path - the DBus error path * @param[in] src6 - the SBE error SRC6 word * @param[in] msg - the error message * @param[in] fd - the file descriptor for any FFDC */ static uint32_t createPEL(const char* path, uint32_t src6, const char* msg, int fd = -1); /** @brief Helper function to create a PEL for the OCC reset with the * OpenPower DBus interface * * @param[in] instance - the OCC instance id * @param[in] path - the DBus error path * @param[in] err - the error return code * @param[in] callout - the PEL callout path */ static void createOCCResetPEL(unsigned int instance, const char* path, int err, const char* callout); /** * @brief Create a file containing the latest journal traces for the * specified executable and add it to the file list. * * @param[in] fileList - where to add the new file * @param[in] executable - name of app to collect * @param[in] lines - number of journal lines to save * * @return std::unique_ptr - The file object */ static std::unique_ptr addJournalEntries(FFDCFiles& fileList, const std::string& executable, unsigned int lines); private: /** @brief OCC instance number. Ex, 0,1, etc */ unsigned int instance; /** @brief Stores the temporary files and file descriptors * in usage. They will be cleaned up when the class * is destroyed (when the application exits). */ std::vector> temporaryFiles; /** @brief When the error event is received, analyzes it * and makes a callback to error handler if the * content denotes an error condition */ void analyzeEvent() override; /** * @brief Returns an FFDCFile containing the JSON data * * @param[in] ffdcData - The JSON data to write to a file * * @return std::unique_ptr - The file object */ static std::unique_ptr makeJsonFFDCFile(const nlohmann::json& ffdcData); /** * @brief Returns a JSON structure containing the previous N journal * entries. * * @param[in] numLines - Number of lines of journal to retrieve * @param[in] executable - name of app to collect for * * @return JSON object that was created */ static nlohmann::json getJournalEntries(int numLines, std::string executable); /** * @brief Gets the realtime (wallclock) timestamp for the current journal * entry. * * @param journal current journal entry * @return timestamp as a date/time string */ static std::string getTimeStamp(sd_journal* journal); /** * @brief Gets the value of the specified field for the current journal * entry. * * Returns an empty string if the current journal entry does not have the * specified field. * * @param journal current journal entry * @param field journal field name * @return field value */ static std::string getFieldValue(sd_journal* journal, const std::string& field); }; /** * @class JournalCloser * @brief Automatically closes the journal when the object goes out of scope. */ class JournalCloser { public: // Specify which compiler-generated methods we want JournalCloser() = delete; JournalCloser(const JournalCloser&) = delete; JournalCloser(JournalCloser&&) = delete; JournalCloser& operator=(const JournalCloser&) = delete; JournalCloser& operator=(JournalCloser&&) = delete; JournalCloser(sd_journal* journal) : journal{journal} {} ~JournalCloser() { sd_journal_close(journal); } private: sd_journal* journal{nullptr}; }; } // namespace occ } // namespace open_power