GCC Code Coverage Report


Directory: Svc/DpWriter/
File: DpWriter.cpp
Date: 2026-10-14 21:19:15
Exec Total Coverage
Lines: 127 127 100.0%
Functions: 10 10 100.0%
Branches: 109 112 97.3%

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 6160 void DpWriter::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) {
35 6160 Fw::Success::T status = Fw::Success::SUCCESS;
36 // Update num buffers received
37 6160 ++this->m_numBuffersReceived;
38 // Check that the buffer is valid
39
3/3
✓ Branch 4 taken 6160 times.
✓ Branch 6 taken 1028 times.
✓ Branch 7 taken 5132 times.
6160 if (!buffer.isValid()) {
40
1/1
✓ Branch 5 taken 1028 times.
1028 this->log_WARNING_HI_InvalidBuffer();
41 1028 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 6160 times.
6160 const FwSizeType bufferSize = buffer.getSize();
45
2/2
✓ Branch 0 taken 5132 times.
✓ Branch 1 taken 1028 times.
6160 if (status == Fw::Success::SUCCESS) {
46
2/2
✓ Branch 0 taken 998 times.
✓ Branch 1 taken 4134 times.
5132 if (bufferSize < Fw::DpContainer::MIN_PACKET_SIZE) {
47
1/1
✓ Branch 5 taken 998 times.
998 this->log_WARNING_HI_BufferTooSmallForPacket(static_cast<U32>(bufferSize),
48 Fw::DpContainer::MIN_PACKET_SIZE);
49
50 998 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 6160 times.
6160 Fw::DpContainer container;
55
2/2
✓ Branch 0 taken 4134 times.
✓ Branch 1 taken 2026 times.
6160 if (status == Fw::Success::SUCCESS) {
56
1/1
✓ Branch 3 taken 4134 times.
4134 container.setBuffer(buffer);
57
1/1
✓ Branch 2 taken 4134 times.
4134 Utils::HashBuffer storedHash;
58
1/1
✓ Branch 2 taken 4134 times.
4134 Utils::HashBuffer computedHash;
59
1/1
✓ Branch 2 taken 4134 times.
4134 status = container.checkHeaderHash(storedHash, computedHash);
60
2/2
✓ Branch 0 taken 1014 times.
✓ Branch 1 taken 3120 times.
4134 if (status != Fw::Success::SUCCESS) {
61
3/3
✓ Branch 5 taken 1014 times.
✓ Branch 9 taken 1014 times.
✓ Branch 12 taken 1014 times.
2028 this->log_WARNING_HI_InvalidHeaderHash(static_cast<U32>(bufferSize), storedHash.asBigEndianU32(),
62 1014 computedHash.asBigEndianU32());
63 }
64 4134 }
65 // Deserialize the packet header
66
2/2
✓ Branch 0 taken 3120 times.
✓ Branch 1 taken 3040 times.
6160 if (status == Fw::Success::SUCCESS) {
67
1/1
✓ Branch 4 taken 3120 times.
3120 status = this->deserializePacketHeader(buffer, container);
68 }
69 // Check that the packet size fits in the buffer
70
2/2
✓ Branch 0 taken 2147 times.
✓ Branch 1 taken 4013 times.
6160 if (status == Fw::Success::SUCCESS) {
71
1/1
✓ Branch 2 taken 2147 times.
2147 const FwSizeType packetSize = container.getPacketSize();
72
2/2
✓ Branch 0 taken 996 times.
✓ Branch 1 taken 1151 times.
2147 if (bufferSize < packetSize) {
73
1/1
✓ Branch 5 taken 996 times.
996 this->log_WARNING_HI_BufferTooSmallForData(static_cast<U32>(bufferSize), static_cast<U32>(packetSize));
74 996 status = Fw::Success::FAILURE;
75 }
76 }
77 // Perform the requested processing
78
2/2
✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 5009 times.
6160 if (status == Fw::Success::SUCCESS) {
79
1/1
✓ Branch 4 taken 1151 times.
1151 this->performProcessing(container);
80 }
81 // Construct the file name
82
1/1
✓ Branch 2 taken 6160 times.
6160 Fw::FileNameString fileName;
83
2/2
✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 5009 times.
6160 if (status == Fw::Success::SUCCESS) {
84 1151 const FwDpIdType containerId = container.getId();
85
1/1
✓ Branch 2 taken 1151 times.
1151 const Fw::Time timeTag = container.getTimeTag();
86
3/3
✓ Branch 2 taken 1151 times.
✓ Branch 5 taken 1151 times.
✓ Branch 14 taken 1151 times.
3453 const Fw::FormatStatus formatStatus = fileName.format(DP_FILENAME_FORMAT, this->m_dpFileNamePrefix.toChar(),
87 2302 containerId, timeTag.getSeconds(), timeTag.getUSeconds());
88
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1140 times.
1151 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 1151 }
93 // Calculate and populate the file data checksum
94
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 5020 times.
6160 if (status == Fw::Success::SUCCESS) {
95
1/1
✓ Branch 2 taken 1140 times.
1140 container.updateDataHash();
96 }
97 // Write the file
98 6160 FwSizeType fileSize = 0;
99
2/2
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 5020 times.
6160 if (status == Fw::Success::SUCCESS) {
100
1/1
✓ Branch 4 taken 1140 times.
1140 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 432 times.
✓ Branch 1 taken 5728 times.
6160 if (status == Fw::Success::SUCCESS) {
104
1/1
✓ Branch 4 taken 432 times.
432 this->sendNotification(portNum, container, fileName, fileSize);
105 }
106 // Return the buffer on the path matching the input port
107
3/3
✓ Branch 4 taken 6160 times.
✓ Branch 6 taken 5132 times.
✓ Branch 7 taken 1028 times.
6160 if (buffer.isValid()) {
108
1/1
✓ Branch 5 taken 5132 times.
5132 this->deallocBufferSendOut_out(portNum, buffer);
109 }
110 // Update the error count
111
2/2
✓ Branch 0 taken 5728 times.
✓ Branch 1 taken 432 times.
6160 if (status != Fw::Success::SUCCESS) {
112 5728 this->m_numErrors++;
113 }
114 12320 }
115
116 954 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 954 times.
✓ Branch 13 taken 954 times.
954 this->tlmWrite_NumBuffersReceived(this->m_numBuffersReceived);
122
2/2
✓ Branch 6 taken 954 times.
✓ Branch 13 taken 954 times.
954 this->tlmWrite_NumBytesWritten(this->m_numBytesWritten);
123
2/2
✓ Branch 6 taken 954 times.
✓ Branch 13 taken 954 times.
954 this->tlmWrite_NumSuccessfulWrites(this->m_numSuccessfulWrites);
124
2/2
✓ Branch 6 taken 954 times.
✓ Branch 13 taken 954 times.
954 this->tlmWrite_NumFailedWrites(this->m_numFailedWrites);
125
2/2
✓ Branch 6 taken 954 times.
✓ Branch 13 taken 954 times.
954 this->tlmWrite_NumErrors(this->m_numErrors);
126 954 }
127
128 // ----------------------------------------------------------------------
129 // Handler implementations for commands
130 // ----------------------------------------------------------------------
131
132 1006 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 1006 this->log_WARNING_HI_BufferTooSmallForData_ThrottleClear();
138 1006 this->log_WARNING_HI_BufferTooSmallForPacket_ThrottleClear();
139 1006 this->log_WARNING_HI_FileOpenError_ThrottleClear();
140 1006 this->log_WARNING_HI_FileWriteError_ThrottleClear();
141 1006 this->log_WARNING_HI_InvalidBuffer_ThrottleClear();
142 1006 this->log_WARNING_HI_InvalidHeaderHash_ThrottleClear();
143 1006 this->log_WARNING_HI_InvalidHeader_ThrottleClear();
144 // Return command response
145
2/2
✓ Branch 6 taken 1006 times.
✓ Branch 9 taken 1006 times.
1006 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
146 1006 }
147
148 // ----------------------------------------------------------------------
149 // Private helper functions
150 // ----------------------------------------------------------------------
151
152 3120 Fw::Success::T DpWriter::deserializePacketHeader(Fw::Buffer& buffer, Fw::DpContainer& container) {
153 3120 Fw::Success::T status = Fw::Success::SUCCESS;
154 3120 container.setBuffer(buffer);
155 3120 const Fw::SerializeStatus serialStatus = container.deserializeHeader();
156
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 2147 times.
3120 if (serialStatus != Fw::FW_SERIALIZE_OK) {
157 973 this->log_WARNING_HI_InvalidHeader(static_cast<U32>(buffer.getSize()), static_cast<U32>(serialStatus));
158 973 status = Fw::Success::FAILURE;
159 }
160 3120 return status;
161 }
162
163 1151 void DpWriter::performProcessing(Fw::DpContainer& container) {
164 // Get the buffer
165
1/1
✓ Branch 2 taken 1151 times.
1151 Fw::Buffer buffer = container.getBuffer();
166 // Get the bit mask for the processing types
167 1151 const Fw::DpCfg::ProcType::SerialType procTypes = container.getProcTypes();
168 // Do the processing
169 1151 bool did_process = false;
170
2/2
✓ Branch 0 taken 5755 times.
✓ Branch 1 taken 1151 times.
6906 for (FwIndexType portNum = 0; portNum < NUM_PROCBUFFERSENDOUT_OUTPUT_PORTS; ++portNum) {
171
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5755 times.
✓ Branch 2 taken 2118 times.
✓ Branch 3 taken 3637 times.
5755 if ((procTypes & (1 << portNum)) != 0) {
172
1/1
✓ Branch 5 taken 2118 times.
2118 this->procBufferSendOut_out(portNum, buffer);
173 2118 did_process = true;
174 }
175 }
176
177
2/2
✓ Branch 0 taken 1093 times.
✓ Branch 1 taken 58 times.
1151 if (did_process) {
178 // Updated DpContainer object state with the returned value in the
179 // container buffer
180
1/1
✓ Branch 4 taken 1093 times.
1093 Fw::SerializeStatus stat = container.deserializeHeader();
181 1093 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 1093 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 1093 times.
1093 container.updateHeaderHash();
191
1/1
✓ Branch 4 taken 1093 times.
1093 container.serializeHeader();
192
193 // Shrink internal Fw::Buffer
194
1/1
✓ Branch 4 taken 1093 times.
1093 container.shrinkBufferSize();
195 }
196 2302 }
197
198 1140 Fw::Success::T DpWriter::writeFile(const Fw::DpContainer& container,
199 const Fw::FileNameString& fileName,
200 FwSizeType& fileSize) {
201 1140 Fw::Success::T status = Fw::Success::SUCCESS;
202 // Get the buffer
203
1/1
✓ Branch 2 taken 1140 times.
1140 Fw::Buffer buffer = container.getBuffer();
204 // Get the file size
205
1/1
✓ Branch 4 taken 1140 times.
1140 fileSize = container.getPacketSize();
206 // Open the file
207
1/1
✓ Branch 2 taken 1140 times.
1140 Os::File file;
208
1/1
✓ Branch 6 taken 1140 times.
1140 Os::File::Status fileStatus = file.open(fileName.toChar(), Os::File::OPEN_CREATE);
209
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 672 times.
1140 if (fileStatus != Os::File::OP_OK) {
210
1/1
✓ Branch 8 taken 468 times.
468 this->log_WARNING_HI_FileOpenError(static_cast<U32>(fileStatus), fileName);
211 468 status = Fw::Success::FAILURE;
212 }
213 // Write the file
214
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 468 times.
1140 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 672 FwSizeType writeSize = static_cast<FwSizeType>(fileSize);
219
2/2
✓ Branch 3 taken 672 times.
✓ Branch 6 taken 672 times.
672 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 432 times.
✓ Branch 1 taken 240 times.
672 if (fileStatus == Os::File::OP_OK) {
222 432 this->m_numBytesWritten += static_cast<U64>(writeSize);
223 }
224
3/4
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 240 times.
✓ Branch 3 taken 432 times.
✗ Branch 4 not taken.
672 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 432 times.
432 this->log_ACTIVITY_LO_FileWritten(static_cast<U32>(writeSize), fileName);
228 } else {
229 // Otherwise record the failure
230 240 this->log_WARNING_HI_FileWriteError(static_cast<U32>(fileStatus), static_cast<U32>(writeSize),
231
1/1
✓ Branch 2 taken 240 times.
240 static_cast<U32>(fileSize), fileName);
232 240 status = Fw::Success::FAILURE;
233 }
234 }
235 // Update the count of successful or failed writes
236
2/2
✓ Branch 0 taken 432 times.
✓ Branch 1 taken 708 times.
1140 if (status == Fw::Success::SUCCESS) {
237 432 this->m_numSuccessfulWrites++;
238 } else {
239 708 this->m_numFailedWrites++;
240 }
241 // Return the status
242 1140 return status;
243 1140 }
244
245 432 void DpWriter::sendNotification(FwIndexType portNum,
246 const Fw::DpContainer& container,
247 const Fw::FileNameString& fileName,
248 FwSizeType fileSize) {
249
1/2
✓ Branch 5 taken 432 times.
✗ Branch 6 not taken.
432 if (isConnected_dpWrittenOut_OutputPort(portNum)) {
250 // Get the priority
251 432 const FwDpPriorityType priority = container.getPriority();
252 432 this->dpWrittenOut_out(portNum, fileName, priority, fileSize);
253 }
254 432 }
255
256 } // end namespace Svc
257