| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ---------------------------------------------------------------------- | ||
| 2 | // | ||
| 3 | // ComLogger.cpp | ||
| 4 | // | ||
| 5 | // ---------------------------------------------------------------------- | ||
| 6 | |||
| 7 | #include <Fw/FPrimeBasicTypes.hpp> | ||
| 8 | #include <Fw/Types/SerialBuffer.hpp> | ||
| 9 | #include <Fw/Types/StringUtils.hpp> | ||
| 10 | #include <Os/ValidateFile.hpp> | ||
| 11 | #include <Svc/ComLogger/ComLogger.hpp> | ||
| 12 | #include <cstdio> | ||
| 13 | |||
| 14 | namespace Svc { | ||
| 15 | static_assert(std::numeric_limits<U16>::max() <= std::numeric_limits<FwSizeType>::max(), | ||
| 16 | "U16 must fit in the positive range of FwSizeType"); | ||
| 17 | // ---------------------------------------------------------------------- | ||
| 18 | // Construction, initialization, and destruction | ||
| 19 | // ---------------------------------------------------------------------- | ||
| 20 | |||
| 21 | 5 | ComLogger ::ComLogger(const char* compName, const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength) | |
| 22 | : ComLoggerComponentBase(compName), | ||
| 23 | 5 | m_maxFileSize(maxFileSize), | |
| 24 | 5 | m_fileMode(CLOSED), | |
| 25 | 5 | m_byteCount(0), | |
| 26 | 5 | m_writeErrorOccurred(false), | |
| 27 | 5 | m_openErrorOccurred(false), | |
| 28 | 5 | m_storeBufferLength(storeBufferLength), | |
| 29 |
4/4✓ Branch 9 taken 5 times.
✓ Branch 15 taken 5 times.
✓ Branch 21 taken 5 times.
✓ Branch 27 taken 5 times.
|
15 | m_initialized(true) { |
| 30 |
1/1✓ Branch 4 taken 5 times.
|
5 | this->init_log_file(incomingFilePrefix, maxFileSize, storeBufferLength); |
| 31 | 5 | } | |
| 32 | |||
| 33 | 2 | ComLogger ::ComLogger(const char* compName) | |
| 34 | : ComLoggerComponentBase(compName), | ||
| 35 |
1/1✓ Branch 4 taken 2 times.
|
2 | m_filePrefix(), |
| 36 | 2 | m_maxFileSize(0), | |
| 37 | 2 | m_fileMode(CLOSED), | |
| 38 |
1/1✓ Branch 5 taken 2 times.
|
2 | m_fileName(), |
| 39 |
1/1✓ Branch 5 taken 2 times.
|
2 | m_hashFileName(), |
| 40 | 2 | m_byteCount(0), | |
| 41 | 2 | m_writeErrorOccurred(false), | |
| 42 | 2 | m_openErrorOccurred(false), | |
| 43 | 2 | m_storeBufferLength(), | |
| 44 |
1/1✓ Branch 10 taken 2 times.
|
6 | m_initialized(false) {} |
| 45 | |||
| 46 | 7 | void ComLogger ::init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength) { | |
| 47 | 7 | FW_ASSERT(incomingFilePrefix != nullptr); | |
| 48 | 7 | this->m_maxFileSize = maxFileSize; | |
| 49 | 7 | this->m_storeBufferLength = storeBufferLength; | |
| 50 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
|
7 | if (this->m_storeBufferLength) { |
| 51 | 7 | FW_ASSERT(maxFileSize > sizeof(U16), static_cast<FwAssertArgType>(maxFileSize)); | |
| 52 | } | ||
| 53 | // Assign the prefix checking if it is too big | ||
| 54 | 7 | Fw::FormatStatus formatStatus = this->m_filePrefix.format("%s", incomingFilePrefix); | |
| 55 | 7 | FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS); | |
| 56 | 7 | this->m_initialized = true; | |
| 57 | 7 | } | |
| 58 | |||
| 59 | 70 | ComLogger ::~ComLogger() { | |
| 60 | // Close file: | ||
| 61 | // this->closeFile(); | ||
| 62 | // NOTE: the above did not work because we don't want to issue an event | ||
| 63 | // in the destructor. This can cause "virtual method called" segmentation | ||
| 64 | // faults. | ||
| 65 | // So I am copying part of that function here. | ||
| 66 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 2 times.
|
14 | if (OPEN == this->m_fileMode) { |
| 67 | // Close file: | ||
| 68 | 10 | this->m_file.close(); | |
| 69 | |||
| 70 | // Write out the hash file to disk: | ||
| 71 | 10 | this->writeHashFile(); | |
| 72 | |||
| 73 | // Update mode: | ||
| 74 | 10 | this->m_fileMode = CLOSED; | |
| 75 | } | ||
| 76 | 56 | } | |
| 77 | |||
| 78 | // ---------------------------------------------------------------------- | ||
| 79 | // Handler implementations | ||
| 80 | // ---------------------------------------------------------------------- | ||
| 81 | |||
| 82 | 71 | void ComLogger ::comIn_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) { | |
| 83 | 71 | FW_ASSERT(portNum == 0); | |
| 84 | |||
| 85 | // Get length of buffer: | ||
| 86 | 71 | FwSizeType sizeNative = data.getSize(); | |
| 87 | // ComLogger only writes 16-bit sizes to save space | ||
| 88 | // on disk: | ||
| 89 | 71 | FW_ASSERT(sizeNative < 65536, static_cast<FwAssertArgType>(sizeNative)); | |
| 90 | 71 | U16 size = sizeNative & 0xFFFF; | |
| 91 | |||
| 92 | // Close the file if it will be too big: | ||
| 93 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 57 times.
✓ Branch 6 taken 14 times.
|
71 | if (OPEN == this->m_fileMode) { |
| 94 | 57 | U32 projectedByteCount = this->m_byteCount + size; | |
| 95 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✓ Branch 5 taken 43 times.
✓ Branch 6 taken 14 times.
|
57 | if (this->m_storeBufferLength) { |
| 96 | 43 | projectedByteCount += static_cast<U32>(sizeof(size)); | |
| 97 | } | ||
| 98 |
2/2✓ Branch 4 taken 6 times.
✓ Branch 5 taken 51 times.
|
57 | if (projectedByteCount > this->m_maxFileSize) { |
| 99 | 6 | this->closeFile(); | |
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | // Open the file if it there is not one open: | ||
| 104 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 51 times.
|
71 | if (CLOSED == this->m_fileMode) { |
| 105 | 20 | this->openFile(); | |
| 106 | } | ||
| 107 | |||
| 108 | // Write to the file if it is open: | ||
| 109 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 64 times.
✓ Branch 6 taken 7 times.
|
71 | if (OPEN == this->m_fileMode) { |
| 110 | 64 | this->writeComBufferToFile(data, size); | |
| 111 | } | ||
| 112 | 71 | } | |
| 113 | |||
| 114 | 6 | void ComLogger ::CloseFile_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { | |
| 115 | 6 | this->closeFile(); | |
| 116 |
2/2✓ Branch 6 taken 6 times.
✓ Branch 9 taken 6 times.
|
6 | this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); |
| 117 | 6 | } | |
| 118 | |||
| 119 | ✗ | void ComLogger ::pingIn_handler(const FwIndexType portNum, U32 key) { | |
| 120 | // return key | ||
| 121 | ✗ | this->pingOut_out(0, key); | |
| 122 | ✗ | } | |
| 123 | |||
| 124 | 21 | void ComLogger ::openFile() { | |
| 125 | 21 | FW_ASSERT(CLOSED == this->m_fileMode); | |
| 126 | |||
| 127 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 20 times.
|
21 | if (!this->m_initialized) { |
| 128 |
1/1✓ Branch 5 taken 1 times.
|
1 | this->log_WARNING_LO_FileNotInitialized(); |
| 129 | 1 | return; | |
| 130 | } | ||
| 131 | |||
| 132 | // Create filename: | ||
| 133 |
1/1✓ Branch 3 taken 20 times.
|
20 | Fw::Time timestamp = getTime(); |
| 134 |
3/3✓ Branch 6 taken 20 times.
✓ Branch 9 taken 20 times.
✓ Branch 13 taken 20 times.
|
80 | Fw::FormatStatus formatStatus = this->m_fileName.format( |
| 135 | 20 | "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com", this->m_filePrefix.toChar(), | |
| 136 |
1/1✓ Branch 4 taken 20 times.
|
80 | static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds()); |
| 137 | 20 | FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS); | |
| 138 | formatStatus = | ||
| 139 |
2/2✓ Branch 6 taken 20 times.
✓ Branch 15 taken 20 times.
|
20 | this->m_hashFileName.format("%s%s", this->m_fileName.toChar(), Utils::Hash::getFileExtensionString()); |
| 140 | 20 | FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS); | |
| 141 | |||
| 142 |
1/1✓ Branch 12 taken 20 times.
|
20 | Os::File::Status ret = m_file.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE); |
| 143 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
|
20 | if (Os::File::OP_OK != ret) { |
| 144 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
|
6 | if (!this->m_openErrorOccurred) { // throttle this event, otherwise a positive |
| 145 | // feedback event loop can occur! | ||
| 146 |
1/1✓ Branch 8 taken 2 times.
|
2 | this->log_WARNING_HI_FileOpenError(ret, this->m_fileName); |
| 147 | } | ||
| 148 | 6 | this->m_openErrorOccurred = true; | |
| 149 | } else { | ||
| 150 | // Reset event throttle: | ||
| 151 | 14 | this->m_openErrorOccurred = false; | |
| 152 | |||
| 153 | // Reset byte count: | ||
| 154 | 14 | this->m_byteCount = 0; | |
| 155 | |||
| 156 | // Set mode: | ||
| 157 | 14 | this->m_fileMode = OPEN; | |
| 158 | } | ||
| 159 | 20 | } | |
| 160 | |||
| 161 | 13 | void ComLogger ::closeFile() { | |
| 162 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 5 times.
|
13 | if (OPEN == this->m_fileMode) { |
| 163 | // Close file: | ||
| 164 | 8 | this->m_file.close(); | |
| 165 | |||
| 166 | // Write out the hash file to disk: | ||
| 167 | 8 | this->writeHashFile(); | |
| 168 | |||
| 169 | // Update mode: | ||
| 170 | 8 | this->m_fileMode = CLOSED; | |
| 171 | |||
| 172 | // Send event: | ||
| 173 | 8 | this->log_DIAGNOSTIC_FileClosed(this->m_fileName); | |
| 174 | } | ||
| 175 | 13 | } | |
| 176 | |||
| 177 | 64 | void ComLogger ::writeComBufferToFile(Fw::ComBuffer& data, U16 size) { | |
| 178 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 49 times.
✓ Branch 6 taken 15 times.
|
64 | if (this->m_storeBufferLength) { |
| 179 | 49 | U8 buffer[sizeof(size)]; | |
| 180 |
1/1✓ Branch 2 taken 49 times.
|
49 | Fw::SerialBuffer serialLength(&buffer[0], sizeof(size)); |
| 181 |
1/1✓ Branch 2 taken 49 times.
|
49 | Fw::SerializeStatus serStatus = serialLength.serializeFrom(size); |
| 182 | 49 | FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus); | |
| 183 | const bool lengthWritten = | ||
| 184 |
2/2✓ Branch 5 taken 49 times.
✓ Branch 10 taken 49 times.
|
49 | this->writeToFile(serialLength.getBuffAddr(), static_cast<U16>(serialLength.getSize())); |
| 185 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
|
49 | if (lengthWritten) { |
| 186 |
1/1✓ Branch 2 taken 43 times.
|
43 | this->m_byteCount += static_cast<U32>(serialLength.getSize()); |
| 187 | } else { | ||
| 188 | 6 | return; | |
| 189 | } | ||
| 190 | 49 | } | |
| 191 | |||
| 192 | // Write buffer to file: | ||
| 193 | 58 | const bool dataWritten = this->writeToFile(data.getBuffAddr(), size); | |
| 194 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (dataWritten) { |
| 195 | 58 | this->m_byteCount += size; | |
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | 107 | bool ComLogger ::writeToFile(void* data, U16 length) { | |
| 200 | 107 | FwSizeType size = length; | |
| 201 |
1/1✓ Branch 6 taken 107 times.
|
107 | Os::File::Status ret = m_file.write(reinterpret_cast<const U8*>(data), size); |
| 202 |
3/4✓ Branch 0 taken 101 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 101 times.
|
107 | if ((Os::File::OP_OK != ret) || (size != length)) { |
| 203 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
|
6 | if (!this->m_writeErrorOccurred) { // throttle this event, otherwise a positive |
| 204 | // feedback event loop can occur! | ||
| 205 |
1/1✓ Branch 8 taken 2 times.
|
2 | this->log_WARNING_HI_FileWriteError(ret, static_cast<U32>(size), length, this->m_fileName); |
| 206 | } | ||
| 207 | 6 | this->m_writeErrorOccurred = true; | |
| 208 | 6 | return false; | |
| 209 | } | ||
| 210 | |||
| 211 | 101 | this->m_writeErrorOccurred = false; | |
| 212 | 101 | return true; | |
| 213 | } | ||
| 214 | |||
| 215 | 13 | void ComLogger ::writeHashFile() { | |
| 216 | Os::ValidateFile::Status validateStatus; | ||
| 217 | 13 | validateStatus = Os::ValidateFile::createValidation(this->m_fileName.toChar(), this->m_hashFileName.toChar()); | |
| 218 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
|
13 | if (Os::ValidateFile::VALIDATION_OK != validateStatus) { |
| 219 | 5 | this->log_WARNING_LO_FileValidationError(this->m_hashFileName, this->m_fileName, validateStatus); | |
| 220 | } | ||
| 221 | 13 | } | |
| 222 | } // namespace Svc | ||
| 223 |