GCC Code Coverage Report


Directory: Svc/BufferLogger/
File: BufferLoggerFile.cpp
Date: 2026-09-03 21:16:16
Exec Total Coverage
Lines: 109 118 92.4%
Functions: 12 13 92.3%
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 14 BufferLogger::File ::File(BufferLogger& bufferLogger)
24 14 : m_bufferLogger(bufferLogger),
25 14 m_prefix(""),
26
1/1
✓ Branch 4 taken 14 times.
14 m_suffix(""),
27
1/1
✓ Branch 4 taken 14 times.
14 m_baseName(""),
28 14 m_fileCounter(0),
29 14 m_maxSize(0),
30 14 m_sizeOfSize(0),
31 14 m_mode(Mode::CLOSED),
32
3/3
✓ Branch 4 taken 14 times.
✓ Branch 10 taken 14 times.
✓ Branch 18 taken 14 times.
28 m_bytesWritten(0) {}
33
34 84 BufferLogger::File ::~File() {
35 14 this->close();
36 84 }
37
38 // ----------------------------------------------------------------------
39 // Public functions
40 // ----------------------------------------------------------------------
41
42 13 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 13 FW_ASSERT(this->m_mode == File::Mode::CLOSED);
48
49 13 this->m_prefix = logFilePrefix;
50 13 this->m_suffix = logFileSuffix;
51 13 this->m_maxSize = maxFileSize;
52 13 this->m_sizeOfSize = sizeOfSize;
53
54 13 FW_ASSERT(sizeOfSize <= sizeof(FwSizeType), static_cast<FwAssertArgType>(sizeOfSize));
55 13 FW_ASSERT(m_maxSize > sizeOfSize, static_cast<FwAssertArgType>(m_maxSize));
56 13 }
57
58 2 void BufferLogger::File ::setBaseName(const Fw::ConstStringBase& baseName) {
59
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (this->m_mode == File::Mode::OPEN) {
60 this->closeAndEmitEvent();
61 }
62 2 this->m_baseName = baseName;
63 2 this->m_fileCounter = 0;
64 2 this->open();
65 2 }
66
67 61 void BufferLogger::File ::logBuffer(const U8* const data, const FwSizeType size) {
68 61 FW_ASSERT(data != nullptr);
69 // Close the file if it will be too big
70
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 14 times.
61 if (this->m_mode == File::Mode::OPEN) {
71 47 const FwSizeType projectedByteCount = this->m_bytesWritten + this->m_sizeOfSize + size;
72
2/2
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 41 times.
47 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 61 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 41 times.
61 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 61 times.
✓ Branch 3 taken 52 times.
✓ Branch 4 taken 9 times.
61 if (this->m_mode == File::Mode::OPEN) {
82 52 (void)this->writeBuffer(data, size);
83 }
84 61 }
85
86 17 void BufferLogger::File ::closeAndEmitEvent() {
87
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 6 times.
17 if (this->m_mode == File::Mode::OPEN) {
88
1/1
✓ Branch 2 taken 11 times.
11 this->close();
89
1/1
✓ Branch 8 taken 11 times.
11 Fw::LogStringArg logStringArg(this->m_name.toChar());
90
1/1
✓ Branch 6 taken 11 times.
11 this->m_bufferLogger.log_DIAGNOSTIC_BL_LogFileClosed(logStringArg);
91 11 }
92 17 }
93
94 // ----------------------------------------------------------------------
95 // Private functions
96 // ----------------------------------------------------------------------
97
98 23 void BufferLogger::File ::open() {
99 23 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 23 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 23 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 20 times.
46 if ((this->m_baseName.toChar()[0] == '\0') || (this->m_sizeOfSize > sizeof(FwSizeType)) ||
103
2/2
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 20 times.
23 (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 10 times.
✓ Branch 3 taken 10 times.
20 if (this->m_fileCounter == 0) {
110 formatStatus =
111 10 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 20 times.
20 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 20 const Os::File::Status status = this->m_osFile.open(this->m_name.toChar(), Os::File::OPEN_WRITE);
122
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
20 if (status == Os::File::OP_OK) {
123 14 this->m_fileCounter++;
124 // Reset bytes written
125 14 this->m_bytesWritten = 0;
126 // Initialize incremental hash
127 14 this->m_hash.init();
128 // Set mode
129 14 this->m_mode = File::Mode::OPEN;
130 } else {
131
1/1
✓ Branch 8 taken 6 times.
6 Fw::LogStringArg string(this->m_name.toChar());
132
1/1
✓ Branch 6 taken 6 times.
6 this->m_bufferLogger.log_WARNING_HI_BL_LogFileOpenError(status, string);
133 6 }
134 }
135
136 52 bool BufferLogger::File ::writeBuffer(const U8* const data, const FwSizeType size) {
137 52 bool status = this->writeSize(size);
138
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
52 if (status) {
139 48 status = this->writeBytes(data, size);
140 }
141 52 return status;
142 }
143
144 52 bool BufferLogger::File ::writeSize(const FwSizeType size) {
145 52 FW_ASSERT(this->m_sizeOfSize <= sizeof(FwSizeType));
146 // Reject sizes that do not fit in sizeOfSize bytes; writing the low bytes would corrupt the log
147
4/8
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 52 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 52 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 52 times.
52 if ((this->m_sizeOfSize < sizeof(FwSizeType)) && ((size >> (8 * this->m_sizeOfSize)) != 0)) {
148 Fw::LogStringArg string(this->m_name.toChar());
149 this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(Os::File::INVALID_ARGUMENT, 0, static_cast<U32>(size),
150 string);
151 return false;
152 }
153 52 U8 sizeBuffer[sizeof(FwSizeType)];
154 52 FwSizeType sizeRegister = size;
155
2/2
✓ Branch 2 taken 208 times.
✓ Branch 3 taken 52 times.
260 for (U8 i = 0; i < this->m_sizeOfSize; ++i) {
156 208 sizeBuffer[this->m_sizeOfSize - i - 1] = sizeRegister & 0xFF;
157 208 sizeRegister >>= 8;
158 }
159
1/1
✓ Branch 4 taken 52 times.
52 const bool status = this->writeBytes(sizeBuffer, this->m_sizeOfSize);
160 52 return status;
161 }
162
163 100 bool BufferLogger::File ::writeBytes(const void* const data, const FwSizeType length) {
164 100 FwSizeType size = length;
165
1/1
✓ Branch 6 taken 100 times.
100 const Os::File::Status fileStatus = this->m_osFile.write(reinterpret_cast<const U8*>(data), size);
166 bool status;
167
3/4
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
100 if (fileStatus == Os::File::OP_OK && static_cast<FwSizeType>(size) == length) {
168 96 this->m_bytesWritten += length;
169
1/1
✓ Branch 4 taken 96 times.
96 this->m_hash.update(data, length);
170 96 status = true;
171 } else {
172
1/1
✓ Branch 8 taken 4 times.
4 Fw::LogStringArg string(this->m_name.toChar());
173
174
1/1
✓ Branch 6 taken 4 times.
4 this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(fileStatus, static_cast<U32>(size),
175 static_cast<U32>(length), string);
176 4 status = false;
177 4 }
178 100 return status;
179 }
180
181 13 void BufferLogger::File ::writeHashFile() {
182 // Finalize the incrementally computed hash
183
1/1
✓ Branch 2 taken 13 times.
13 Utils::HashBuffer hashBuffer;
184
1/1
✓ Branch 4 taken 13 times.
13 this->m_hash.finalize(hashBuffer);
185
186 // Write hash file via ValidatedFile
187
1/1
✓ Branch 8 taken 13 times.
13 Os::ValidatedFile validatedFile(this->m_name.toChar());
188
1/1
✓ Branch 1 taken 13 times.
13 const Os::ValidateFile::Status status = validatedFile.createHashFile(hashBuffer);
189
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (status != Os::ValidateFile::VALIDATION_OK) {
190
3/3
✓ Branch 2 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 14 taken 1 times.
1 Fw::LogStringArg logStringArg(validatedFile.getHashFileName().toChar());
191
1/1
✓ Branch 6 taken 1 times.
1 this->m_bufferLogger.log_WARNING_HI_BL_LogFileValidationError(logStringArg, status);
192 1 }
193 26 }
194
195 bool BufferLogger::File ::flush() {
196 // Unbuffered file I/O requires no flush; flush the Os::File here if using buffered I/O
197 return true;
198 }
199
200 26 void BufferLogger::File ::close() {
201
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 13 times.
26 if (this->m_mode == File::Mode::OPEN) {
202 // Close file
203 13 this->m_osFile.close();
204 // Write out the hash file to disk
205 13 this->writeHashFile();
206 // Update mode
207 13 this->m_mode = File::Mode::CLOSED;
208 }
209 26 }
210
211 } // namespace Svc
212