blob: 7cf3ae9ec3c6d3628b23304e5ad2830f66d767d7 [file] [log] [blame]
#pragma once
#include <config.h>
#include <common/utils.hpp>
#include <phosphor-logging/lg2.hpp>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <vector>
PHOSPHOR_LOG2_USING;
namespace pldm
{
namespace flightrecorder
{
using ReqOrResponse = bool;
using FlightRecorderData = std::vector<uint8_t>;
using FlightRecorderTimeStamp = std::string;
using FlightRecorderRecord =
std::tuple<FlightRecorderTimeStamp, ReqOrResponse, FlightRecorderData>;
using FlightRecorderCassette = std::vector<FlightRecorderRecord>;
static constexpr auto flightRecorderDumpPath = "/tmp/pldm_flight_recorder";
/** @class FlightRecorder
*
* The class for implementing the PLDM flight recorder logic. This class
* handles the insertion of the data into the recorder and also provides
* API's to dump the flight recorder into a file.
*/
class FlightRecorder
{
private:
FlightRecorder() : index(0)
{
flightRecorderPolicy = FLIGHT_RECORDER_MAX_ENTRIES ? true : false;
if (flightRecorderPolicy)
{
tapeRecorder = FlightRecorderCassette(FLIGHT_RECORDER_MAX_ENTRIES);
}
}
protected:
int index;
FlightRecorderCassette tapeRecorder;
bool flightRecorderPolicy;
public:
FlightRecorder(const FlightRecorder&) = delete;
FlightRecorder(FlightRecorder&&) = delete;
FlightRecorder& operator=(const FlightRecorder&) = delete;
FlightRecorder& operator=(FlightRecorder&&) = delete;
~FlightRecorder() = default;
static FlightRecorder& GetInstance()
{
static FlightRecorder flightRecorder;
return flightRecorder;
}
/** @brief Add records to the flightRecorder
*
* @param[in] buffer - The request/respose byte buffer
* @param[in] isRequest - bool that captures if it is a request message or
* a response message
*
* @return void
*/
void saveRecord(const FlightRecorderData& buffer, ReqOrResponse isRequest)
{
// if the flight recorder policy is enabled, then only insert the
// messages into the flight recorder, if not this function will be just
// a no-op
if (flightRecorderPolicy)
{
int currentIndex = index++;
tapeRecorder[currentIndex] = std::make_tuple(
pldm::utils::getCurrentSystemTime(), isRequest, buffer);
index =
(currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 : index;
}
}
/** @brief play flight recorder
*
* @return void
*/
void playRecorder()
{
if (flightRecorderPolicy)
{
std::ofstream recorderOutputFile(flightRecorderDumpPath);
info("Dumping the flight recorder into : {DUMP_PATH}", "DUMP_PATH",
flightRecorderDumpPath);
for (const auto& message : tapeRecorder)
{
recorderOutputFile << std::get<FlightRecorderTimeStamp>(message)
<< " : ";
if (std::get<ReqOrResponse>(message))
{
recorderOutputFile << "Tx : \n";
}
else
{
recorderOutputFile << "Rx : \n";
}
for (const auto& word : std::get<FlightRecorderData>(message))
{
recorderOutputFile << std::setfill('0') << std::setw(2)
<< std::hex << (unsigned)word << " ";
}
recorderOutputFile << std::endl;
}
recorderOutputFile.close();
}
else
{
error("Fight recorder policy is disabled");
}
}
};
} // namespace flightrecorder
} // namespace pldm