GCC Code Coverage Report


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