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
PrmDbImpl.cpp
Go to the documentation of this file.
1/*
2 * PrmDbImpl.cpp
3 *
4 * Created on: March 9, 2015
5 * Author: Timothy Canham
6 */
7
9#include <Fw/Types/Assert.hpp>
10
11#include <Os/File.hpp>
12
13#include <cstring>
14#include <cstdio>
15
16namespace Svc {
17
18
21 // anonymous namespace for buffer declaration
22 namespace {
23 class WorkingBuffer : public Fw::SerializeBufferBase {
24 public:
25
26 NATIVE_UINT_TYPE getBuffCapacity() const {
27 return sizeof(m_buff);
28 }
29
30 U8* getBuffAddr() {
31 return m_buff;
32 }
33
34 const U8* getBuffAddr() const {
35 return m_buff;
36 }
37
38 private:
39 // Set to max of parameter buffer + id
40 U8 m_buff[FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)];
41 };
42 }
43
44 PrmDbImpl::PrmDbImpl(const char* name) : PrmDbComponentBase(name) {
45 this->clearDb();
46 }
47
48 void PrmDbImpl::configure(const char* file) {
49 FW_ASSERT(file != nullptr);
50 this->m_fileName = file;
51 }
52
53 void PrmDbImpl::init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance) {
54 PrmDbComponentBase::init(queueDepth,instance);
55 }
56
57 void PrmDbImpl::clearDb() {
58 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
59 this->m_db[entry].used = false;
60 this->m_db[entry].id = 0;
61 }
62 }
63
64 // If ports are no longer guarded, these accesses need to be protected from each other
65 // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
66
67 Fw::ParamValid PrmDbImpl::getPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
68 // search for entry
70
71 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
72 if (this->m_db[entry].used) {
73 if (this->m_db[entry].id == id) {
74 val = this->m_db[entry].val;
76 break;
77 }
78 }
79 }
80
81 // if unable to find parameter, send error message
82 if (Fw::ParamValid::INVALID == stat.e) {
84 }
85
86 return stat;
87 }
88
89 void PrmDbImpl::setPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
90
91 this->lock();
92
93 // search for existing entry
94
95 bool existingEntry = false;
96 bool noSlots = true;
97
98 for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
99 if ((this->m_db[entry].used) && (id == this->m_db[entry].id)) {
100 this->m_db[entry].val = val;
101 existingEntry = true;
102 break;
103 }
104 }
105
106 // if there is no existing entry, add one
107 if (!existingEntry) {
108 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
109 if (!(this->m_db[entry].used)) {
110 this->m_db[entry].val = val;
111 this->m_db[entry].id = id;
112 this->m_db[entry].used = true;
113 noSlots = false;
114 break;
115 }
116 }
117 }
118
119 this->unLock();
120
121 if (existingEntry) {
123 } else if (noSlots) {
124 this->log_FATAL_PrmDbFull(id);
125 } else {
127 }
128
129 }
130
131 void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
132 FW_ASSERT(this->m_fileName.length() > 0);
133 Os::File paramFile;
134 WorkingBuffer buff;
135
136 Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_WRITE);
137 if (stat != Os::File::OP_OK) {
140 return;
141 }
142
143 this->lock();
144
145 // Traverse the parameter list, saving each entry
146
147 U32 numRecords = 0;
148
149 for (NATIVE_UINT_TYPE entry = 0; entry < FW_NUM_ARRAY_ELEMENTS(this->m_db); entry++) {
150 if (this->m_db[entry].used) {
151 // write delimiter
152 static const U8 delim = PRMDB_ENTRY_DELIMITER;
153 NATIVE_INT_TYPE writeSize = sizeof(delim);
154 stat = paramFile.write(&delim,writeSize,true);
155 if (stat != Os::File::OP_OK) {
156 this->unLock();
159 return;
160 }
161 if (writeSize != sizeof(delim)) {
162 this->unLock();
165 return;
166 }
167 // serialize record size = id field + data
168 U32 recordSize = sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength();
169
170 // reset buffer
171 buff.resetSer();
172 Fw::SerializeStatus serStat = buff.serialize(recordSize);
173 // should always work
174 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
175
176 // write record size
177 writeSize = buff.getBuffLength();
178 stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
179 if (stat != Os::File::OP_OK) {
180 this->unLock();
183 return;
184 }
185 if (writeSize != sizeof(writeSize)) {
186 this->unLock();
189 return;
190 }
191
192 // reset buffer
193 buff.resetSer();
194
195 // serialize parameter id
196
197 serStat = buff.serialize(this->m_db[entry].id);
198 // should always work
199 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
200
201 // write parameter ID
202 writeSize = buff.getBuffLength();
203 stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
204 if (stat != Os::File::OP_OK) {
205 this->unLock();
208 return;
209 }
210 if (writeSize != static_cast<NATIVE_INT_TYPE>(buff.getBuffLength())) {
211 this->unLock();
214 return;
215 }
216
217 // write serialized parameter value
218
219 writeSize = this->m_db[entry].val.getBuffLength();
220 stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,true);
221 if (stat != Os::File::OP_OK) {
222 this->unLock();
225 return;
226 }
227 if (writeSize != static_cast<NATIVE_INT_TYPE>(this->m_db[entry].val.getBuffLength())) {
228 this->unLock();
231 return;
232 }
233 numRecords++;
234 } // end if record in use
235 } // end for each record
236
237 this->unLock();
238 this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
239 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
240
241 }
242
245
247 FW_ASSERT(this->m_fileName.length() > 0);
248 // load file. FIXME: Put more robust file checking, such as a CRC.
249 Os::File paramFile;
250
251 Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_READ);
252 if (stat != Os::File::OP_OK) {
254 return;
255 }
256
257 WorkingBuffer buff;
258
259 U32 recordNum = 0;
260
261 this->clearDb();
262
263 for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
264
265 U8 delimiter;
266 NATIVE_INT_TYPE readSize = sizeof(delimiter);
267
268 // read delimiter
269 Os::File::Status fStat = paramFile.read(&delimiter,readSize,true);
270
271 // check for end of file (read size 0)
272 if (0 == readSize) {
273 break;
274 }
275
276 if (fStat != Os::File::OP_OK) {
278 return;
279 }
280
281 if (sizeof(delimiter) != readSize) {
283 return;
284 }
285
286 if (PRMDB_ENTRY_DELIMITER != delimiter) {
288 return;
289 }
290
291 U32 recordSize = 0;
292 // read record size
293 readSize = sizeof(recordSize);
294
295 fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
296 if (fStat != Os::File::OP_OK) {
298 return;
299 }
300 if (sizeof(recordSize) != readSize) {
302 return;
303 }
304 // set serialized size to read size
305 Fw::SerializeStatus desStat = buff.setBuffLen(readSize);
306 // should never fail
307 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
308 // reset deserialization
309 buff.resetDeser();
310 // deserialize, since record size is serialized in file
311 desStat = buff.deserialize(recordSize);
312 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
313
314 // sanity check value. It can't be larger than the maximum parameter buffer size + id
315 // or smaller than the record id
316 if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
318 return;
319 }
320
321 // read the parameter ID
322 FwPrmIdType parameterId = 0;
323 readSize = sizeof(FwPrmIdType);
324
325 fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
326 if (fStat != Os::File::OP_OK) {
328 return;
329 }
330 if (sizeof(parameterId) != static_cast<NATIVE_INT_TYPE>(readSize)) {
332 return;
333 }
334
335 // set serialized size to read parameter ID
336 desStat = buff.setBuffLen(readSize);
337 // should never fail
338 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
339 // reset deserialization
340 buff.resetDeser();
341 // deserialize, since parameter ID is serialized in file
342 desStat = buff.deserialize(parameterId);
343 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
344
345 // copy parameter
346 this->m_db[entry].used = true;
347 this->m_db[entry].id = parameterId;
348 readSize = recordSize-sizeof(parameterId);
349
350 fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
351
352 if (fStat != Os::File::OP_OK) {
354 return;
355 }
356 if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
358 return;
359 }
360
361 // set serialized size to read size
362 desStat = this->m_db[entry].val.setBuffLen(readSize);
363 // should never fail
364 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
365 recordNum++;
366
367 }
368
370 }
371
372 void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
373 // respond to ping
374 this->pingOut_out(0,key);
375 }
376
377
378
379}
#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
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition BasicTypes.h:66
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
#define FW_PARAM_BUFFER_MAX_SIZE
Definition FpConfig.h:274
U32 FwOpcodeType
Definition FpConfig.h:56
U32 FwPrmIdType
Definition FpConfig.h:65
Component for managing parameters.
@ EXECUTION_ERROR
Command had execution error.
@ OK
Command successfully executed.
void init()
Object initializer.
Definition ObjBase.cpp:27
U8 * getBuffAddr()
gets buffer address for data filling
Definition PrmBuffer.cpp:40
Enum representing parameter validity.
T e
The raw enum value.
SerializeStatus setBuffLen(NATIVE_UINT_TYPE length)
sets buffer length manually after filling with data
NATIVE_UINT_TYPE getBuffLength() const
returns current buffer size
NATIVE_UINT_TYPE length() const
Get length of string.
const char * toChar() const
gets char buffer
Definition String.cpp:48
@ 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
@ OPEN_READ
Open file for reading.
Definition File.hpp:15
Status open(const char *fileName, Mode mode)
open file. Writing creates file if it doesn't exist
Definition File.cpp:12
Status read(void *buffer, NATIVE_INT_TYPE &size, bool waitForFull=true)
waitForFull = true to wait for all bytes to be read
Definition File.cpp:28
Auto-generated base for PrmDb component.
virtual void unLock()
Unlock the guarded mutex.
void log_WARNING_HI_PrmFileReadError(Svc::PrmDb_PrmReadError stage, I32 record, I32 error)
void log_WARNING_HI_PrmFileWriteError(Svc::PrmDb_PrmWriteError stage, I32 record, I32 error)
void log_ACTIVITY_HI_PrmIdUpdated(U32 Id)
virtual void lock()
Lock the guarded mutex.
void pingOut_out(NATIVE_INT_TYPE portNum, U32 key)
Invoke output port pingOut.
void log_ACTIVITY_HI_PrmFileLoadComplete(U32 records)
void log_WARNING_LO_PrmIdNotFound(U32 Id)
void log_ACTIVITY_HI_PrmFileSaveComplete(U32 records)
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void readParamFile()
PrmDb file read function.
virtual ~PrmDbImpl()
PrmDb destructor.
PrmDbImpl(const char *name)
PrmDb constructor.
Definition PrmDbImpl.cpp:44
void configure(const char *file)
PrmDb configure method.
Definition PrmDbImpl.cpp:48
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
PrmDb_PrmReadError PrmReadError
Definition PrmDbImpl.cpp:20
PrmDb_PrmWriteError PrmWriteError
Definition PrmDbImpl.cpp:19