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 
50 
52  init(
53  NATIVE_INT_TYPE queueDepth,
54  NATIVE_INT_TYPE instance
55  )
56  {
57  ComLoggerComponentBase::init(queueDepth, instance);
58  }
59 
61  init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength)
62  {
63  FW_ASSERT(incomingFilePrefix != nullptr);
64  this->m_maxFileSize = maxFileSize;
65  this->m_storeBufferLength = storeBufferLength;
66  if( this->m_storeBufferLength ) {
67  FW_ASSERT(maxFileSize > sizeof(U16), static_cast<FwAssertArgType>(maxFileSize));
68  }
69 
70  FW_ASSERT(Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->m_filePrefix)) < sizeof(this->m_filePrefix),
71  static_cast<FwAssertArgType>(Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->m_filePrefix))),
72  static_cast<FwAssertArgType>(sizeof(this->m_filePrefix))); // ensure that file prefix is not too big
73 
74  (void)Fw::StringUtils::string_copy(this->m_filePrefix, incomingFilePrefix, sizeof(this->m_filePrefix));
75 
76  this->m_initialized = true;
77  }
78 
79 
82  {
83  // Close file:
84  // this->closeFile();
85  // NOTE: the above did not work because we don't want to issue an event
86  // in the destructor. This can cause "virtual method called" segmentation
87  // faults.
88  // So I am copying part of that function here.
89  if( OPEN == this->m_fileMode ) {
90  // Close file:
91  this->m_file.close();
92 
93  // Write out the hash file to disk:
94  this->writeHashFile();
95 
96  // Update mode:
97  this->m_fileMode = CLOSED;
98 
99  // Send event:
100  //Fw::LogStringArg logStringArg((char*) fileName);
101  //this->log_DIAGNOSTIC_FileClosed(logStringArg);
102  }
103  }
104 
105  // ----------------------------------------------------------------------
106  // Handler implementations
107  // ----------------------------------------------------------------------
108 
109  void ComLogger ::
110  comIn_handler(
111  NATIVE_INT_TYPE portNum,
112  Fw::ComBuffer &data,
113  U32 context
114  )
115  {
116  FW_ASSERT(portNum == 0);
117 
118  // Get length of buffer:
119  U32 size32 = data.getBuffLength();
120  // ComLogger only writes 16-bit sizes to save space
121  // on disk:
122  FW_ASSERT(size32 < 65536, static_cast<FwAssertArgType>(size32));
123  U16 size = size32 & 0xFFFF;
124 
125  // Close the file if it will be too big:
126  if( OPEN == this->m_fileMode ) {
127  U32 projectedByteCount = this->m_byteCount + size;
128  if( this->m_storeBufferLength ) {
129  projectedByteCount += static_cast<U32>(sizeof(size));
130  }
131  if( projectedByteCount > this->m_maxFileSize ) {
132  this->closeFile();
133  }
134  }
135 
136  // Open the file if it there is not one open:
137  if( CLOSED == this->m_fileMode ){
138  this->openFile();
139  }
140 
141  // Write to the file if it is open:
142  if( OPEN == this->m_fileMode ) {
143  this->writeComBufferToFile(data, size);
144  }
145  }
146 
147  void ComLogger ::
148  CloseFile_cmdHandler(
149  FwOpcodeType opCode,
150  U32 cmdSeq
151  )
152  {
153  this->closeFile();
154  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
155  }
156 
157  void ComLogger ::
158  pingIn_handler(
159  const NATIVE_INT_TYPE portNum,
160  U32 key
161  )
162  {
163  // return key
164  this->pingOut_out(0,key);
165  }
166 
167  void ComLogger ::
168  openFile(
169  )
170  {
171  FW_ASSERT( CLOSED == this->m_fileMode );
172 
173  if( !this->m_initialized ){
175  return;
176  }
177 
178  U32 bytesCopied;
179 
180  // Create filename:
181  Fw::Time timestamp = getTime();
182  memset(this->m_fileName, 0, sizeof(this->m_fileName));
183  bytesCopied = static_cast<U32>(snprintf(
184  this->m_fileName,
185  sizeof(this->m_fileName),
186  "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com",
187  this->m_filePrefix,
188  static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()),
189  timestamp.getSeconds(),
190  timestamp.getUSeconds()));
191 
192  // "A return value of size or more means that the output was truncated"
193  // See here: http://linux.die.net/man/3/snprintf
194  FW_ASSERT( bytesCopied < sizeof(this->m_fileName) );
195 
196  // Create sha filename:
197  bytesCopied = static_cast<U32>(snprintf(
198  this->m_hashFileName,
199  sizeof(this->m_hashFileName),
200  "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com%s",
201  this->m_filePrefix,
202  static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()),
203  timestamp.getSeconds(),
204  timestamp.getUSeconds(),
206  FW_ASSERT( bytesCopied < sizeof(this->m_hashFileName) );
207 
208  Os::File::Status ret = m_file.open(this->m_fileName, Os::File::OPEN_WRITE);
209  if( Os::File::OP_OK != ret ) {
210  if( !this->m_openErrorOccurred ) { // throttle this event, otherwise a positive
211  // feedback event loop can occur!
212  Fw::LogStringArg logStringArg(this->m_fileName);
213  this->log_WARNING_HI_FileOpenError(ret, logStringArg);
214  }
215  this->m_openErrorOccurred = true;
216  } else {
217  // Reset event throttle:
218  this->m_openErrorOccurred = false;
219 
220  // Reset byte count:
221  this->m_byteCount = 0;
222 
223  // Set mode:
224  this->m_fileMode = OPEN;
225  }
226  }
227 
228  void ComLogger ::
229  closeFile(
230  )
231  {
232  if( OPEN == this->m_fileMode ) {
233  // Close file:
234  this->m_file.close();
235 
236  // Write out the hash file to disk:
237  this->writeHashFile();
238 
239  // Update mode:
240  this->m_fileMode = CLOSED;
241 
242  // Send event:
243  Fw::LogStringArg logStringArg(this->m_fileName);
244  this->log_DIAGNOSTIC_FileClosed(logStringArg);
245  }
246  }
247 
248  void ComLogger ::
249  writeComBufferToFile(
250  Fw::ComBuffer &data,
251  U16 size
252  )
253  {
254  if( this->m_storeBufferLength ) {
255  U8 buffer[sizeof(size)];
256  Fw::SerialBuffer serialLength(&buffer[0], sizeof(size));
257  serialLength.serialize(size);
258  if(this->writeToFile(serialLength.getBuffAddr(),
259  static_cast<U16>(serialLength.getBuffLength()))) {
260  this->m_byteCount += serialLength.getBuffLength();
261  }
262  else {
263  return;
264  }
265  }
266 
267  // Write buffer to file:
268  if(this->writeToFile(data.getBuffAddr(), size)) {
269  this->m_byteCount += size;
270  }
271  }
272 
273  bool ComLogger ::
274  writeToFile(
275  void* data,
276  U16 length
277  )
278  {
279  FwSignedSizeType size = length;
280  Os::File::Status ret = m_file.write(reinterpret_cast<const U8*>(data), size);
281  if( Os::File::OP_OK != ret || size != static_cast<NATIVE_INT_TYPE>(length) ) {
282  if( !this->m_writeErrorOccurred ) { // throttle this event, otherwise a positive
283  // feedback event loop can occur!
284  Fw::LogStringArg logStringArg(this->m_fileName);
285  this->log_WARNING_HI_FileWriteError(ret, static_cast<U32>(size), length, logStringArg);
286  }
287  this->m_writeErrorOccurred = true;
288  return false;
289  }
290 
291  this->m_writeErrorOccurred = false;
292  return true;
293  }
294 
295  void ComLogger ::
296  writeHashFile(
297  )
298  {
299  Os::ValidateFile::Status validateStatus;
300  validateStatus = Os::ValidateFile::createValidation(this->m_fileName, this->m_hashFileName);
301  if( Os::ValidateFile::VALIDATION_OK != validateStatus ) {
302  Fw::LogStringArg logStringArg1(this->m_fileName);
303  Fw::LogStringArg logStringArg2(this->m_hashFileName);
304  this->log_WARNING_LO_FileValidationError(logStringArg1, logStringArg2, validateStatus);
305  }
306  }
307 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:34
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:25
U16 FwTimeBaseStoreType
Definition: FpConfig.h:66
U32 FwOpcodeType
Definition: FpConfig.h:78
#define PRI_FwTimeBaseStoreType
Definition: FpConfig.h:67
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
void init()
Object initializer.
Definition: ObjBase.cpp:27
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:69
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:162
@ 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:61
ComLogger(const char *compName, const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition: ComLogger.cpp:21
static const char * getFileExtensionString()
Definition: HashCommon.cpp:6
char * string_copy(char *destination, const char *source, U32 num)
copy string with null-termination guaranteed
Definition: StringUtils.cpp:6
U32 string_length(const CHAR *source, U32 max_len)
get the length of the source string or max_len if the string is longer than max_len.
Definition: StringUtils.cpp:23
@ VALIDATION_OK
The validation of the file passed.
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)