GCC Code Coverage Report


Directory: Svc/ComLoggerDp/
File: ComLoggerDp.cpp
Date: 2026-10-14 21:18:22
Exec Total Coverage
Lines: 122 123 99.2%
Functions: 19 19 100.0%
Branches: 90 99 90.9%

Line Branch Exec Source
1 // ======================================================================
2 // \title ComLoggerDp.cpp
3 // \author tcanham
4 // \brief cpp file for ComLoggerDp component implementation class
5 // ======================================================================
6
7 #include "Svc/ComLoggerDp/ComLoggerDp.hpp"
8 #include "Fw/FPrimeBasicTypes.hpp"
9
10 namespace Svc {
11
12 // ----------------------------------------------------------------------
13 // Component construction and destruction
14 // ----------------------------------------------------------------------
15
16
1/1
✓ Branch 14 taken 29 times.
29 ComLoggerDp ::ComLoggerDp(const char* const compName) : ComLoggerDpComponentBase(compName) {}
17
18 58 ComLoggerDp ::~ComLoggerDp() {}
19
20 // ----------------------------------------------------------------------
21 // Public interface
22 // ----------------------------------------------------------------------
23
24 6 void ComLoggerDp ::configure(bool enabled,
25 FwSizeType packetsPerContainer,
26 FwDpPriorityType priority,
27 U32 flushTimeout) {
28 // Store flush timeout setting
29 6 this->m_flushTimeout = flushTimeout;
30
31 // If enabling, use the internal start function which validates parameters
32
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (enabled) {
33 // This will validate packetsPerContainer and set m_enabled
34
1/1
✓ Branch 2 taken 4 times.
4 const Fw::Success started = this->startRecordingInternal(packetsPerContainer, priority);
35 4 FW_ASSERT(started == Fw::Success::SUCCESS, static_cast<FwAssertArgType>(packetsPerContainer));
36 4 } else {
37 // Just disable if not enabling
38 2 this->m_enabled = false;
39 }
40 6 }
41
42 // ----------------------------------------------------------------------
43 // Handler implementations for typed input ports
44 // ----------------------------------------------------------------------
45
46 49 void ComLoggerDp ::comIn_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
47 // portNum and context are unused
48 (void)portNum;
49 (void)context;
50
51 // If logging is not enabled, return immediately
52
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 46 times.
49 if (!this->m_enabled) {
53 3 return;
54 }
55
56 // Reset inactivity counter - we received a packet
57 46 this->m_schedCallsSinceLastPacket = 0;
58
59 // Allocate container if needed
60
11/15
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 15 times.
✓ Branch 8 taken 31 times.
✓ Branch 14 taken 8 times.
✓ Branch 15 taken 23 times.
✓ Branch 16 taken 31 times.
✓ Branch 17 taken 15 times.
✓ Branch 20 taken 31 times.
✓ Branch 21 taken 15 times.
✓ Branch 23 taken 8 times.
✓ Branch 24 taken 38 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
46 if ((this->m_currentPacketCount == 0) && (this->allocateAndSetupContainer() != Fw::Success::SUCCESS)) {
61 8 return;
62 }
63
64 // Get data from ComBuffer
65 38 const FwSizeType dataSize = data.getSize();
66 38 const U8* dataPtr = data.getBuffAddr();
67
68 // Serialize the packet
69 38 this->serializePacket(dataPtr, dataSize);
70
71 // Increment counters
72 38 ++this->m_currentPacketCount;
73 38 ++this->m_numBuffersLogged;
74
75 // Check if container has reached the limit
76
2/2
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 26 times.
38 if (this->m_currentPacketCount >= this->m_packetsPerContainer) {
77 12 this->finalizeContainer();
78 }
79 }
80
81 1 void ComLoggerDp ::pingIn_handler(FwIndexType portNum, U32 key) {
82 // Return the key via pingOut port
83 1 this->pingOut_out(portNum, key);
84 1 }
85
86 46 void ComLoggerDp ::schedIn_handler(FwIndexType portNum, U32 context) {
87 // portNum and context are unused
88 (void)portNum;
89 (void)context;
90
91 // Check for auto-flush condition
92 // Note: m_flushTimeout > 0 check ensures auto-flush is disabled when timeout is 0
93 // Without this check, flushTimeout=0 would cause immediate flush (0 >= 0 is true)
94
7/8
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 43 times.
✓ Branch 6 taken 3 times.
✓ Branch 11 taken 33 times.
✓ Branch 12 taken 10 times.
✓ Branch 17 taken 28 times.
✓ Branch 18 taken 5 times.
46 if (this->m_enabled && this->m_currentPacketCount > 0 && this->m_flushTimeout > 0) {
95 28 ++this->m_schedCallsSinceLastPacket;
96
97
2/2
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 26 times.
28 if (this->m_schedCallsSinceLastPacket >= this->m_flushTimeout) {
98 // Flush the partial container
99 2 this->finalizeContainer();
100 2 this->m_schedCallsSinceLastPacket = 0;
101 }
102 }
103
104 // Write telemetry
105
3/4
✓ Branch 6 taken 46 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 46 times.
✓ Branch 14 taken 46 times.
46 this->tlmWrite_LoggingEnabled(this->m_enabled);
106
2/2
✓ Branch 6 taken 46 times.
✓ Branch 13 taken 46 times.
46 this->tlmWrite_NumBuffersLogged(this->m_numBuffersLogged);
107
2/2
✓ Branch 6 taken 46 times.
✓ Branch 13 taken 46 times.
46 this->tlmWrite_NumBuffersDropped(this->m_numBuffersDropped);
108
3/3
✓ Branch 6 taken 46 times.
✓ Branch 13 taken 46 times.
✓ Branch 16 taken 46 times.
46 this->tlmWrite_NumQueueDrops(static_cast<U32>(this->getNumMsgsDropped()));
109 46 }
110
111 2 void ComLoggerDp ::startRecordingIn_handler(FwIndexType portNum,
112 FwSizeType packetsPerContainer,
113 FwDpPriorityType priority) {
114 // portNum is unused
115 (void)portNum;
116
117 // Call internal helper function and check for validation failure
118
1/1
✓ Branch 2 taken 2 times.
2 const Fw::Success success = this->startRecordingInternal(packetsPerContainer, priority);
119
120 // Log warning if validation failed
121
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (success != Fw::Success::SUCCESS) {
122
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_LO_StartRecordingFailed(packetsPerContainer);
123 }
124 4 }
125
126 1 void ComLoggerDp ::stopRecordingIn_handler(FwIndexType portNum) {
127 // portNum is unused
128 (void)portNum;
129
130 // Call internal helper function
131
1/1
✓ Branch 2 taken 1 times.
1 (void)this->stopRecordingInternal();
132 1 }
133
134 // ----------------------------------------------------------------------
135 // Private helper functions
136 // ----------------------------------------------------------------------
137
138 29 Fw::Success ComLoggerDp ::startRecordingInternal(FwSizeType packetsPerContainer, FwDpPriorityType priority) {
139 // The container (header + records) is requested through Fw.BufferGet, whose size argument is a U32,
140 // so reserve the header and bound the record count to what fits in the remaining U32 range
141 29 constexpr FwSizeType MAX_PACKETS_PER_CONTAINER =
142 (static_cast<FwSizeType>(std::numeric_limits<U32>::max()) - Fw::DpContainer::MIN_PACKET_SIZE) / RECORD_SIZE;
143
4/4
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 25 times.
29 if ((packetsPerContainer == 0) || (packetsPerContainer > MAX_PACKETS_PER_CONTAINER)) {
144 // Disable logging on validation failure, flushing any partial container first
145
1/1
✓ Branch 2 taken 4 times.
4 (void)this->sendContainerIfNonEmpty();
146 4 this->m_enabled = false;
147 4 return Fw::Success::FAILURE;
148 }
149
150 // If recording is already active and there's a partial container, send it before reconfiguring
151
1/1
✓ Branch 2 taken 25 times.
25 (void)this->sendContainerIfNonEmpty();
152
153 // Store configuration
154 25 this->m_packetsPerContainer = packetsPerContainer;
155 25 this->m_priority = priority;
156
157 // Reset inactivity counter
158 25 this->m_schedCallsSinceLastPacket = 0;
159
160 // Enable logging
161 25 this->m_enabled = true;
162
163 // Log event
164 25 this->log_ACTIVITY_HI_ComDpStarted(packetsPerContainer);
165
166 25 return Fw::Success::SUCCESS;
167 }
168
169 5 ComLoggerDp_PartialContainerStatus ComLoggerDp ::stopRecordingInternal() {
170 // If there's a partial container, send it before stopping
171 5 const ComLoggerDp_PartialContainerStatus partialContainer = this->sendContainerIfNonEmpty();
172
173 // Disable logging
174 5 this->m_enabled = false;
175
176 // Reset inactivity counter
177 5 this->m_schedCallsSinceLastPacket = 0;
178
179 // Log event
180
1/1
✓ Branch 5 taken 5 times.
5 this->log_ACTIVITY_HI_ComDpStopped(partialContainer);
181
182 5 return partialContainer;
183 ✗ }
184
185 8 void ComLoggerDp ::handleBufferDrop(U32 size) {
186 8 this->log_WARNING_HI_DpBufferError(size);
187 8 ++this->m_numBuffersDropped;
188 8 }
189
190 31 Fw::Success ComLoggerDp ::allocateAndSetupContainer() {
191 // Calculate data size needed for the requested number of packets
192 // Each record holds a sentry plus up to FW_COM_BUFFER_MAX_SIZE bytes
193 // Note: DpManager adds the container header overhead, so we only request the data size
194 31 const FwSizeType containerSize = this->m_packetsPerContainer * RECORD_SIZE;
195
196 // Get a container buffer
197
2/2
✓ Branch 9 taken 31 times.
✓ Branch 12 taken 31 times.
31 const Fw::Success status = this->dpGet_ComBuffContainer(containerSize, this->m_container);
198
199 // Check for allocation failure
200
2/2
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 23 times.
31 if (status != Fw::Success::SUCCESS) {
201
1/1
✓ Branch 4 taken 8 times.
8 this->handleBufferDrop(static_cast<U32>(containerSize));
202
1/1
✓ Branch 1 taken 8 times.
8 return Fw::Success::FAILURE;
203 }
204
205 // Set the priority on the newly allocated container
206 23 this->m_container.setPriority(this->m_priority);
207
1/1
✓ Branch 1 taken 23 times.
23 return Fw::Success::SUCCESS;
208 31 }
209
210 38 void ComLoggerDp ::serializePacket(const U8* dataPtr, FwSizeType dataSize) {
211 // Create buffer with sentry followed by ComBuffer data
212 // Use sizeof to get sentry size (supports user changing the constant type)
213 38 const FwSizeType sentrySize = sizeof(ComLoggerDpSentry);
214 38 const FwSizeType totalSize = sentrySize + dataSize;
215
216 // Use F Prime serialization to insert sentry value (handles endianness automatically)
217
1/1
✓ Branch 4 taken 38 times.
38 Fw::ExternalSerializeBuffer serBuf(this->m_recordBuffer, sizeof(this->m_recordBuffer));
218
1/1
✓ Branch 2 taken 38 times.
38 Fw::SerializeStatus serStatus = serBuf.serializeFrom(ComLoggerDpSentry);
219 38 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
220
221 // Copy ComBuffer data after sentry
222
1/1
✓ Branch 2 taken 38 times.
38 serStatus = serBuf.serializeFrom(dataPtr, dataSize, Fw::Serialization::OMIT_LENGTH);
223 38 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
224
225 // Serialize the complete record into the container
226
1/1
✓ Branch 8 taken 38 times.
38 serStatus = this->m_container.serializeRecord_ComBufferRecord(this->m_recordBuffer, totalSize);
227 38 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
228 76 }
229
230 48 ComLoggerDp_PartialContainerStatus ComLoggerDp ::sendContainerIfNonEmpty() {
231 // Send container if logging is enabled and it has any packets
232 // Handles both full and partial containers
233
5/6
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 27 times.
✓ Branch 11 taken 19 times.
✓ Branch 12 taken 2 times.
48 if (this->m_enabled && this->m_currentPacketCount > 0) {
234
2/2
✓ Branch 7 taken 19 times.
✓ Branch 13 taken 19 times.
19 this->dpSend(this->m_container);
235 // Note: dpSend() invalidates the container; will allocate new one on next packet
236 19 this->m_currentPacketCount = 0;
237 19 return ComLoggerDp_PartialContainerStatus::SENT;
238 }
239 29 return ComLoggerDp_PartialContainerStatus::NOT_SENT;
240 }
241
242 14 void ComLoggerDp ::finalizeContainer() {
243 // Send the container (full or partial) and reset the packet count
244
1/1
✓ Branch 2 taken 14 times.
14 (void)this->sendContainerIfNonEmpty();
245 14 }
246
247 // ----------------------------------------------------------------------
248 // Handler implementations for commands
249 // ----------------------------------------------------------------------
250
251 23 void ComLoggerDp ::StartComDp_cmdHandler(FwOpcodeType opCode,
252 U32 cmdSeq,
253 FwSizeType packetsPerContainer,
254 FwDpPriorityType priority) {
255 // Call internal helper function
256
1/1
✓ Branch 2 taken 23 times.
23 const Fw::Success success = this->startRecordingInternal(packetsPerContainer, priority);
257
258 // Send command response
259
2/2
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 3 times.
23 if (success == Fw::Success::SUCCESS) {
260
2/2
✓ Branch 6 taken 20 times.
✓ Branch 9 taken 20 times.
20 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
261 } else {
262 // Log warning event for validation failure (consistent with port path)
263
1/1
✓ Branch 5 taken 3 times.
3 this->log_WARNING_LO_StartRecordingFailed(packetsPerContainer);
264
2/2
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
265 }
266 46 }
267
268 3 void ComLoggerDp ::UpdatePriority_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, FwDpPriorityType priority) {
269 // Store the new priority
270 3 this->m_priority = priority;
271
272 // Update priority if logging is enabled and there's an active container
273
5/6
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
3 if (this->m_enabled && (this->m_currentPacketCount > 0)) {
274 1 this->m_container.setPriority(this->m_priority);
275 }
276
277 // Log event
278 3 this->log_ACTIVITY_LO_PriorityUpdated(priority);
279
280
2/2
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
281 3 }
282
283 4 void ComLoggerDp ::StopComDp_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
284 // Call internal helper function
285
1/1
✓ Branch 2 taken 4 times.
4 (void)this->stopRecordingInternal();
286
287 // Send command response
288
2/2
✓ Branch 6 taken 4 times.
✓ Branch 9 taken 4 times.
4 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
289 4 }
290
291 3 void ComLoggerDp ::CLEAR_COUNTERS_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
292 // Clear the NumBuffersLogged counter
293 3 this->m_numBuffersLogged = 0;
294
295 // Clear the NumBuffersDropped counter
296 3 this->m_numBuffersDropped = 0;
297
298 // Clear the DpBufferError event throttle
299 3 this->log_WARNING_HI_DpBufferError_ThrottleClear();
300
301 // Log event
302 3 this->log_ACTIVITY_LO_CountersCleared();
303
304 // Send command response
305
2/2
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
306 3 }
307
308 } // namespace Svc
309