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), maxFileSize);
68  }
69 
70  FW_ASSERT(Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->m_filePrefix)) < sizeof(this->m_filePrefix),
71  Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->m_filePrefix)), sizeof(this->m_filePrefix)); // ensure that file prefix is not too big
72 
73  (void)Fw::StringUtils::string_copy(this->m_filePrefix, incomingFilePrefix, sizeof(this->m_filePrefix));
74 
75  this->m_initialized = true;
76  }
77 
78 
81  {
82  // Close file:
83  // this->closeFile();
84  // NOTE: the above did not work because we don't want to issue an event
85  // in the destructor. This can cause "virtual method called" segmentation
86  // faults.
87  // So I am copying part of that function here.
88  if( OPEN == this->m_fileMode ) {
89  // Close file:
90  this->m_file.close();
91 
92  // Write out the hash file to disk:
93  this->writeHashFile();
94 
95  // Update mode:
96  this->m_fileMode = CLOSED;
97 
98  // Send event:
99  //Fw::LogStringArg logStringArg((char*) fileName);
100  //this->log_DIAGNOSTIC_FileClosed(logStringArg);
101  }
102  }
103 
104  // ----------------------------------------------------------------------
105  // Handler implementations
106  // ----------------------------------------------------------------------
107 
108  void ComLogger ::
109  comIn_handler(
110  NATIVE_INT_TYPE portNum,
111  Fw::ComBuffer &data,
112  U32 context
113  )
114  {
115  FW_ASSERT(portNum == 0);
116 
117  // Get length of buffer:
118  U32 size32 = data.getBuffLength();
119  // ComLogger only writes 16-bit sizes to save space
120  // on disk:
121  FW_ASSERT(size32 < 65536, size32);
122  U16 size = size32 & 0xFFFF;
123 
124  // Close the file if it will be too big:
125  if( OPEN == this->m_fileMode ) {
126  U32 projectedByteCount = this->m_byteCount + size;
127  if( this->m_storeBufferLength ) {
128  projectedByteCount += sizeof(size);
129  }
130  if( projectedByteCount > this->m_maxFileSize ) {
131  this->closeFile();
132  }
133  }
134 
135  // Open the file if it there is not one open:
136  if( CLOSED == this->m_fileMode ){
137  this->openFile();
138  }
139 
140  // Write to the file if it is open:
141  if( OPEN == this->m_fileMode ) {
142  this->writeComBufferToFile(data, size);
143  }
144  }
145 
146  void ComLogger ::
147  CloseFile_cmdHandler(
148  FwOpcodeType opCode,
149  U32 cmdSeq
150  )
151  {
152  this->closeFile();
153  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
154  }
155 
156  void ComLogger ::
157  pingIn_handler(
158  const NATIVE_INT_TYPE portNum,
159  U32 key
160  )
161  {
162  // return key
163  this->pingOut_out(0,key);
164  }
165 
166  void ComLogger ::
167  openFile(
168  )
169  {
170  FW_ASSERT( CLOSED == this->m_fileMode );
171 
172  if( !this->m_initialized ){
174  return;
175  }
176 
177  U32 bytesCopied;
178 
179  // Create filename:
180  Fw::Time timestamp = getTime();
181  memset(this->m_fileName, 0, sizeof(this->m_fileName));
182  bytesCopied = snprintf(this->m_fileName, sizeof(this->m_fileName), "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com",
183  this->m_filePrefix, static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds());
184 
185  // "A return value of size or more means that the output was truncated"
186  // See here: http://linux.die.net/man/3/snprintf
187  FW_ASSERT( bytesCopied < sizeof(this->m_fileName) );
188 
189  // Create sha filename:
190  bytesCopied = snprintf(this->m_hashFileName, sizeof(this->m_hashFileName), "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com%s",
191  this->m_filePrefix, static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds(), Utils::Hash::getFileExtensionString());
192  FW_ASSERT( bytesCopied < sizeof(this->m_hashFileName) );
193 
194  Os::File::Status ret = m_file.open(this->m_fileName, Os::File::OPEN_WRITE);
195  if( Os::File::OP_OK != ret ) {
196  if( !this->m_openErrorOccurred ) { // throttle this event, otherwise a positive
197  // feedback event loop can occur!
198  Fw::LogStringArg logStringArg(this->m_fileName);
199  this->log_WARNING_HI_FileOpenError(ret, logStringArg);
200  }
201  this->m_openErrorOccurred = true;
202  } else {
203  // Reset event throttle:
204  this->m_openErrorOccurred = false;
205 
206  // Reset byte count:
207  this->m_byteCount = 0;
208 
209  // Set mode:
210  this->m_fileMode = OPEN;
211  }
212  }
213 
214  void ComLogger ::
215  closeFile(
216  )
217  {
218  if( OPEN == this->m_fileMode ) {
219  // Close file:
220  this->m_file.close();
221 
222  // Write out the hash file to disk:
223  this->writeHashFile();
224 
225  // Update mode:
226  this->m_fileMode = CLOSED;
227 
228  // Send event:
229  Fw::LogStringArg logStringArg(this->m_fileName);
230  this->log_DIAGNOSTIC_FileClosed(logStringArg);
231  }
232  }
233 
234  void ComLogger ::
235  writeComBufferToFile(
236  Fw::ComBuffer &data,
237  U16 size
238  )
239  {
240  if( this->m_storeBufferLength ) {
241  U8 buffer[sizeof(size)];
242  Fw::SerialBuffer serialLength(&buffer[0], sizeof(size));
243  serialLength.serialize(size);
244  if(this->writeToFile(serialLength.getBuffAddr(),
245  static_cast<U16>(serialLength.getBuffLength()))) {
246  this->m_byteCount += serialLength.getBuffLength();
247  }
248  else {
249  return;
250  }
251  }
252 
253  // Write buffer to file:
254  if(this->writeToFile(data.getBuffAddr(), size)) {
255  this->m_byteCount += size;
256  }
257  }
258 
259  bool ComLogger ::
260  writeToFile(
261  void* data,
262  U16 length
263  )
264  {
265  NATIVE_INT_TYPE size = length;
266  Os::File::Status ret = m_file.write(data, size);
267  if( Os::File::OP_OK != ret || size != static_cast<NATIVE_INT_TYPE>(length) ) {
268  if( !this->m_writeErrorOccurred ) { // throttle this event, otherwise a positive
269  // feedback event loop can occur!
270  Fw::LogStringArg logStringArg(this->m_fileName);
271  this->log_WARNING_HI_FileWriteError(ret, size, length, logStringArg);
272  }
273  this->m_writeErrorOccurred = true;
274  return false;
275  }
276 
277  this->m_writeErrorOccurred = false;
278  return true;
279  }
280 
281  void ComLogger ::
282  writeHashFile(
283  )
284  {
285  Os::ValidateFile::Status validateStatus;
286  validateStatus = Os::ValidateFile::createValidation(this->m_fileName, this->m_hashFileName);
287  if( Os::ValidateFile::VALIDATION_OK != validateStatus ) {
288  Fw::LogStringArg logStringArg1(this->m_fileName);
289  Fw::LogStringArg logStringArg2(this->m_hashFileName);
290  this->log_WARNING_LO_FileValidationError(logStringArg1, logStringArg2, validateStatus);
291  }
292  }
293 }
#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
U16 FwTimeBaseStoreType
Definition: FpConfig.h:47
U32 FwOpcodeType
Definition: FpConfig.h:56
#define PRI_FwTimeBaseStoreType
Definition: FpConfig.h:48
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.
NATIVE_UINT_TYPE 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()
close file
Definition: File.cpp:36
Status
Definition: File.hpp:23
@ OP_OK
Operation was successful.
Definition: File.hpp:24
Status write(const void *buffer, NATIVE_INT_TYPE &size, bool waitForDone=true)
write size; will return amount written or errno
Definition: File.cpp:32
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:16
Status open(const char *fileName, Mode mode)
open file. Writing creates file if it doesn't exist
Definition: File.cpp:12
Auto-generated base for ComLogger component.
void log_WARNING_HI_FileOpenError(U32 errornum, const Fw::LogStringArg &file)
void log_DIAGNOSTIC_FileClosed(const Fw::LogStringArg &file)
void log_WARNING_LO_FileValidationError(const Fw::LogStringArg &validationFile, const Fw::LogStringArg &file, U32 status)
void log_WARNING_LO_FileNotInitialized()
Log event FileNotInitialized.
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void pingOut_out(NATIVE_INT_TYPE portNum, U32 key)
Invoke output port pingOut.
void log_WARNING_HI_FileWriteError(U32 errornum, U32 bytesWritten, U32 bytesToWrite, const Fw::LogStringArg &file)
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:5
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:20
@ VALIDATION_OK
The validation of the file passed.
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)