GCC Code Coverage Report


Directory: Svc/BufferLogger/
File: BufferLoggerFile.cpp
Date: 2026-10-14 21:17:35
Exec Total Coverage
Lines: 111 118 94.1%
Functions: 13 13 100.0%
Branches: 66 85 77.6%

Line Branch Exec Source
1 // ======================================================================
2 // \title BufferLoggerFile.cpp
3 // \author bocchino, dinkel, mereweth
4 // \brief Implementation for Svc::BufferLogger::BufferLoggerFile
5 //
6 // \copyright
7 // Copyright (C) 2015-2017 California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12
13 #include "Os/ValidatedFile.hpp"
14 #include "Svc/BufferLogger/BufferLogger.hpp"
15 #include "Utils/Hash/Hash.hpp"
16
17 namespace Svc {
18
19 // ----------------------------------------------------------------------
20 // Constructors and destructors
21 // ----------------------------------------------------------------------
22
23 18 BufferLogger::File ::File(BufferLogger& bufferLogger)
24 18 : m_bufferLogger(bufferLogger),
25 18 m_prefix(""),
26
1/1
✓ Branch 4 taken 18 times.
18 m_suffix(""),
27
1/1
✓ Branch 4 taken 18 times.
18 m_baseName(""),
28 18 m_fileCounter(0),
29 18 m_maxSize(0),
30 18 m_sizeOfSize(0),
31 18 m_mode(Mode::CLOSED),
32
3/3
✓ Branch 4 taken 18 times.
✓ Branch 10 taken 18 times.
✓ Branch 18 taken 18 times.
36 m_bytesWritten(0) {}
33
34 108 BufferLogger::File ::~File() {
35 18 this->close();
36 108 }
37
38 // ----------------------------------------------------------------------
39 // Public functions
40 // ----------------------------------------------------------------------
41
42 17 void BufferLogger::File ::init(const char* const logFilePrefix,
43 const char* const logFileSuffix,
44 const FwSizeType maxFileSize,
45 const U8 sizeOfSize) {
46 // NOTE(mereweth) - only call this before opening the file
47 17 FW_ASSERT(this->m_mode == File::Mode::CLOSED);
48
49 17 this->m_prefix = logFilePrefix;
50 17 this->m_suffix = logFileSuffix;
51 17 this->m_maxSize = maxFileSize;
52 17 this->m_sizeOfSize = sizeOfSize;
53
54 17 FW_ASSERT(sizeOfSize <= sizeof(FwSizeType), static_cast<FwAssertArgType>(sizeOfSize));
55 17 FW_ASSERT(m_maxSize > sizeOfSize, static_cast<FwAssertArgType>(m_maxSize));
56 17 }
57
58 4 void BufferLogger::File ::setBaseName(const Fw::ConstStringBase& baseName) {
59
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 if (this->m_mode == File::Mode::OPEN) {
60 ✗ this->closeAndEmitEvent();
61 }
62 4 this->m_baseName = baseName;
63 4 this->m_fileCounter = 0;
64 4 this->open();
65 4 }
66
67 68 void BufferLogger::File ::logBuffer(const U8* const data, const FwSizeType size) {
68 68 FW_ASSERT(data != nullptr);
69 // Close the file if it will be too big
70
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 54 times.
✓ Branch 4 taken 14 times.
68 if (this->m_mode == File::Mode::OPEN) {
71 54 const FwSizeType projectedByteCount = this->m_bytesWritten + this->m_sizeOfSize + size;
72
2/2
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 48 times.
54 if (projectedByteCount > this->m_maxSize) {
73 6 this->closeAndEmitEvent();
74 }
75 }
76 // Open a file if necessary
77
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 48 times.
68 if (this->m_mode == File::Mode::CLOSED) {
78 20 this->open();
79 }
80 // Write to the file if it is open
81
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 59 times.
✓ Branch 4 taken 9 times.
68 if (this->m_mode == File::Mode::OPEN) {
82 59 (void)this->writeBuffer(data, size);
83 }
84 68 }
85
86 19 void BufferLogger::File ::closeAndEmitEvent() {
87
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 6 times.
19 if (this->m_mode == File::Mode::OPEN) {
88
1/1
✓ Branch 2 taken 13 times.
13 this->close();
89
1/1
✓ Branch 8 taken 13 times.
13 Fw::LogStringArg logStringArg(this->m_name.toChar());
90
1/1
✓ Branch 6 taken 13 times.
13 this->m_bufferLogger.log_DIAGNOSTIC_BL_LogFileClosed(logStringArg);
91 13 }
92 19 }
93
94 // ----------------------------------------------------------------------
95 // Private functions
96 // ----------------------------------------------------------------------
97
98 25 void BufferLogger::File ::open() {
99 25 FW_ASSERT(this->m_mode == File::Mode::CLOSED);
100
101 // NOTE(mereweth) - check that file path has been set and that initLog has been called
102
4/6
✓ Branch 7 taken 25 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 25 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 22 times.
50 if ((this->m_baseName.toChar()[0] == '\0') || (this->m_sizeOfSize > sizeof(FwSizeType)) ||
103
2/2
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 22 times.
25 (this->m_maxSize <= this->m_sizeOfSize)) {
104 3 this->m_bufferLogger.log_WARNING_HI_BL_NoLogFileOpenInitError();
105 3 return;
106 }
107
108 Fw::FormatStatus formatStatus;
109
2/2
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 10 times.
22 if (this->m_fileCounter == 0) {
110 formatStatus =
111 12 this->m_name.format("%s%s%s", this->m_prefix.toChar(), this->m_baseName.toChar(), this->m_suffix.toChar());
112 } else {
113 30 formatStatus = this->m_name.format("%s%s%" PRI_FwSizeType "%s", this->m_prefix.toChar(),
114 20 this->m_baseName.toChar(), this->m_fileCounter, this->m_suffix.toChar());
115 }
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (formatStatus != Fw::FormatStatus::SUCCESS) {
117 ✗ this->m_bufferLogger.log_WARNING_HI_BL_LogFileNameError(static_cast<Fw::StringFormatStatus::T>(formatStatus));
118 ✗ return;
119 }
120
121 const Os::File::Status status =
122 22 this->m_osFile.open(this->m_name.toChar(), Os::File::OPEN_CREATE, Os::File::OVERWRITE);
123
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 if (status == Os::File::OP_OK) {
124 16 this->m_fileCounter++;
125 // Reset bytes written
126 16 this->m_bytesWritten = 0;
127 // Initialize incremental hash
128 16 this->m_hash.init();
129 // Set mode
130 16 this->m_mode = File::Mode::OPEN;
131 } else {
132
1/1
✓ Branch 8 taken 6 times.
6 Fw::LogStringArg string(this->m_name.toChar());
133
1/1
✓ Branch 6 taken 6 times.
6 this->m_bufferLogger.log_WARNING_HI_BL_LogFileOpenError(status, string);
134 6 }
135 }
136
137 59 bool BufferLogger::File ::writeBuffer(const U8* const data, const FwSizeType size) {
138 59 bool status = this->writeSize(size);
139
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 4 times.
59 if (status) {
140 55 status = this->writeBytes(data, size);
141 }
142 59 return status;
143 }
144
145 59 bool BufferLogger::File ::writeSize(const FwSizeType size) {
146 59 FW_ASSERT(this->m_sizeOfSize <= sizeof(FwSizeType));
147 // Reject sizes that do not fit in sizeOfSize bytes; writing the low bytes would corrupt the log
148
4/8
✓ Branch 2 taken 59 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 59 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 59 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 59 times.
59 if ((this->m_sizeOfSize < sizeof(FwSizeType)) && ((size >> (8 * this->m_sizeOfSize)) != 0)) {
149 ✗ Fw::LogStringArg string(this->m_name.toChar());
150 ✗ this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(Os::File::INVALID_ARGUMENT, 0, static_cast<U32>(size),
151 string);
152 ✗ return false;
153 ✗ }
154 59 U8 sizeBuffer[sizeof(FwSizeType)];
155 59 FwSizeType sizeRegister = size;
156
2/2
✓ Branch 2 taken 236 times.
✓ Branch 3 taken 59 times.
295 for (U8 i = 0; i < this->m_sizeOfSize; ++i) {
157 236 sizeBuffer[this->m_sizeOfSize - i - 1] = sizeRegister & 0xFF;
158 236 sizeRegister >>= 8;
159 }
160
1/1
✓ Branch 4 taken 59 times.
59 const bool status = this->writeBytes(sizeBuffer, this->m_sizeOfSize);
161 59 return status;
162 }
163
164 114 bool BufferLogger::File ::writeBytes(const void* const data, const FwSizeType length) {
165 114 FwSizeType size = length;
166
1/1
✓ Branch 6 taken 114 times.
114 const Os::File::Status fileStatus = this->m_osFile.write(reinterpret_cast<const U8*>(data), size);
167 bool status;
168
3/4
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 110 times.
✗ Branch 3 not taken.
114 if (fileStatus == Os::File::OP_OK && static_cast<FwSizeType>(size) == length) {
169 110 this->m_bytesWritten += length;
170
1/1
✓ Branch 4 taken 110 times.
110 this->m_hash.update(data, length);
171 110 status = true;
172 } else {
173
1/1
✓ Branch 8 taken 4 times.
4 Fw::LogStringArg string(this->m_name.toChar());
174
175
1/1
✓ Branch 6 taken 4 times.
4 this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(fileStatus, static_cast<U32>(size),
176 static_cast<U32>(length), string);
177 4 status = false;
178 4 }
179 114 return status;
180 }
181
182 15 void BufferLogger::File ::writeHashFile() {
183 // Finalize the incrementally computed hash
184
1/1
✓ Branch 2 taken 15 times.
15 Utils::HashBuffer hashBuffer;
185
1/1
✓ Branch 4 taken 15 times.
15 this->m_hash.finalize(hashBuffer);
186
187 // Write hash file via ValidatedFile
188
1/1
✓ Branch 8 taken 15 times.
15 Os::ValidatedFile validatedFile(this->m_name.toChar());
189
1/1
✓ Branch 1 taken 15 times.
15 const Os::ValidateFile::Status status = validatedFile.createHashFile(hashBuffer);
190
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (status != Os::ValidateFile::VALIDATION_OK) {
191
3/3
✓ Branch 2 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 14 taken 1 times.
1 Fw::LogStringArg logStringArg(validatedFile.getHashFileName().toChar());
192
1/1
✓ Branch 6 taken 1 times.
1 this->m_bufferLogger.log_WARNING_HI_BL_LogFileValidationError(logStringArg, status);
193 1 }
194 30 }
195
196 2 bool BufferLogger::File ::flush() {
197 // Unbuffered file I/O requires no flush; flush the Os::File here if using buffered I/O
198 2 return true;
199 }
200
201 32 void BufferLogger::File ::close() {
202
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 17 times.
32 if (this->m_mode == File::Mode::OPEN) {
203 // Close file
204 15 this->m_osFile.close();
205 // Write out the hash file to disk
206 15 this->writeHashFile();
207 // Update mode
208 15 this->m_mode = File::Mode::CLOSED;
209 }
210 32 }
211
212 } // namespace Svc
213