F´ Flight Software - C/C++ Documentation devel
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ComLogger.cpp
Go to the documentation of this file.
1// ----------------------------------------------------------------------
2//
3// ComLogger.cpp
4//
5// ----------------------------------------------------------------------
6
8#include <FpConfig.hpp>
11#include <Os/ValidateFile.hpp>
12#include <cstdio>
13
14namespace Svc {
15
16 // ----------------------------------------------------------------------
17 // Construction, initialization, and destruction
18 // ----------------------------------------------------------------------
19
20 ComLogger ::
21 ComLogger(const char* compName, const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength) :
22 ComLoggerComponentBase(compName),
23 maxFileSize(maxFileSize),
24 fileMode(CLOSED),
25 byteCount(0),
26 writeErrorOccurred(false),
27 openErrorOccurred(false),
28 storeBufferLength(storeBufferLength),
29 initialized(true)
30 {
31 this->init_log_file(incomingFilePrefix, maxFileSize, storeBufferLength);
32 }
33
34 ComLogger ::
35 ComLogger(const char* compName) :
36 ComLoggerComponentBase(compName),
37 filePrefix(),
38 maxFileSize(0),
39 fileMode(CLOSED),
40 fileName(),
41 hashFileName(),
42 byteCount(0),
43 writeErrorOccurred(false),
44 openErrorOccurred(false),
45 storeBufferLength(),
46 initialized(false)
47 {
48 }
49
50
51 void ComLogger ::
52 init(
53 NATIVE_INT_TYPE queueDepth,
54 NATIVE_INT_TYPE instance
55 )
56 {
57 ComLoggerComponentBase::init(queueDepth, instance);
58 }
59
60 void ComLogger ::
61 init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength)
62 {
63 FW_ASSERT(incomingFilePrefix != nullptr);
64 this->maxFileSize = maxFileSize;
65 this->storeBufferLength = storeBufferLength;
66 if( this->storeBufferLength ) {
67 FW_ASSERT(maxFileSize > sizeof(U16), maxFileSize);
68 }
69
70 FW_ASSERT(Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->filePrefix)) < sizeof(this->filePrefix),
71 Fw::StringUtils::string_length(incomingFilePrefix, sizeof(this->filePrefix)), sizeof(this->filePrefix)); // ensure that file prefix is not too big
72
73 (void)Fw::StringUtils::string_copy(this->filePrefix, incomingFilePrefix, sizeof(this->filePrefix));
74
75 this->initialized = true;
76 }
77
78
79 ComLogger ::
80 ~ComLogger()
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->fileMode ) {
89 // Close file:
90 this->file.close();
91
92 // Write out the hash file to disk:
93 this->writeHashFile();
94
95 // Update mode:
96 this->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->fileMode ) {
126 U32 projectedByteCount = this->byteCount + size;
127 if( this->storeBufferLength ) {
128 projectedByteCount += sizeof(size);
129 }
130 if( projectedByteCount > this->maxFileSize ) {
131 this->closeFile();
132 }
133 }
134
135 // Open the file if it there is not one open:
136 if( CLOSED == this->fileMode ){
137 this->openFile();
138 }
139
140 // Write to the file if it is open:
141 if( OPEN == this->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->fileMode );
171
172 if( !this->initialized ){
173 this->log_WARNING_LO_FileNotInitialized();
174 return;
175 }
176
177 U32 bytesCopied;
178
179 // Create filename:
180 Fw::Time timestamp = getTime();
181 memset(this->fileName, 0, sizeof(this->fileName));
182 bytesCopied = snprintf(this->fileName, sizeof(this->fileName), "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com",
183 this->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->fileName) );
188
189 // Create sha filename:
190 bytesCopied = snprintf(this->hashFileName, sizeof(this->hashFileName), "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com%s",
191 this->filePrefix, static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds(), Utils::Hash::getFileExtensionString());
192 FW_ASSERT( bytesCopied < sizeof(this->hashFileName) );
193
194 Os::File::Status ret = file.open(this->fileName, Os::File::OPEN_WRITE);
195 if( Os::File::OP_OK != ret ) {
196 if( !this->openErrorOccurred ) { // throttle this event, otherwise a positive
197 // feedback event loop can occur!
198 Fw::LogStringArg logStringArg(this->fileName);
199 this->log_WARNING_HI_FileOpenError(ret, logStringArg);
200 }
201 this->openErrorOccurred = true;
202 } else {
203 // Reset event throttle:
204 this->openErrorOccurred = false;
205
206 // Reset byte count:
207 this->byteCount = 0;
208
209 // Set mode:
210 this->fileMode = OPEN;
211 }
212 }
213
214 void ComLogger ::
215 closeFile(
216 )
217 {
218 if( OPEN == this->fileMode ) {
219 // Close file:
220 this->file.close();
221
222 // Write out the hash file to disk:
223 this->writeHashFile();
224
225 // Update mode:
226 this->fileMode = CLOSED;
227
228 // Send event:
229 Fw::LogStringArg logStringArg(this->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->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->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->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 = file.write(data, size);
267 if( Os::File::OP_OK != ret || size != static_cast<NATIVE_INT_TYPE>(length) ) {
268 if( !this->writeErrorOccurred ) { // throttle this event, otherwise a positive
269 // feedback event loop can occur!
270 Fw::LogStringArg logStringArg(this->fileName);
271 this->log_WARNING_HI_FileWriteError(ret, size, length, logStringArg);
272 }
273 this->writeErrorOccurred = true;
274 return false;
275 }
276
277 this->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->fileName, this->hashFileName);
287 if( Os::ValidateFile::VALIDATION_OK != validateStatus ) {
288 Fw::LogStringArg logStringArg1(this->fileName);
289 Fw::LogStringArg logStringArg2(this->hashFileName);
290 this->log_WARNING_LO_FileValidationError(logStringArg1, logStringArg2, validateStatus);
291 }
292 }
293};
#define FW_ASSERT(...)
Definition Assert.hpp:7
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
U32 getUSeconds() const
Definition Time.cpp:139
TimeBase getTimeBase() const
Definition Time.cpp:143
U32 getSeconds() const
Definition Time.cpp:135
@ OP_OK
Operation was successful.
Definition File.hpp:24
@ OPEN_WRITE
Open file for writing.
Definition File.hpp:16
Auto-generated base for ComLogger component.
void init_log_file(const char *filePrefix, U32 maxFileSize, bool storeBufferLength=true)
Definition ComLogger.cpp:61
static const char * getFileExtensionString()
Definition HashCommon.cpp:6
char * string_copy(char *destination, const char *source, U32 num)
copy string with null-termination guaranteed
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.
@ VALIDATION_OK
The validation of the file passed.
Status createValidation(const char *fileName, const char *hash, Utils::HashBuffer &hashBuffer)