| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title DpWriter.cpp | ||
| 3 | // \author bocchino | ||
| 4 | // \brief cpp file for DpWriter component implementation class | ||
| 5 | // ====================================================================== | ||
| 6 | |||
| 7 | #include "Svc/DpWriter/DpWriter.hpp" | ||
| 8 | #include "Fw/Com/ComPacket.hpp" | ||
| 9 | #include "Fw/FPrimeBasicTypes.hpp" | ||
| 10 | #include "Fw/Types/FileNameString.hpp" | ||
| 11 | #include "Fw/Types/Serializable.hpp" | ||
| 12 | #include "Os/File.hpp" | ||
| 13 | #include "Utils/Hash/Hash.hpp" | ||
| 14 | #include "config/DpCfg.hpp" | ||
| 15 | |||
| 16 | namespace Svc { | ||
| 17 | |||
| 18 | // ---------------------------------------------------------------------- | ||
| 19 | // Construction, initialization, and destruction | ||
| 20 | // ---------------------------------------------------------------------- | ||
| 21 | |||
| 22 |
1/1✓ Branch 31 taken 21 times.
|
21 | DpWriter::DpWriter(const char* const compName) : DpWriterComponentBase(compName), m_dpFileNamePrefix() {} |
| 23 | |||
| 24 | 42 | DpWriter::~DpWriter() {} | |
| 25 | |||
| 26 | 1 | void DpWriter::configure(const Fw::ConstStringBase& dpFileNamePrefix) { | |
| 27 | 1 | this->m_dpFileNamePrefix = dpFileNamePrefix; | |
| 28 | 1 | } | |
| 29 | |||
| 30 | // ---------------------------------------------------------------------- | ||
| 31 | // Handler implementations for user-defined typed input ports | ||
| 32 | // ---------------------------------------------------------------------- | ||
| 33 | |||
| 34 | 6027 | void DpWriter::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) { | |
| 35 | 6027 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 36 | // portNum is unused | ||
| 37 | (void)portNum; | ||
| 38 | // Update num buffers received | ||
| 39 | 6027 | ++this->m_numBuffersReceived; | |
| 40 | // Check that the buffer is valid | ||
| 41 |
3/3✓ Branch 4 taken 6027 times.
✓ Branch 6 taken 1016 times.
✓ Branch 7 taken 5011 times.
|
6027 | if (!buffer.isValid()) { |
| 42 |
1/1✓ Branch 5 taken 1016 times.
|
1016 | this->log_WARNING_HI_InvalidBuffer(); |
| 43 | 1016 | status = Fw::Success::FAILURE; | |
| 44 | } | ||
| 45 | // Check that the buffer is large enough to hold a data product packet | ||
| 46 |
1/1✓ Branch 4 taken 6027 times.
|
6027 | const FwSizeType bufferSize = buffer.getSize(); |
| 47 |
2/2✓ Branch 0 taken 5011 times.
✓ Branch 1 taken 1016 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 48 |
2/2✓ Branch 0 taken 941 times.
✓ Branch 1 taken 4070 times.
|
5011 | if (bufferSize < Fw::DpContainer::MIN_PACKET_SIZE) { |
| 49 |
1/1✓ Branch 5 taken 941 times.
|
941 | this->log_WARNING_HI_BufferTooSmallForPacket(static_cast<U32>(bufferSize), |
| 50 | Fw::DpContainer::MIN_PACKET_SIZE); | ||
| 51 | |||
| 52 | 941 | status = Fw::Success::FAILURE; | |
| 53 | } | ||
| 54 | } | ||
| 55 | // Set up the container and check that the header hash is valid | ||
| 56 |
1/1✓ Branch 2 taken 6027 times.
|
6027 | Fw::DpContainer container; |
| 57 |
2/2✓ Branch 0 taken 4070 times.
✓ Branch 1 taken 1957 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 58 |
1/1✓ Branch 3 taken 4070 times.
|
4070 | container.setBuffer(buffer); |
| 59 |
1/1✓ Branch 2 taken 4070 times.
|
4070 | Utils::HashBuffer storedHash; |
| 60 |
1/1✓ Branch 2 taken 4070 times.
|
4070 | Utils::HashBuffer computedHash; |
| 61 |
1/1✓ Branch 2 taken 4070 times.
|
4070 | status = container.checkHeaderHash(storedHash, computedHash); |
| 62 |
2/2✓ Branch 0 taken 908 times.
✓ Branch 1 taken 3162 times.
|
4070 | if (status != Fw::Success::SUCCESS) { |
| 63 |
3/3✓ Branch 5 taken 908 times.
✓ Branch 9 taken 908 times.
✓ Branch 12 taken 908 times.
|
1816 | this->log_WARNING_HI_InvalidHeaderHash(static_cast<U32>(bufferSize), storedHash.asBigEndianU32(), |
| 64 | 908 | computedHash.asBigEndianU32()); | |
| 65 | } | ||
| 66 | 4070 | } | |
| 67 | // Deserialize the packet header | ||
| 68 |
2/2✓ Branch 0 taken 3162 times.
✓ Branch 1 taken 2865 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 69 |
1/1✓ Branch 4 taken 3162 times.
|
3162 | status = this->deserializePacketHeader(buffer, container); |
| 70 | } | ||
| 71 | // Check that the packet size fits in the buffer | ||
| 72 |
2/2✓ Branch 0 taken 2207 times.
✓ Branch 1 taken 3820 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 73 |
1/1✓ Branch 2 taken 2207 times.
|
2207 | const FwSizeType packetSize = container.getPacketSize(); |
| 74 |
2/2✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 1199 times.
|
2207 | if (bufferSize < packetSize) { |
| 75 |
1/1✓ Branch 5 taken 1008 times.
|
1008 | this->log_WARNING_HI_BufferTooSmallForData(static_cast<U32>(bufferSize), static_cast<U32>(packetSize)); |
| 76 | 1008 | status = Fw::Success::FAILURE; | |
| 77 | } | ||
| 78 | } | ||
| 79 | // Perform the requested processing | ||
| 80 |
2/2✓ Branch 0 taken 1199 times.
✓ Branch 1 taken 4828 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 81 |
1/1✓ Branch 4 taken 1199 times.
|
1199 | this->performProcessing(container); |
| 82 | } | ||
| 83 | // Construct the file name | ||
| 84 |
1/1✓ Branch 2 taken 6027 times.
|
6027 | Fw::FileNameString fileName; |
| 85 |
2/2✓ Branch 0 taken 1199 times.
✓ Branch 1 taken 4828 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 86 | 1199 | const FwDpIdType containerId = container.getId(); | |
| 87 |
1/1✓ Branch 2 taken 1199 times.
|
1199 | const Fw::Time timeTag = container.getTimeTag(); |
| 88 |
3/3✓ Branch 2 taken 1199 times.
✓ Branch 5 taken 1199 times.
✓ Branch 14 taken 1199 times.
|
3597 | const Fw::FormatStatus formatStatus = fileName.format(DP_FILENAME_FORMAT, this->m_dpFileNamePrefix.toChar(), |
| 89 | 2398 | containerId, timeTag.getSeconds(), timeTag.getUSeconds()); | |
| 90 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1188 times.
|
1199 | if (formatStatus != Fw::FormatStatus::SUCCESS) { |
| 91 |
2/2✓ Branch 6 taken 11 times.
✓ Branch 10 taken 11 times.
|
11 | this->log_WARNING_HI_FileNameFormatError(static_cast<Fw::StringFormatStatus::T>(formatStatus)); |
| 92 | 11 | status = Fw::Success::FAILURE; | |
| 93 | } | ||
| 94 | 1199 | } | |
| 95 | // Calculate and populate the file data checksum | ||
| 96 |
2/2✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 4839 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 97 |
1/1✓ Branch 2 taken 1188 times.
|
1188 | container.updateDataHash(); |
| 98 | } | ||
| 99 | // Write the file | ||
| 100 | 6027 | FwSizeType fileSize = 0; | |
| 101 |
2/2✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 4839 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 102 |
1/1✓ Branch 4 taken 1188 times.
|
1188 | status = this->writeFile(container, fileName, fileSize); |
| 103 | } | ||
| 104 | // Send the DpWritten notification | ||
| 105 |
2/2✓ Branch 0 taken 472 times.
✓ Branch 1 taken 5555 times.
|
6027 | if (status == Fw::Success::SUCCESS) { |
| 106 |
1/1✓ Branch 4 taken 472 times.
|
472 | this->sendNotification(container, fileName, fileSize); |
| 107 | } | ||
| 108 | // Deallocate the buffer | ||
| 109 |
3/3✓ Branch 4 taken 6027 times.
✓ Branch 6 taken 5011 times.
✓ Branch 7 taken 1016 times.
|
6027 | if (buffer.isValid()) { |
| 110 |
1/1✓ Branch 5 taken 5011 times.
|
5011 | this->deallocBufferSendOut_out(0, buffer); |
| 111 | } | ||
| 112 | // Update the error count | ||
| 113 |
2/2✓ Branch 0 taken 5555 times.
✓ Branch 1 taken 472 times.
|
6027 | if (status != Fw::Success::SUCCESS) { |
| 114 | 5555 | this->m_numErrors++; | |
| 115 | } | ||
| 116 | 12054 | } | |
| 117 | |||
| 118 | 979 | void DpWriter::schedIn_handler(const FwIndexType portNum, U32 context) { | |
| 119 | // portNum and context are not used | ||
| 120 | (void)portNum; | ||
| 121 | (void)context; | ||
| 122 | // Write telemetry | ||
| 123 |
2/2✓ Branch 6 taken 979 times.
✓ Branch 13 taken 979 times.
|
979 | this->tlmWrite_NumBuffersReceived(this->m_numBuffersReceived); |
| 124 |
2/2✓ Branch 6 taken 979 times.
✓ Branch 13 taken 979 times.
|
979 | this->tlmWrite_NumBytesWritten(this->m_numBytesWritten); |
| 125 |
2/2✓ Branch 6 taken 979 times.
✓ Branch 13 taken 979 times.
|
979 | this->tlmWrite_NumSuccessfulWrites(this->m_numSuccessfulWrites); |
| 126 |
2/2✓ Branch 6 taken 979 times.
✓ Branch 13 taken 979 times.
|
979 | this->tlmWrite_NumFailedWrites(this->m_numFailedWrites); |
| 127 |
2/2✓ Branch 6 taken 979 times.
✓ Branch 13 taken 979 times.
|
979 | this->tlmWrite_NumErrors(this->m_numErrors); |
| 128 | 979 | } | |
| 129 | |||
| 130 | // ---------------------------------------------------------------------- | ||
| 131 | // Handler implementations for commands | ||
| 132 | // ---------------------------------------------------------------------- | ||
| 133 | |||
| 134 | 988 | void DpWriter::CLEAR_EVENT_THROTTLE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { | |
| 135 | // opCode and cmdSeq are not used | ||
| 136 | (void)opCode; | ||
| 137 | (void)cmdSeq; | ||
| 138 | // Clear throttling | ||
| 139 | 988 | this->log_WARNING_HI_BufferTooSmallForData_ThrottleClear(); | |
| 140 | 988 | this->log_WARNING_HI_BufferTooSmallForPacket_ThrottleClear(); | |
| 141 | 988 | this->log_WARNING_HI_FileOpenError_ThrottleClear(); | |
| 142 | 988 | this->log_WARNING_HI_FileWriteError_ThrottleClear(); | |
| 143 | 988 | this->log_WARNING_HI_InvalidBuffer_ThrottleClear(); | |
| 144 | 988 | this->log_WARNING_HI_InvalidHeaderHash_ThrottleClear(); | |
| 145 | 988 | this->log_WARNING_HI_InvalidHeader_ThrottleClear(); | |
| 146 | // Return command response | ||
| 147 |
2/2✓ Branch 6 taken 988 times.
✓ Branch 9 taken 988 times.
|
988 | this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); |
| 148 | 988 | } | |
| 149 | |||
| 150 | // ---------------------------------------------------------------------- | ||
| 151 | // Private helper functions | ||
| 152 | // ---------------------------------------------------------------------- | ||
| 153 | |||
| 154 | 3162 | Fw::Success::T DpWriter::deserializePacketHeader(Fw::Buffer& buffer, Fw::DpContainer& container) { | |
| 155 | 3162 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 156 | 3162 | container.setBuffer(buffer); | |
| 157 | 3162 | const Fw::SerializeStatus serialStatus = container.deserializeHeader(); | |
| 158 |
2/2✓ Branch 0 taken 955 times.
✓ Branch 1 taken 2207 times.
|
3162 | if (serialStatus != Fw::FW_SERIALIZE_OK) { |
| 159 | 955 | this->log_WARNING_HI_InvalidHeader(static_cast<U32>(buffer.getSize()), static_cast<U32>(serialStatus)); | |
| 160 | 955 | status = Fw::Success::FAILURE; | |
| 161 | } | ||
| 162 | 3162 | return status; | |
| 163 | } | ||
| 164 | |||
| 165 | 1199 | void DpWriter::performProcessing(Fw::DpContainer& container) { | |
| 166 | // Get the buffer | ||
| 167 |
1/1✓ Branch 2 taken 1199 times.
|
1199 | Fw::Buffer buffer = container.getBuffer(); |
| 168 | // Get the bit mask for the processing types | ||
| 169 | 1199 | const Fw::DpCfg::ProcType::SerialType procTypes = container.getProcTypes(); | |
| 170 | // Do the processing | ||
| 171 | 1199 | bool did_process = false; | |
| 172 |
2/2✓ Branch 0 taken 5995 times.
✓ Branch 1 taken 1199 times.
|
7194 | for (FwIndexType portNum = 0; portNum < NUM_PROCBUFFERSENDOUT_OUTPUT_PORTS; ++portNum) { |
| 173 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5995 times.
✓ Branch 2 taken 2163 times.
✓ Branch 3 taken 3832 times.
|
5995 | if ((procTypes & (1 << portNum)) != 0) { |
| 174 |
1/1✓ Branch 5 taken 2163 times.
|
2163 | this->procBufferSendOut_out(portNum, buffer); |
| 175 | 2163 | did_process = true; | |
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 |
2/2✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 51 times.
|
1199 | if (did_process) { |
| 180 | // Updated DpContainer object state with the returned value in the | ||
| 181 | // container buffer | ||
| 182 |
1/1✓ Branch 4 taken 1148 times.
|
1148 | Fw::SerializeStatus stat = container.deserializeHeader(); |
| 183 | 1148 | FW_ASSERT(stat == Fw::FW_SERIALIZE_OK, stat); | |
| 184 | |||
| 185 | // Check that the buffer size is compatible with the packet size in | ||
| 186 | // the container header | ||
| 187 | 1148 | FW_ASSERT(container.getPacketSize() <= buffer.getSize(), | |
| 188 | static_cast<FwAssertArgType>(container.getPacketSize()), | ||
| 189 | static_cast<FwAssertArgType>(buffer.getSize())); | ||
| 190 | |||
| 191 | // Re-compute and serialize the container header into the buffer | ||
| 192 |
1/1✓ Branch 4 taken 1148 times.
|
1148 | container.updateHeaderHash(); |
| 193 |
1/1✓ Branch 4 taken 1148 times.
|
1148 | container.serializeHeader(); |
| 194 | |||
| 195 | // Shrink internal Fw::Buffer | ||
| 196 |
1/1✓ Branch 4 taken 1148 times.
|
1148 | container.shrinkBufferSize(); |
| 197 | } | ||
| 198 | 2398 | } | |
| 199 | |||
| 200 | 1188 | Fw::Success::T DpWriter::writeFile(const Fw::DpContainer& container, | |
| 201 | const Fw::FileNameString& fileName, | ||
| 202 | FwSizeType& fileSize) { | ||
| 203 | 1188 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 204 | // Get the buffer | ||
| 205 |
1/1✓ Branch 2 taken 1188 times.
|
1188 | Fw::Buffer buffer = container.getBuffer(); |
| 206 | // Get the file size | ||
| 207 |
1/1✓ Branch 4 taken 1188 times.
|
1188 | fileSize = container.getPacketSize(); |
| 208 | // Open the file | ||
| 209 |
1/1✓ Branch 2 taken 1188 times.
|
1188 | Os::File file; |
| 210 |
1/1✓ Branch 6 taken 1188 times.
|
1188 | Os::File::Status fileStatus = file.open(fileName.toChar(), Os::File::OPEN_CREATE); |
| 211 |
2/2✓ Branch 0 taken 475 times.
✓ Branch 1 taken 713 times.
|
1188 | if (fileStatus != Os::File::OP_OK) { |
| 212 |
1/1✓ Branch 8 taken 475 times.
|
475 | this->log_WARNING_HI_FileOpenError(static_cast<U32>(fileStatus), fileName); |
| 213 | 475 | status = Fw::Success::FAILURE; | |
| 214 | } | ||
| 215 | // Write the file | ||
| 216 |
2/2✓ Branch 0 taken 713 times.
✓ Branch 1 taken 475 times.
|
1188 | if (status == Fw::Success::SUCCESS) { |
| 217 | // Set write size to file size | ||
| 218 | // On entry to the write call, this is the number of bytes to write | ||
| 219 | // On return from the write call, this is the number of bytes written | ||
| 220 | 713 | FwSizeType writeSize = static_cast<FwSizeType>(fileSize); | |
| 221 |
2/2✓ Branch 3 taken 713 times.
✓ Branch 6 taken 713 times.
|
713 | fileStatus = file.write(buffer.getData(), writeSize); |
| 222 | // If a successful write occurred, then update the number of bytes written | ||
| 223 |
2/2✓ Branch 0 taken 472 times.
✓ Branch 1 taken 241 times.
|
713 | if (fileStatus == Os::File::OP_OK) { |
| 224 | 472 | this->m_numBytesWritten += static_cast<U64>(writeSize); | |
| 225 | } | ||
| 226 |
3/4✓ Branch 0 taken 472 times.
✓ Branch 1 taken 241 times.
✓ Branch 3 taken 472 times.
✗ Branch 4 not taken.
|
713 | if ((fileStatus == Os::File::OP_OK) and (writeSize == static_cast<FwSizeType>(fileSize))) { |
| 227 | // If the write status is success, and the number of bytes written | ||
| 228 | // is the expected number, then record the success | ||
| 229 |
1/1✓ Branch 8 taken 472 times.
|
472 | this->log_ACTIVITY_LO_FileWritten(static_cast<U32>(writeSize), fileName); |
| 230 | } else { | ||
| 231 | // Otherwise record the failure | ||
| 232 | 241 | this->log_WARNING_HI_FileWriteError(static_cast<U32>(fileStatus), static_cast<U32>(writeSize), | |
| 233 |
1/1✓ Branch 2 taken 241 times.
|
241 | static_cast<U32>(fileSize), fileName); |
| 234 | 241 | status = Fw::Success::FAILURE; | |
| 235 | } | ||
| 236 | } | ||
| 237 | // Update the count of successful or failed writes | ||
| 238 |
2/2✓ Branch 0 taken 472 times.
✓ Branch 1 taken 716 times.
|
1188 | if (status == Fw::Success::SUCCESS) { |
| 239 | 472 | this->m_numSuccessfulWrites++; | |
| 240 | } else { | ||
| 241 | 716 | this->m_numFailedWrites++; | |
| 242 | } | ||
| 243 | // Return the status | ||
| 244 | 1188 | return status; | |
| 245 | 1188 | } | |
| 246 | |||
| 247 | 472 | void DpWriter::sendNotification(const Fw::DpContainer& container, | |
| 248 | const Fw::FileNameString& fileName, | ||
| 249 | FwSizeType fileSize) { | ||
| 250 |
1/2✓ Branch 5 taken 472 times.
✗ Branch 6 not taken.
|
472 | if (isConnected_dpWrittenOut_OutputPort(0)) { |
| 251 | // Get the priority | ||
| 252 | 472 | const FwDpPriorityType priority = container.getPriority(); | |
| 253 | 472 | this->dpWrittenOut_out(0, fileName, priority, fileSize); | |
| 254 | } | ||
| 255 | 472 | } | |
| 256 | |||
| 257 | } // end namespace Svc | ||
| 258 |