GCC Code Coverage Report


Directory: ./
File: Svc/BufferLogger/BufferLoggerFile.cpp
Date: 2026-09-23 22:11:34
Exec Total Coverage
Lines: 0 116 0.0%
Functions: 0 13 0.0%
Branches: 0 69 0.0%

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 ✗ BufferLogger::File ::File(BufferLogger& bufferLogger)
24 ✗ : m_bufferLogger(bufferLogger),
25 ✗ m_prefix(""),
26 ✗ m_suffix(""),
27 ✗ m_baseName(""),
28 ✗ m_fileCounter(0),
29 ✗ m_maxSize(0),
30 ✗ m_sizeOfSize(0),
31 ✗ m_mode(Mode::CLOSED),
32 ✗ m_bytesWritten(0) {}
33
34 ✗ BufferLogger::File ::~File() {
35 ✗ this->close();
36 ✗ }
37
38 // ----------------------------------------------------------------------
39 // Public functions
40 // ----------------------------------------------------------------------
41
42 ✗ 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 ✗ FW_ASSERT(this->m_mode == File::Mode::CLOSED);
48
49 ✗ this->m_prefix = logFilePrefix;
50 ✗ this->m_suffix = logFileSuffix;
51 ✗ this->m_maxSize = maxFileSize;
52 ✗ this->m_sizeOfSize = sizeOfSize;
53
54 ✗ FW_ASSERT(sizeOfSize <= sizeof(FwSizeType), static_cast<FwAssertArgType>(sizeOfSize));
55 ✗ FW_ASSERT(m_maxSize > sizeOfSize, static_cast<FwAssertArgType>(m_maxSize));
56 ✗ }
57
58 ✗ void BufferLogger::File ::setBaseName(const Fw::ConstStringBase& baseName) {
59 ✗ if (this->m_mode == File::Mode::OPEN) {
60 ✗ this->closeAndEmitEvent();
61 }
62 ✗ this->m_baseName = baseName;
63 ✗ this->m_fileCounter = 0;
64 ✗ this->open();
65 ✗ }
66
67 ✗ void BufferLogger::File ::logBuffer(const U8* const data, const FwSizeType size) {
68 ✗ FW_ASSERT(data != nullptr);
69 // Close the file if it will be too big
70 ✗ if (this->m_mode == File::Mode::OPEN) {
71 ✗ const FwSizeType projectedByteCount = this->m_bytesWritten + this->m_sizeOfSize + size;
72 ✗ if (projectedByteCount > this->m_maxSize) {
73 ✗ this->closeAndEmitEvent();
74 }
75 }
76 // Open a file if necessary
77 ✗ if (this->m_mode == File::Mode::CLOSED) {
78 ✗ this->open();
79 }
80 // Write to the file if it is open
81 ✗ if (this->m_mode == File::Mode::OPEN) {
82 ✗ (void)this->writeBuffer(data, size);
83 }
84 ✗ }
85
86 ✗ void BufferLogger::File ::closeAndEmitEvent() {
87 ✗ if (this->m_mode == File::Mode::OPEN) {
88 ✗ this->close();
89 ✗ Fw::LogStringArg logStringArg(this->m_name.toChar());
90 ✗ this->m_bufferLogger.log_DIAGNOSTIC_BL_LogFileClosed(logStringArg);
91 ✗ }
92 ✗ }
93
94 // ----------------------------------------------------------------------
95 // Private functions
96 // ----------------------------------------------------------------------
97
98 ✗ void BufferLogger::File ::open() {
99 ✗ 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 ✗ if ((this->m_baseName.toChar()[0] == '\0') || (this->m_sizeOfSize > sizeof(FwSizeType)) ||
103 ✗ (this->m_maxSize <= this->m_sizeOfSize)) {
104 ✗ this->m_bufferLogger.log_WARNING_HI_BL_NoLogFileOpenInitError();
105 ✗ return;
106 }
107
108 Fw::FormatStatus formatStatus;
109 ✗ if (this->m_fileCounter == 0) {
110 formatStatus =
111 ✗ this->m_name.format("%s%s%s", this->m_prefix.toChar(), this->m_baseName.toChar(), this->m_suffix.toChar());
112 } else {
113 ✗ formatStatus = this->m_name.format("%s%s%" PRI_FwSizeType "%s", this->m_prefix.toChar(),
114 this->m_baseName.toChar(), this->m_fileCounter, this->m_suffix.toChar());
115 }
116 ✗ 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 ✗ this->m_osFile.open(this->m_name.toChar(), Os::File::OPEN_CREATE, Os::File::OVERWRITE);
123 ✗ if (status == Os::File::OP_OK) {
124 ✗ this->m_fileCounter++;
125 // Reset bytes written
126 ✗ this->m_bytesWritten = 0;
127 // Initialize incremental hash
128 ✗ this->m_hash.init();
129 // Set mode
130 ✗ this->m_mode = File::Mode::OPEN;
131 } else {
132 ✗ Fw::LogStringArg string(this->m_name.toChar());
133 ✗ this->m_bufferLogger.log_WARNING_HI_BL_LogFileOpenError(status, string);
134 ✗ }
135 }
136
137 ✗ bool BufferLogger::File ::writeBuffer(const U8* const data, const FwSizeType size) {
138 ✗ bool status = this->writeSize(size);
139 ✗ if (status) {
140 ✗ status = this->writeBytes(data, size);
141 }
142 ✗ return status;
143 }
144
145 ✗ bool BufferLogger::File ::writeSize(const FwSizeType size) {
146 ✗ 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 ✗ 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 U8 sizeBuffer[sizeof(FwSizeType)];
155 ✗ FwSizeType sizeRegister = size;
156 ✗ for (U8 i = 0; i < this->m_sizeOfSize; ++i) {
157 ✗ sizeBuffer[this->m_sizeOfSize - i - 1] = sizeRegister & 0xFF;
158 ✗ sizeRegister >>= 8;
159 }
160 ✗ const bool status = this->writeBytes(sizeBuffer, this->m_sizeOfSize);
161 ✗ return status;
162 }
163
164 ✗ bool BufferLogger::File ::writeBytes(const void* const data, const FwSizeType length) {
165 ✗ FwSizeType size = length;
166 ✗ const Os::File::Status fileStatus = this->m_osFile.write(reinterpret_cast<const U8*>(data), size);
167 bool status;
168 ✗ if (fileStatus == Os::File::OP_OK && static_cast<FwSizeType>(size) == length) {
169 ✗ this->m_bytesWritten += length;
170 ✗ this->m_hash.update(data, length);
171 ✗ status = true;
172 } else {
173 ✗ Fw::LogStringArg string(this->m_name.toChar());
174
175 ✗ this->m_bufferLogger.log_WARNING_HI_BL_LogFileWriteError(fileStatus, static_cast<U32>(size),
176 static_cast<U32>(length), string);
177 ✗ status = false;
178 ✗ }
179 ✗ return status;
180 }
181
182 ✗ void BufferLogger::File ::writeHashFile() {
183 // Finalize the incrementally computed hash
184 ✗ Utils::HashBuffer hashBuffer;
185 ✗ this->m_hash.finalize(hashBuffer);
186
187 // Write hash file via ValidatedFile
188 ✗ Os::ValidatedFile validatedFile(this->m_name.toChar());
189 ✗ const Os::ValidateFile::Status status = validatedFile.createHashFile(hashBuffer);
190 ✗ if (status != Os::ValidateFile::VALIDATION_OK) {
191 ✗ Fw::LogStringArg logStringArg(validatedFile.getHashFileName().toChar());
192 ✗ this->m_bufferLogger.log_WARNING_HI_BL_LogFileValidationError(logStringArg, status);
193 ✗ }
194 ✗ }
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 ✗ void BufferLogger::File ::close() {
202 ✗ if (this->m_mode == File::Mode::OPEN) {
203 // Close file
204 ✗ this->m_osFile.close();
205 // Write out the hash file to disk
206 ✗ this->writeHashFile();
207 // Update mode
208 ✗ this->m_mode = File::Mode::CLOSED;
209 }
210 ✗ }
211
212 } // namespace Svc
213