F´ Flight Software - C/C++ Documentation  devel
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 
8 #include <FpConfig.hpp>
10 #include <Fw/Types/StringUtils.hpp>
11 #include <Os/ValidateFile.hpp>
12 #include <cstdio>
13 
14 namespace Svc {
15 
16  // ----------------------------------------------------------------------
17  // Construction, initialization, and destruction
18  // ----------------------------------------------------------------------
19 
21  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  {
31  this->init_log_file(incomingFilePrefix, maxFileSize, storeBufferLength);
32  }
33 
35  ComLogger(const char* compName) :
36  ComLoggerComponentBase(compName),
37  m_filePrefix(),
38  m_maxFileSize(0),
39  m_fileMode(CLOSED),
40  m_fileName(),
41  m_hashFileName(),
42  m_byteCount(0),
43  m_writeErrorOccurred(false),
44  m_openErrorOccurred(false),
45  m_storeBufferLength(),
46  m_initialized(false)
47  {
48  }
49 
51  init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength)
52  {
53  FW_ASSERT(incomingFilePrefix != nullptr);
54  this->m_maxFileSize = maxFileSize;
55  this->m_storeBufferLength = storeBufferLength;
56  if( this->m_storeBufferLength ) {
57  FW_ASSERT(maxFileSize > sizeof(U16), static_cast<FwAssertArgType>(maxFileSize));
58  }
59 
60  FW_ASSERT(Fw::StringUtils::string_length(incomingFilePrefix, static_cast<FwSizeType>(sizeof(this->m_filePrefix))) < sizeof(this->m_filePrefix),
61  static_cast<FwAssertArgType>(Fw::StringUtils::string_length(incomingFilePrefix, static_cast<FwSizeType>(sizeof(this->m_filePrefix)))),
62  static_cast<FwAssertArgType>(sizeof(this->m_filePrefix))); // ensure that file prefix is not too big
63 
64  (void)Fw::StringUtils::string_copy(this->m_filePrefix, incomingFilePrefix, static_cast<FwSizeType>(sizeof(this->m_filePrefix)));
65 
66  this->m_initialized = true;
67  }
68 
69 
72  {
73  // Close file:
74  // this->closeFile();
75  // NOTE: the above did not work because we don't want to issue an event
76  // in the destructor. This can cause "virtual method called" segmentation
77  // faults.
78  // So I am copying part of that function here.
79  if( OPEN == this->m_fileMode ) {
80  // Close file:
81  this->m_file.close();
82 
83  // Write out the hash file to disk:
84  this->writeHashFile();
85 
86  // Update mode:
87  this->m_fileMode = CLOSED;
88 
89  // Send event:
90  //Fw::LogStringArg logStringArg((char*) fileName);
91  //this->log_DIAGNOSTIC_FileClosed(logStringArg);
92  }
93  }
94 
95  // ----------------------------------------------------------------------
96  // Handler implementations
97  // ----------------------------------------------------------------------
98 
99  void ComLogger ::
100  comIn_handler(
101  NATIVE_INT_TYPE portNum,
102  Fw::ComBuffer &data,
103  U32 context
104  )
105  {
106  FW_ASSERT(portNum == 0);
107 
108  // Get length of buffer:
109  U32 size32 = data.getBuffLength();
110  // ComLogger only writes 16-bit sizes to save space
111  // on disk:
112  FW_ASSERT(size32 < 65536, static_cast<FwAssertArgType>(size32));
113  U16 size = size32 & 0xFFFF;
114 
115  // Close the file if it will be too big:
116  if( OPEN == this->m_fileMode ) {
117  U32 projectedByteCount = this->m_byteCount + size;
118  if( this->m_storeBufferLength ) {
119  projectedByteCount += static_cast<U32>(sizeof(size));
120  }
121  if( projectedByteCount > this->m_maxFileSize ) {
122  this->closeFile();
123  }
124  }
125 
126  // Open the file if it there is not one open:
127  if( CLOSED == this->m_fileMode ){
128  this->openFile();
129  }
130 
131  // Write to the file if it is open:
132  if( OPEN == this->m_fileMode ) {
133  this->writeComBufferToFile(data, size);
134  }
135  }
136 
137  void ComLogger ::
138  CloseFile_cmdHandler(
139  FwOpcodeType opCode,
140  U32 cmdSeq
141  )
142  {
143  this->closeFile();
144  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
145  }
146 
147  void ComLogger ::
148  pingIn_handler(
149  const NATIVE_INT_TYPE portNum,
150  U32 key
151  )
152  {
153  // return key
154  this->pingOut_out(0,key);
155  }
156 
157  void ComLogger ::
158  openFile(
159  )
160  {
161  FW_ASSERT( CLOSED == this->m_fileMode );
162 
163  if( !this->m_initialized ){
165  return;
166  }
167 
168  U32 bytesCopied;
169 
170  // Create filename:
171  Fw::Time timestamp = getTime();
172  memset(this->m_fileName, 0, sizeof(this->m_fileName));
173  bytesCopied = static_cast<U32>(snprintf(
174  this->m_fileName,
175  sizeof(this->m_fileName),
176  "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com",
177  this->m_filePrefix,
178  static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()),
179  timestamp.getSeconds(),
180  timestamp.getUSeconds()));
181 
182  // "A return value of size or more means that the output was truncated"
183  // See here: http://linux.die.net/man/3/snprintf
184  FW_ASSERT( bytesCopied < sizeof(this->m_fileName) );
185 
186  // Create sha filename:
187  bytesCopied = static_cast<U32>(snprintf(
188  this->m_hashFileName,
189  sizeof(this->m_hashFileName),
190  "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com%s",
191  this->m_filePrefix,
192  static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()),
193  timestamp.getSeconds(),
194  timestamp.getUSeconds(),
196  FW_ASSERT( bytesCopied < sizeof(this->m_hashFileName) );
197 
198  Os::File::Status ret = m_file.open(this->m_fileName, Os::File::OPEN_WRITE);
199  if( Os::File::OP_OK != ret ) {
200  if( !this->m_openErrorOccurred ) { // throttle this event, otherwise a positive
201  // feedback event loop can occur!
202  Fw::LogStringArg logStringArg(this->m_fileName);
203  this->log_WARNING_HI_FileOpenError(ret, logStringArg);
204  }
205  this->m_openErrorOccurred = true;
206  } else {
207  // Reset event throttle:
208  this->m_openErrorOccurred = false;
209 
210  // Reset byte count:
211  this->m_byteCount = 0;
212 
213  // Set mode:
214  this->m_fileMode = OPEN;
215  }
216  }
217 
218  void ComLogger ::
219  closeFile(
220  )
221  {
222  if( OPEN == this->m_fileMode ) {
223  // Close file:
224  this->m_file.close();
225 
226  // Write out the hash file to disk:
227  this->writeHashFile();
228 
229  // Update mode:
230  this->m_fileMode = CLOSED;
231 
232  // Send event:
233  Fw::LogStringArg logStringArg(this->m_fileName);
234  this->log_DIAGNOSTIC_FileClosed(logStringArg);
235  }
236  }
237 
238  void ComLogger ::
239  writeComBufferToFile(
240  Fw::ComBuffer &data,
241  U16 size
242  )
243  {
244  if( this->m_storeBufferLength ) {
245  U8 buffer[sizeof(size)];
246  Fw::SerialBuffer serialLength(&buffer[0], sizeof(size));
247  serialLength.serialize(size);
248  if(this->writeToFile(serialLength.getBuffAddr(),
249  static_cast<U16>(serialLength.getBuffLength()))) {
250  this->m_byteCount += serialLength.getBuffLength();
251  }
252  else {
253  return;
254  }
255  }
256 
257  // Write buffer to file:
258  if(this->writeToFile(data.getBuffAddr(), size)) {
259  this->m_byteCount += size;
260  }
261  }
262 
263  bool ComLogger ::
264  writeToFile(
265  void* data,
266  U16 length
267  )
268  {
269  FwSignedSizeType size = length;
270  Os::File::Status ret = m_file.write(reinterpret_cast<const U8*>(data), size);
271  if( Os::File::OP_OK != ret || size != static_cast<NATIVE_INT_TYPE>(length) ) {
272  if( !this->m_writeErrorOccurred ) { // throttle this event, otherwise a positive
273  // feedback event loop can occur!
274  Fw::LogStringArg logStringArg(this->m_fileName);
275  this->log_WARNING_HI_FileWriteError(ret, static_cast<U32>(size), length, logStringArg);
276  }
277  this->m_writeErrorOccurred = true;
278  return false;
279  }
280 
281  this->m_writeErrorOccurred = false;
282  return true;
283  }
284 
285  void ComLogger ::
286  writeHashFile(
287  )
288  {
289  Os::ValidateFile::Status validateStatus;
290  validateStatus = Os::ValidateFile::createValidation(this->m_fileName, this->m_hashFileName);
291  if( Os::ValidateFile::VALIDATION_OK != validateStatus ) {
292  Fw::LogStringArg logStringArg1(this->m_fileName);
293  Fw::LogStringArg logStringArg2(this->m_hashFileName);
294  this->log_WARNING_LO_FileValidationError(logStringArg1, logStringArg2, validateStatus);
295  }
296  }
297 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:55
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:39
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:30
U16 FwTimeBaseStoreType
Definition: FpConfig.h:79
U32 FwOpcodeType
Definition: FpConfig.h:91
PlatformSizeType FwSizeType
Definition: FpConfig.h:35
#define PRI_FwTimeBaseStoreType
Definition: FpConfig.h:80
C++-compatible configuration header for fprime configuration.
Defines a file class to validate files or generate a file validator file.
@ OK
Command successfully executed.
U8 * getBuffAddr()
gets buffer address for data filling
Definition: ComBuffer.cpp:40
A variable-length serializable buffer.
Serializable::SizeType getBuffLength() const
returns current buffer size
Definition: Time.hpp:9
U32 getUSeconds() const
Definition: Time.cpp:139
TimeBase getTimeBase() const
Definition: Time.cpp:143
U32 getSeconds() const
Definition: Time.cpp:135
void close() override
close the file, if not opened then do nothing
Definition: File.cpp:70
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:45
Status write(const U8 *buffer, FwSignedSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:163
@ OP_OK
Operation was successful.
Definition: File.hpp:30
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:23
Auto-generated base for ComLogger component.
void log_WARNING_HI_FileWriteError(U32 errornum, U32 bytesWritten, U32 bytesToWrite, const Fw::StringBase &file)
void log_WARNING_HI_FileOpenError(U32 errornum, const Fw::StringBase &file)
void log_WARNING_LO_FileValidationError(const Fw::StringBase &validationFile, const Fw::StringBase &file, U32 status)
void log_DIAGNOSTIC_FileClosed(const Fw::StringBase &file)
void log_WARNING_LO_FileNotInitialized()
Log event FileNotInitialized.
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
void init_log_file(const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition: ComLogger.cpp:51
ComLogger(const char *compName, const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition: ComLogger.cpp:21
static const char * getFileExtensionString()
Definition: HashCommon.cpp:6
FwSizeType string_length(const CHAR *source, FwSizeType buffer_size)
get the length of the source string
Definition: StringUtils.cpp:23
char * string_copy(char *destination, const char *source, FwSizeType num)
copy string with null-termination guaranteed
Definition: StringUtils.cpp:6
@ VALIDATION_OK
The validation of the file passed.
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)