F´ Flight Software - C/C++ Documentation devel
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
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