| 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 22 times.
|
22 | DpWriter::DpWriter(const char* const compName) : DpWriterComponentBase(compName), m_dpFileNamePrefix() {} |
| 23 | |||
| 24 | 44 | 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 | 6199 | void DpWriter::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) { | |
| 35 | 6199 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 36 | // Update num buffers received | ||
| 37 | 6199 | ++this->m_numBuffersReceived; | |
| 38 | // Check that the buffer is valid | ||
| 39 |
3/3✓ Branch 4 taken 6199 times.
✓ Branch 6 taken 957 times.
✓ Branch 7 taken 5242 times.
|
6199 | if (!buffer.isValid()) { |
| 40 |
1/1✓ Branch 5 taken 957 times.
|
957 | this->log_WARNING_HI_InvalidBuffer(); |
| 41 | 957 | status = Fw::Success::FAILURE; | |
| 42 | } | ||
| 43 | // Check that the buffer is large enough to hold a data product packet | ||
| 44 |
1/1✓ Branch 4 taken 6199 times.
|
6199 | const FwSizeType bufferSize = buffer.getSize(); |
| 45 |
2/2✓ Branch 0 taken 5242 times.
✓ Branch 1 taken 957 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 46 |
2/2✓ Branch 0 taken 1041 times.
✓ Branch 1 taken 4201 times.
|
5242 | if (bufferSize < Fw::DpContainer::MIN_PACKET_SIZE) { |
| 47 |
1/1✓ Branch 5 taken 1041 times.
|
1041 | this->log_WARNING_HI_BufferTooSmallForPacket(static_cast<U32>(bufferSize), |
| 48 | Fw::DpContainer::MIN_PACKET_SIZE); | ||
| 49 | |||
| 50 | 1041 | status = Fw::Success::FAILURE; | |
| 51 | } | ||
| 52 | } | ||
| 53 | // Set up the container and check that the header hash is valid | ||
| 54 |
1/1✓ Branch 2 taken 6199 times.
|
6199 | Fw::DpContainer container; |
| 55 |
2/2✓ Branch 0 taken 4201 times.
✓ Branch 1 taken 1998 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 56 |
1/1✓ Branch 3 taken 4201 times.
|
4201 | container.setBuffer(buffer); |
| 57 |
1/1✓ Branch 2 taken 4201 times.
|
4201 | Utils::HashBuffer storedHash; |
| 58 |
1/1✓ Branch 2 taken 4201 times.
|
4201 | Utils::HashBuffer computedHash; |
| 59 |
1/1✓ Branch 2 taken 4201 times.
|
4201 | status = container.checkHeaderHash(storedHash, computedHash); |
| 60 |
2/2✓ Branch 0 taken 977 times.
✓ Branch 1 taken 3224 times.
|
4201 | if (status != Fw::Success::SUCCESS) { |
| 61 |
3/3✓ Branch 5 taken 977 times.
✓ Branch 9 taken 977 times.
✓ Branch 12 taken 977 times.
|
1954 | this->log_WARNING_HI_InvalidHeaderHash(static_cast<U32>(bufferSize), storedHash.asBigEndianU32(), |
| 62 | 977 | computedHash.asBigEndianU32()); | |
| 63 | } | ||
| 64 | 4201 | } | |
| 65 | // Deserialize the packet header | ||
| 66 |
2/2✓ Branch 0 taken 3224 times.
✓ Branch 1 taken 2975 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 67 |
1/1✓ Branch 4 taken 3224 times.
|
3224 | status = this->deserializePacketHeader(buffer, container); |
| 68 | } | ||
| 69 | // Check that the packet size fits in the buffer | ||
| 70 |
2/2✓ Branch 0 taken 2273 times.
✓ Branch 1 taken 3926 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 71 |
1/1✓ Branch 2 taken 2273 times.
|
2273 | const FwSizeType packetSize = container.getPacketSize(); |
| 72 |
2/2✓ Branch 0 taken 1058 times.
✓ Branch 1 taken 1215 times.
|
2273 | if (bufferSize < packetSize) { |
| 73 |
1/1✓ Branch 5 taken 1058 times.
|
1058 | this->log_WARNING_HI_BufferTooSmallForData(static_cast<U32>(bufferSize), static_cast<U32>(packetSize)); |
| 74 | 1058 | status = Fw::Success::FAILURE; | |
| 75 | } | ||
| 76 | } | ||
| 77 | // Perform the requested processing | ||
| 78 |
2/2✓ Branch 0 taken 1215 times.
✓ Branch 1 taken 4984 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 79 |
1/1✓ Branch 4 taken 1215 times.
|
1215 | this->performProcessing(container); |
| 80 | } | ||
| 81 | // Construct the file name | ||
| 82 |
1/1✓ Branch 2 taken 6199 times.
|
6199 | Fw::FileNameString fileName; |
| 83 |
2/2✓ Branch 0 taken 1215 times.
✓ Branch 1 taken 4984 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 84 | 1215 | const FwDpIdType containerId = container.getId(); | |
| 85 |
1/1✓ Branch 2 taken 1215 times.
|
1215 | const Fw::Time timeTag = container.getTimeTag(); |
| 86 |
3/3✓ Branch 2 taken 1215 times.
✓ Branch 5 taken 1215 times.
✓ Branch 14 taken 1215 times.
|
3645 | const Fw::FormatStatus formatStatus = fileName.format(DP_FILENAME_FORMAT, this->m_dpFileNamePrefix.toChar(), |
| 87 | 2430 | containerId, timeTag.getSeconds(), timeTag.getUSeconds()); | |
| 88 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1204 times.
|
1215 | if (formatStatus != Fw::FormatStatus::SUCCESS) { |
| 89 |
2/2✓ Branch 6 taken 11 times.
✓ Branch 10 taken 11 times.
|
11 | this->log_WARNING_HI_FileNameFormatError(static_cast<Fw::StringFormatStatus::T>(formatStatus)); |
| 90 | 11 | status = Fw::Success::FAILURE; | |
| 91 | } | ||
| 92 | 1215 | } | |
| 93 | // Calculate and populate the file data checksum | ||
| 94 |
2/2✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 4995 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 95 |
1/1✓ Branch 2 taken 1204 times.
|
1204 | container.updateDataHash(); |
| 96 | } | ||
| 97 | // Write the file | ||
| 98 | 6199 | FwSizeType fileSize = 0; | |
| 99 |
2/2✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 4995 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 100 |
1/1✓ Branch 4 taken 1204 times.
|
1204 | status = this->writeFile(container, fileName, fileSize); |
| 101 | } | ||
| 102 | // Send the DpWritten notification on the path matching the input port | ||
| 103 |
2/2✓ Branch 0 taken 512 times.
✓ Branch 1 taken 5687 times.
|
6199 | if (status == Fw::Success::SUCCESS) { |
| 104 |
1/1✓ Branch 4 taken 512 times.
|
512 | this->sendNotification(portNum, container, fileName, fileSize); |
| 105 | } | ||
| 106 | // Return the buffer on the path matching the input port | ||
| 107 |
3/3✓ Branch 4 taken 6199 times.
✓ Branch 6 taken 5242 times.
✓ Branch 7 taken 957 times.
|
6199 | if (buffer.isValid()) { |
| 108 |
1/1✓ Branch 5 taken 5242 times.
|
5242 | this->deallocBufferSendOut_out(portNum, buffer); |
| 109 | } | ||
| 110 | // Update the error count | ||
| 111 |
2/2✓ Branch 0 taken 5687 times.
✓ Branch 1 taken 512 times.
|
6199 | if (status != Fw::Success::SUCCESS) { |
| 112 | 5687 | this->m_numErrors++; | |
| 113 | } | ||
| 114 | 12398 | } | |
| 115 | |||
| 116 | 981 | void DpWriter::schedIn_handler(const FwIndexType portNum, U32 context) { | |
| 117 | // portNum and context are not used | ||
| 118 | (void)portNum; | ||
| 119 | (void)context; | ||
| 120 | // Write telemetry | ||
| 121 |
2/2✓ Branch 6 taken 981 times.
✓ Branch 13 taken 981 times.
|
981 | this->tlmWrite_NumBuffersReceived(this->m_numBuffersReceived); |
| 122 |
2/2✓ Branch 6 taken 981 times.
✓ Branch 13 taken 981 times.
|
981 | this->tlmWrite_NumBytesWritten(this->m_numBytesWritten); |
| 123 |
2/2✓ Branch 6 taken 981 times.
✓ Branch 13 taken 981 times.
|
981 | this->tlmWrite_NumSuccessfulWrites(this->m_numSuccessfulWrites); |
| 124 |
2/2✓ Branch 6 taken 981 times.
✓ Branch 13 taken 981 times.
|
981 | this->tlmWrite_NumFailedWrites(this->m_numFailedWrites); |
| 125 |
2/2✓ Branch 6 taken 981 times.
✓ Branch 13 taken 981 times.
|
981 | this->tlmWrite_NumErrors(this->m_numErrors); |
| 126 | 981 | } | |
| 127 | |||
| 128 | // ---------------------------------------------------------------------- | ||
| 129 | // Handler implementations for commands | ||
| 130 | // ---------------------------------------------------------------------- | ||
| 131 | |||
| 132 | 945 | void DpWriter::CLEAR_EVENT_THROTTLE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { | |
| 133 | // opCode and cmdSeq are not used | ||
| 134 | (void)opCode; | ||
| 135 | (void)cmdSeq; | ||
| 136 | // Clear throttling | ||
| 137 | 945 | this->log_WARNING_HI_BufferTooSmallForData_ThrottleClear(); | |
| 138 | 945 | this->log_WARNING_HI_BufferTooSmallForPacket_ThrottleClear(); | |
| 139 | 945 | this->log_WARNING_HI_FileOpenError_ThrottleClear(); | |
| 140 | 945 | this->log_WARNING_HI_FileWriteError_ThrottleClear(); | |
| 141 | 945 | this->log_WARNING_HI_InvalidBuffer_ThrottleClear(); | |
| 142 | 945 | this->log_WARNING_HI_InvalidHeaderHash_ThrottleClear(); | |
| 143 | 945 | this->log_WARNING_HI_InvalidHeader_ThrottleClear(); | |
| 144 | // Return command response | ||
| 145 |
2/2✓ Branch 6 taken 945 times.
✓ Branch 9 taken 945 times.
|
945 | this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); |
| 146 | 945 | } | |
| 147 | |||
| 148 | // ---------------------------------------------------------------------- | ||
| 149 | // Private helper functions | ||
| 150 | // ---------------------------------------------------------------------- | ||
| 151 | |||
| 152 | 3224 | Fw::Success::T DpWriter::deserializePacketHeader(Fw::Buffer& buffer, Fw::DpContainer& container) { | |
| 153 | 3224 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 154 | 3224 | container.setBuffer(buffer); | |
| 155 | 3224 | const Fw::SerializeStatus serialStatus = container.deserializeHeader(); | |
| 156 |
2/2✓ Branch 0 taken 951 times.
✓ Branch 1 taken 2273 times.
|
3224 | if (serialStatus != Fw::FW_SERIALIZE_OK) { |
| 157 | 951 | this->log_WARNING_HI_InvalidHeader(static_cast<U32>(buffer.getSize()), static_cast<U32>(serialStatus)); | |
| 158 | 951 | status = Fw::Success::FAILURE; | |
| 159 | } | ||
| 160 | 3224 | return status; | |
| 161 | } | ||
| 162 | |||
| 163 | 1215 | void DpWriter::performProcessing(Fw::DpContainer& container) { | |
| 164 | // Get the buffer | ||
| 165 |
1/1✓ Branch 2 taken 1215 times.
|
1215 | Fw::Buffer buffer = container.getBuffer(); |
| 166 | // Get the bit mask for the processing types | ||
| 167 | 1215 | const Fw::DpCfg::ProcType::SerialType procTypes = container.getProcTypes(); | |
| 168 | // Do the processing | ||
| 169 | 1215 | bool did_process = false; | |
| 170 |
2/2✓ Branch 0 taken 6075 times.
✓ Branch 1 taken 1215 times.
|
7290 | for (FwIndexType portNum = 0; portNum < NUM_PROCBUFFERSENDOUT_OUTPUT_PORTS; ++portNum) { |
| 171 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 6075 times.
✓ Branch 2 taken 2182 times.
✓ Branch 3 taken 3893 times.
|
6075 | if ((procTypes & (1 << portNum)) != 0) { |
| 172 |
1/1✓ Branch 5 taken 2182 times.
|
2182 | this->procBufferSendOut_out(portNum, buffer); |
| 173 | 2182 | did_process = true; | |
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 |
2/2✓ Branch 0 taken 1154 times.
✓ Branch 1 taken 61 times.
|
1215 | if (did_process) { |
| 178 | // Updated DpContainer object state with the returned value in the | ||
| 179 | // container buffer | ||
| 180 |
1/1✓ Branch 4 taken 1154 times.
|
1154 | Fw::SerializeStatus stat = container.deserializeHeader(); |
| 181 | 1154 | FW_ASSERT(stat == Fw::FW_SERIALIZE_OK, stat); | |
| 182 | |||
| 183 | // Check that the buffer size is compatible with the packet size in | ||
| 184 | // the container header | ||
| 185 | 1154 | FW_ASSERT(container.getPacketSize() <= buffer.getSize(), | |
| 186 | static_cast<FwAssertArgType>(container.getPacketSize()), | ||
| 187 | static_cast<FwAssertArgType>(buffer.getSize())); | ||
| 188 | |||
| 189 | // Re-compute and serialize the container header into the buffer | ||
| 190 |
1/1✓ Branch 4 taken 1154 times.
|
1154 | container.updateHeaderHash(); |
| 191 |
1/1✓ Branch 4 taken 1154 times.
|
1154 | container.serializeHeader(); |
| 192 | |||
| 193 | // Shrink internal Fw::Buffer | ||
| 194 |
1/1✓ Branch 4 taken 1154 times.
|
1154 | container.shrinkBufferSize(); |
| 195 | } | ||
| 196 | 2430 | } | |
| 197 | |||
| 198 | 1204 | Fw::Success::T DpWriter::writeFile(const Fw::DpContainer& container, | |
| 199 | const Fw::FileNameString& fileName, | ||
| 200 | FwSizeType& fileSize) { | ||
| 201 | 1204 | Fw::Success::T status = Fw::Success::SUCCESS; | |
| 202 | // Get the buffer | ||
| 203 |
1/1✓ Branch 2 taken 1204 times.
|
1204 | Fw::Buffer buffer = container.getBuffer(); |
| 204 | // Get the file size | ||
| 205 |
1/1✓ Branch 4 taken 1204 times.
|
1204 | fileSize = container.getPacketSize(); |
| 206 | // Open the file | ||
| 207 |
1/1✓ Branch 2 taken 1204 times.
|
1204 | Os::File file; |
| 208 |
1/1✓ Branch 6 taken 1204 times.
|
1204 | Os::File::Status fileStatus = file.open(fileName.toChar(), Os::File::OPEN_CREATE); |
| 209 |
2/2✓ Branch 0 taken 454 times.
✓ Branch 1 taken 750 times.
|
1204 | if (fileStatus != Os::File::OP_OK) { |
| 210 |
1/1✓ Branch 8 taken 454 times.
|
454 | this->log_WARNING_HI_FileOpenError(static_cast<U32>(fileStatus), fileName); |
| 211 | 454 | status = Fw::Success::FAILURE; | |
| 212 | } | ||
| 213 | // Write the file | ||
| 214 |
2/2✓ Branch 0 taken 750 times.
✓ Branch 1 taken 454 times.
|
1204 | if (status == Fw::Success::SUCCESS) { |
| 215 | // Set write size to file size | ||
| 216 | // On entry to the write call, this is the number of bytes to write | ||
| 217 | // On return from the write call, this is the number of bytes written | ||
| 218 | 750 | FwSizeType writeSize = static_cast<FwSizeType>(fileSize); | |
| 219 |
2/2✓ Branch 3 taken 750 times.
✓ Branch 6 taken 750 times.
|
750 | fileStatus = file.write(buffer.getData(), writeSize); |
| 220 | // If a successful write occurred, then update the number of bytes written | ||
| 221 |
2/2✓ Branch 0 taken 512 times.
✓ Branch 1 taken 238 times.
|
750 | if (fileStatus == Os::File::OP_OK) { |
| 222 | 512 | this->m_numBytesWritten += static_cast<U64>(writeSize); | |
| 223 | } | ||
| 224 |
3/4✓ Branch 0 taken 512 times.
✓ Branch 1 taken 238 times.
✓ Branch 3 taken 512 times.
✗ Branch 4 not taken.
|
750 | if ((fileStatus == Os::File::OP_OK) and (writeSize == static_cast<FwSizeType>(fileSize))) { |
| 225 | // If the write status is success, and the number of bytes written | ||
| 226 | // is the expected number, then record the success | ||
| 227 |
1/1✓ Branch 8 taken 512 times.
|
512 | this->log_ACTIVITY_LO_FileWritten(static_cast<U32>(writeSize), fileName); |
| 228 | } else { | ||
| 229 | // Otherwise record the failure | ||
| 230 | 238 | this->log_WARNING_HI_FileWriteError(static_cast<U32>(fileStatus), static_cast<U32>(writeSize), | |
| 231 |
1/1✓ Branch 2 taken 238 times.
|
238 | static_cast<U32>(fileSize), fileName); |
| 232 | 238 | status = Fw::Success::FAILURE; | |
| 233 | } | ||
| 234 | } | ||
| 235 | // Update the count of successful or failed writes | ||
| 236 |
2/2✓ Branch 0 taken 512 times.
✓ Branch 1 taken 692 times.
|
1204 | if (status == Fw::Success::SUCCESS) { |
| 237 | 512 | this->m_numSuccessfulWrites++; | |
| 238 | } else { | ||
| 239 | 692 | this->m_numFailedWrites++; | |
| 240 | } | ||
| 241 | // Return the status | ||
| 242 | 1204 | return status; | |
| 243 | 1204 | } | |
| 244 | |||
| 245 | 512 | void DpWriter::sendNotification(FwIndexType portNum, | |
| 246 | const Fw::DpContainer& container, | ||
| 247 | const Fw::FileNameString& fileName, | ||
| 248 | FwSizeType fileSize) { | ||
| 249 |
1/2✓ Branch 5 taken 512 times.
✗ Branch 6 not taken.
|
512 | if (isConnected_dpWrittenOut_OutputPort(portNum)) { |
| 250 | // Get the priority | ||
| 251 | 512 | const FwDpPriorityType priority = container.getPriority(); | |
| 252 | 512 | this->dpWrittenOut_out(portNum, fileName, priority, fileSize); | |
| 253 | } | ||
| 254 | 512 | } | |
| 255 | |||
| 256 | } // end namespace Svc | ||
| 257 |