F´ Flight Software - C/C++ Documentation NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
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.
U8 * getBuffAddr()
gets buffer address for data filling
Definition ComBuffer.cpp:40
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
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)