F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
ComLogger.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------
2 //
3 // ComLogger.cpp
4 //
5 // ----------------------------------------------------------------------
6 
10 #include <Os/ValidateFile.hpp>
12 #include <cstdio>
13 
14 namespace Svc {
15 static_assert(std::numeric_limits<U16>::max() <= std::numeric_limits<FwSizeType>::max(),
16  "U16 must fit in the positive range of FwSizeType");
17 // ----------------------------------------------------------------------
18 // Construction, initialization, and destruction
19 // ----------------------------------------------------------------------
20 
21 ComLogger ::ComLogger(const char* compName, const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength)
22  : ComLoggerComponentBase(compName),
23  m_maxFileSize(maxFileSize),
24  m_fileMode(CLOSED),
25  m_byteCount(0),
26  m_writeErrorOccurred(false),
27  m_openErrorOccurred(false),
28  m_storeBufferLength(storeBufferLength),
29  m_initialized(true) {
30  this->init_log_file(incomingFilePrefix, maxFileSize, storeBufferLength);
31 }
32 
33 ComLogger ::ComLogger(const char* compName)
34  : ComLoggerComponentBase(compName),
35  m_filePrefix(),
36  m_maxFileSize(0),
37  m_fileMode(CLOSED),
38  m_fileName(),
39  m_hashFileName(),
40  m_byteCount(0),
41  m_writeErrorOccurred(false),
42  m_openErrorOccurred(false),
43  m_storeBufferLength(),
44  m_initialized(false) {}
45 
46 void ComLogger ::init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength) {
47  FW_ASSERT(incomingFilePrefix != nullptr);
48  this->m_maxFileSize = maxFileSize;
49  this->m_storeBufferLength = storeBufferLength;
50  if (this->m_storeBufferLength) {
51  FW_ASSERT(maxFileSize > sizeof(U16), static_cast<FwAssertArgType>(maxFileSize));
52  }
53  // Assign the prefix checking if it is too big
54  Fw::FormatStatus formatStatus = this->m_filePrefix.format("%s", incomingFilePrefix);
55  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
56  this->m_initialized = true;
57 }
58 
60  // Close file:
61  // this->closeFile();
62  // NOTE: the above did not work because we don't want to issue an event
63  // in the destructor. This can cause "virtual method called" segmentation
64  // faults.
65  // So I am copying part of that function here.
66  if (OPEN == this->m_fileMode) {
67  // Close file:
68  this->m_file.close();
69 
70  // Write out the hash file to disk:
71  this->writeHashFile();
72 
73  // Update mode:
74  this->m_fileMode = CLOSED;
75  }
76 }
77 
78 // ----------------------------------------------------------------------
79 // Handler implementations
80 // ----------------------------------------------------------------------
81 
82 void ComLogger ::comIn_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
83  FW_ASSERT(portNum == 0);
84 
85  // Get length of buffer:
86  FwSizeType sizeNative = data.getSize();
87  // ComLogger only writes 16-bit sizes to save space
88  // on disk:
89  FW_ASSERT(sizeNative < 65536, static_cast<FwAssertArgType>(sizeNative));
90  U16 size = sizeNative & 0xFFFF;
91 
92  // Close the file if it will be too big:
93  if (OPEN == this->m_fileMode) {
94  U32 projectedByteCount = this->m_byteCount + size;
95  if (this->m_storeBufferLength) {
96  projectedByteCount += static_cast<U32>(sizeof(size));
97  }
98  if (projectedByteCount > this->m_maxFileSize) {
99  this->closeFile();
100  }
101  }
102 
103  // Open the file if it there is not one open:
104  if (CLOSED == this->m_fileMode) {
105  this->openFile();
106  }
107 
108  // Write to the file if it is open:
109  if (OPEN == this->m_fileMode) {
110  this->writeComBufferToFile(data, size);
111  }
112 }
113 
114 void ComLogger ::CloseFile_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
115  this->closeFile();
116  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
117 }
118 
119 void ComLogger ::pingIn_handler(const FwIndexType portNum, U32 key) {
120  // return key
121  this->pingOut_out(0, key);
122 }
123 
124 void ComLogger ::openFile() {
125  FW_ASSERT(CLOSED == this->m_fileMode);
126 
127  if (!this->m_initialized) {
129  return;
130  }
131 
132  // Create filename:
133  Fw::Time timestamp = getTime();
134  Fw::FormatStatus formatStatus = this->m_fileName.format(
135  "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com", this->m_filePrefix.toChar(),
136  static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds());
137  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
138  formatStatus =
139  this->m_hashFileName.format("%s%s", this->m_fileName.toChar(), Utils::Hash::getFileExtensionString());
140  FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
141 
142  Os::File::Status ret = m_file.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE);
143  if (Os::File::OP_OK != ret) {
144  if (!this->m_openErrorOccurred) { // throttle this event, otherwise a positive
145  // feedback event loop can occur!
146  this->log_WARNING_HI_FileOpenError(ret, this->m_fileName);
147  }
148  this->m_openErrorOccurred = true;
149  } else {
150  // Reset event throttle:
151  this->m_openErrorOccurred = false;
152 
153  // Reset byte count:
154  this->m_byteCount = 0;
155 
156  // Set mode:
157  this->m_fileMode = OPEN;
158  }
159 }
160 
161 void ComLogger ::closeFile() {
162  if (OPEN == this->m_fileMode) {
163  // Close file:
164  this->m_file.close();
165 
166  // Write out the hash file to disk:
167  this->writeHashFile();
168 
169  // Update mode:
170  this->m_fileMode = CLOSED;
171 
172  // Send event:
173  this->log_DIAGNOSTIC_FileClosed(this->m_fileName);
174  }
175 }
176 
177 void ComLogger ::writeComBufferToFile(Fw::ComBuffer& data, U16 size) {
178  if (this->m_storeBufferLength) {
179  U8 buffer[sizeof(size)];
180  Fw::SerialBuffer serialLength(&buffer[0], sizeof(size));
181  Fw::SerializeStatus serStatus = serialLength.serializeFrom(size);
182  FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
183  const bool lengthWritten =
184  this->writeToFile(serialLength.getBuffAddr(), static_cast<U16>(serialLength.getSize()));
185  if (lengthWritten) {
186  this->m_byteCount += static_cast<U32>(serialLength.getSize());
187  } else {
188  return;
189  }
190  }
191 
192  // Write buffer to file:
193  const bool dataWritten = this->writeToFile(data.getBuffAddr(), size);
194  if (dataWritten) {
195  this->m_byteCount += size;
196  }
197 }
198 
199 bool ComLogger ::writeToFile(void* data, U16 length) {
200  FwSizeType size = length;
201  Os::File::Status ret = m_file.write(reinterpret_cast<const U8*>(data), size);
202  if ((Os::File::OP_OK != ret) || (size != length)) {
203  if (!this->m_writeErrorOccurred) { // throttle this event, otherwise a positive
204  // feedback event loop can occur!
205  this->log_WARNING_HI_FileWriteError(ret, static_cast<U32>(size), length, this->m_fileName);
206  }
207  this->m_writeErrorOccurred = true;
208  return false;
209  }
210 
211  this->m_writeErrorOccurred = false;
212  return true;
213 }
214 
215 void ComLogger ::writeHashFile() {
216  Os::ValidateFile::Status validateStatus;
217  validateStatus = Os::ValidateFile::createValidation(this->m_fileName.toChar(), this->m_hashFileName.toChar());
218  if (Os::ValidateFile::VALIDATION_OK != validateStatus) {
219  this->log_WARNING_LO_FileValidationError(this->m_fileName, this->m_hashFileName, validateStatus);
220  }
221 }
222 } // namespace Svc
Serialization/Deserialization operation was successful.
A variable-length serializable buffer.
FwIdType FwOpcodeType
The type of a command opcode.
PlatformSizeType FwSizeType
void log_WARNING_LO_FileNotInitialized()
Log event FileNotInitialized.
void log_DIAGNOSTIC_FileClosed(const Fw::StringBase &file) const
Serializable::SizeType getSize() const override
Get current buffer size.
Open file for writing.
Definition: File.hpp:35
TimeBase getTimeBase() const
Definition: Time.cpp:136
void init_log_file(const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition: ComLogger.cpp:46
SerializeStatus
forward declaration for string
The validation of the file passed.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:50
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
void log_WARNING_HI_FileOpenError(U32 errornum, const Fw::StringBase &file) const
U32 getSeconds() const
Definition: Time.cpp:128
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void log_WARNING_HI_FileWriteError(U32 errornum, U32 bytesWritten, U32 bytesToWrite, const Fw::StringBase &file) const
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:97
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:213
static const char * getFileExtensionString()
Definition: HashCommon.cpp:5
const char * toChar() const
Convert to a C-style char*.
#define PRI_FwTimeBaseStoreType
void pingOut_out(FwIndexType portNum, U32 key) const
Invoke output port pingOut.
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
Definition: StringBase.cpp:58
Command successfully executed.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)
void log_WARNING_LO_FileValidationError(const Fw::StringBase &validationFile, const Fw::StringBase &file, U32 status) const
Operation was successful.
Definition: File.hpp:42
U32 getUSeconds() const
Definition: Time.cpp:132
Defines a file class to validate files or generate a file validator file.
PlatformIndexType FwIndexType
RateGroupDivider component implementation.
U16 FwTimeBaseStoreType
The type used to serialize a time base value.
ComLogger(const char *compName, const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition: ComLogger.cpp:21
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Auto-generated base for ComLogger component.
FormatStatus
status of string format calls
Definition: format.hpp:18