1 #pragma once 2 3 #include <config.h> 4 5 #include <common/utils.hpp> 6 7 #include <fstream> 8 #include <iomanip> 9 #include <iostream> 10 #include <vector> 11 namespace pldm 12 { 13 namespace flightrecorder 14 { 15 16 using ReqOrResponse = bool; 17 using FlightRecorderData = std::vector<uint8_t>; 18 using FlightRecorderTimeStamp = std::string; 19 using FlightRecorderRecord = 20 std::tuple<FlightRecorderTimeStamp, ReqOrResponse, FlightRecorderData>; 21 using FlightRecorderCassette = std::vector<FlightRecorderRecord>; 22 static constexpr auto flightRecorderDumpPath = "/tmp/pldm_flight_recorder"; 23 24 /** @class FlightRecorder 25 * 26 * The class for implementing the PLDM flight recorder logic. This class 27 * handles the insertion of the data into the recorder and also provides 28 * API's to dump the flight recorder into a file. 29 */ 30 31 class FlightRecorder 32 { 33 private: 34 FlightRecorder() : index(0) 35 { 36 37 flightRecorderPolicy = FLIGHT_RECORDER_MAX_ENTRIES ? true : false; 38 if (flightRecorderPolicy) 39 { 40 tapeRecorder = FlightRecorderCassette(FLIGHT_RECORDER_MAX_ENTRIES); 41 } 42 } 43 44 protected: 45 int index; 46 FlightRecorderCassette tapeRecorder; 47 bool flightRecorderPolicy; 48 49 public: 50 FlightRecorder(const FlightRecorder&) = delete; 51 FlightRecorder(FlightRecorder&&) = delete; 52 FlightRecorder& operator=(const FlightRecorder&) = delete; 53 FlightRecorder& operator=(FlightRecorder&&) = delete; 54 ~FlightRecorder() = default; 55 56 static FlightRecorder& GetInstance() 57 { 58 static FlightRecorder flightRecorder; 59 return flightRecorder; 60 } 61 62 /** @brief Add records to the flightRecorder 63 * 64 * @param[in] buffer - The request/respose byte buffer 65 * @param[in] isRequest - bool that captures if it is a request message or 66 * a response message 67 * 68 * @return void 69 */ 70 void saveRecord(const FlightRecorderData& buffer, ReqOrResponse isRequest) 71 { 72 // if the flight recorder policy is enabled, then only insert the 73 // messages into the flight recorder, if not this function will be just 74 // a no-op 75 if (flightRecorderPolicy) 76 { 77 int currentIndex = index++; 78 tapeRecorder[currentIndex] = std::make_tuple( 79 pldm::utils::getCurrentSystemTime(), isRequest, buffer); 80 index = 81 (currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 : index; 82 } 83 } 84 85 /** @brief play flight recorder 86 * 87 * @return void 88 */ 89 90 void playRecorder() 91 { 92 if (flightRecorderPolicy) 93 { 94 std::ofstream recorderOutputFile(flightRecorderDumpPath); 95 std::cout << "Dumping the flight recorder into : " 96 << flightRecorderDumpPath << "\n"; 97 98 for (const auto& message : tapeRecorder) 99 { 100 recorderOutputFile << std::get<FlightRecorderTimeStamp>(message) 101 << " : "; 102 if (std::get<ReqOrResponse>(message)) 103 { 104 recorderOutputFile << "Tx : \n"; 105 } 106 else 107 { 108 recorderOutputFile << "Rx : \n"; 109 } 110 for (const auto& word : std::get<FlightRecorderData>(message)) 111 { 112 recorderOutputFile << std::setfill('0') << std::setw(2) 113 << std::hex << (unsigned)word << " "; 114 } 115 recorderOutputFile << std::endl; 116 } 117 recorderOutputFile.close(); 118 } 119 else 120 { 121 std::cerr << "Fight recorder policy is disabled\n"; 122 } 123 } 124 }; 125 126 } // namespace flightrecorder 127 } // namespace pldm 128