F´ Flight Software - C/C++ Documentation
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::clearDb() {
54 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
55 this->m_db[entry].used = false;
56 this->m_db[entry].id = 0;
57 }
58 }
59
60 // If ports are no longer guarded, these accesses need to be protected from each other
61 // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
62
63 Fw::ParamValid PrmDbImpl::getPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
64 // search for entry
66
67 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
68 if (this->m_db[entry].used) {
69 if (this->m_db[entry].id == id) {
70 val = this->m_db[entry].val;
72 break;
73 }
74 }
75 }
76
77 // if unable to find parameter, send error message
78 if (Fw::ParamValid::INVALID == stat.e) {
80 }
81
82 return stat;
83 }
84
85 void PrmDbImpl::setPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
86
87 this->lock();
88
89 // search for existing entry
90
91 bool existingEntry = false;
92 bool noSlots = true;
93
94 for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
95 if ((this->m_db[entry].used) && (id == this->m_db[entry].id)) {
96 this->m_db[entry].val = val;
97 existingEntry = true;
98 break;
99 }
100 }
101
102 // if there is no existing entry, add one
103 if (!existingEntry) {
104 for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
105 if (!(this->m_db[entry].used)) {
106 this->m_db[entry].val = val;
107 this->m_db[entry].id = id;
108 this->m_db[entry].used = true;
109 noSlots = false;
110 break;
111 }
112 }
113 }
114
115 this->unLock();
116
117 if (existingEntry) {
119 } else if (noSlots) {
120 this->log_FATAL_PrmDbFull(id);
121 } else {
123 }
124
125 }
126
127 void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
128 FW_ASSERT(this->m_fileName.length() > 0);
129 Os::File paramFile;
130 WorkingBuffer buff;
131
132 Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_WRITE);
133 if (stat != Os::File::OP_OK) {
136 return;
137 }
138
139 this->lock();
140
141 // Traverse the parameter list, saving each entry
142
143 U32 numRecords = 0;
144
145 for (NATIVE_UINT_TYPE entry = 0; entry < FW_NUM_ARRAY_ELEMENTS(this->m_db); entry++) {
146 if (this->m_db[entry].used) {
147 // write delimiter
148 static const U8 delim = PRMDB_ENTRY_DELIMITER;
149 FwSignedSizeType writeSize = static_cast<FwSignedSizeType>(sizeof(delim));
150 stat = paramFile.write(&delim,writeSize,Os::File::WaitType::WAIT);
151 if (stat != Os::File::OP_OK) {
152 this->unLock();
153 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER,static_cast<I32>(numRecords),stat);
155 return;
156 }
157 if (writeSize != sizeof(delim)) {
158 this->unLock();
161 static_cast<I32>(numRecords),
162 static_cast<I32>(writeSize));
164 return;
165 }
166 // serialize record size = id field + data
167 U32 recordSize = static_cast<U32>(sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength());
168
169 // reset buffer
170 buff.resetSer();
171 Fw::SerializeStatus serStat = buff.serialize(recordSize);
172 // should always work
173 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
174
175 // write record size
176 writeSize = buff.getBuffLength();
177 stat = paramFile.write(buff.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
178 if (stat != Os::File::OP_OK) {
179 this->unLock();
180 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE,static_cast<I32>(numRecords),stat);
182 return;
183 }
184 if (writeSize != sizeof(recordSize)) {
185 this->unLock();
188 static_cast<I32>(numRecords),
189 static_cast<I32>(writeSize));
191 return;
192 }
193
194 // reset buffer
195 buff.resetSer();
196
197 // serialize parameter id
198
199 serStat = buff.serialize(this->m_db[entry].id);
200 // should always work
201 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
202
203 // write parameter ID
204 writeSize = buff.getBuffLength();
205 stat = paramFile.write(buff.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
206 if (stat != Os::File::OP_OK) {
207 this->unLock();
208 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID,static_cast<I32>(numRecords),stat);
210 return;
211 }
212 if (writeSize != static_cast<FwSignedSizeType>(buff.getBuffLength())) {
213 this->unLock();
216 static_cast<I32>(numRecords),
217 static_cast<I32>(writeSize));
219 return;
220 }
221
222 // write serialized parameter value
223
224 writeSize = this->m_db[entry].val.getBuffLength();
225 stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
226 if (stat != Os::File::OP_OK) {
227 this->unLock();
228 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE,static_cast<I32>(numRecords),stat);
230 return;
231 }
232 if (writeSize != static_cast<FwSignedSizeType>(this->m_db[entry].val.getBuffLength())) {
233 this->unLock();
236 static_cast<I32>(numRecords),
237 static_cast<I32>(writeSize));
239 return;
240 }
241 numRecords++;
242 } // end if record in use
243 } // end for each record
244
245 this->unLock();
246 this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
247 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
248
249 }
250
253
255 FW_ASSERT(this->m_fileName.length() > 0);
256 // load file. FIXME: Put more robust file checking, such as a CRC.
257 Os::File paramFile;
258
259 Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_READ);
260 if (stat != Os::File::OP_OK) {
262 return;
263 }
264
265 WorkingBuffer buff;
266
267 U32 recordNum = 0;
268
269 this->clearDb();
270
271 for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
272
273 U8 delimiter;
274 FwSignedSizeType readSize = static_cast<FwSignedSizeType>(sizeof(delimiter));
275
276 // read delimiter
277 Os::File::Status fStat = paramFile.read(&delimiter,readSize,Os::File::WaitType::WAIT);
278
279 // check for end of file (read size 0)
280 if (0 == readSize) {
281 break;
282 }
283
284 if (fStat != Os::File::OP_OK) {
285 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER,static_cast<I32>(recordNum),fStat);
286 return;
287 }
288
289 if (sizeof(delimiter) != readSize) {
290 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
291 return;
292 }
293
294 if (PRMDB_ENTRY_DELIMITER != delimiter) {
295 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE,static_cast<I32>(recordNum),delimiter);
296 return;
297 }
298
299 U32 recordSize = 0;
300 // read record size
301 readSize = sizeof(recordSize);
302
303 fStat = paramFile.read(buff.getBuffAddr(),readSize,Os::File::WaitType::WAIT);
304 if (fStat != Os::File::OP_OK) {
305 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE,static_cast<I32>(recordNum),fStat);
306 return;
307 }
308 if (sizeof(recordSize) != readSize) {
309 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
310 return;
311 }
312 // set serialized size to read size
313 Fw::SerializeStatus desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
314 // should never fail
315 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
316 // reset deserialization
317 buff.resetDeser();
318 // deserialize, since record size is serialized in file
319 desStat = buff.deserialize(recordSize);
320 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
321
322 // sanity check value. It can't be larger than the maximum parameter buffer size + id
323 // or smaller than the record id
324 if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
325 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE,static_cast<I32>(recordNum),static_cast<I32>(recordSize));
326 return;
327 }
328
329 // read the parameter ID
330 FwPrmIdType parameterId = 0;
331 readSize = static_cast<FwSignedSizeType>(sizeof(FwPrmIdType));
332
333 fStat = paramFile.read(buff.getBuffAddr(),readSize,Os::File::WaitType::WAIT);
334 if (fStat != Os::File::OP_OK) {
335 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID,static_cast<I32>(recordNum),fStat);
336 return;
337 }
338 if (sizeof(parameterId) != static_cast<FwSizeType>(readSize)) {
339 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
340 return;
341 }
342
343 // set serialized size to read parameter ID
344 desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
345 // should never fail
346 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
347 // reset deserialization
348 buff.resetDeser();
349 // deserialize, since parameter ID is serialized in file
350 desStat = buff.deserialize(parameterId);
351 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
352
353 // copy parameter
354 this->m_db[entry].used = true;
355 this->m_db[entry].id = parameterId;
356 readSize = recordSize-sizeof(parameterId);
357
358 fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
359
360 if (fStat != Os::File::OP_OK) {
361 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE,static_cast<I32>(recordNum),fStat);
362 return;
363 }
364 if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
365 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
366 return;
367 }
368
369 // set serialized size to read size
370 desStat = this->m_db[entry].val.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
371 // should never fail
372 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
373 recordNum++;
374
375 }
376
378 }
379
380 void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
381 // respond to ping
382 this->pingOut_out(0,key);
383 }
384
385
386
387}
#define FW_ASSERT(...)
Definition Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:55
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:30
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition BasicTypes.h:70
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:56
PlatformSignedSizeType FwSignedSizeType
Definition FpConfig.h:30
#define FW_PARAM_BUFFER_MAX_SIZE
Definition FpConfig.h:334
U32 FwOpcodeType
Definition FpConfig.h:91
PlatformSizeType FwSizeType
Definition FpConfig.h:35
U32 FwPrmIdType
Definition FpConfig.h:107
Component for managing parameters.
@ EXECUTION_ERROR
Command had execution error.
@ OK
Command successfully executed.
U8 * getBuffAddr()
gets buffer address for data filling
Definition PrmBuffer.cpp:40
Enum representing parameter validity.
T e
The raw enum value.
NATIVE_UINT_TYPE SizeType
Serializable::SizeType getBuffLength() const
returns current buffer size
SizeType length() const
Get length of string.
const char * toChar() const
Definition String.hpp:50
Status read(U8 *buffer, FwSignedSizeType &size)
read data from this file into supplied buffer bounded by size
Definition File.cpp:143
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition File.cpp:45
Status write(const U8 *buffer, FwSignedSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition File.cpp:163
@ WAIT
Do wait for read/write operation to finish.
Definition File.hpp:58
@ OP_OK
Operation was successful.
Definition File.hpp:30
@ OPEN_WRITE
Open file for writing.
Definition File.hpp:23
@ OPEN_READ
Open file for reading.
Definition File.hpp:21
Auto-generated base for PrmDb component.
virtual void unLock()
Unlock the guarded mutex.
void log_WARNING_HI_PrmFileWriteError(Svc::PrmDb_PrmWriteError stage, I32 record, I32 error) const
void log_ACTIVITY_HI_PrmIdUpdated(U32 Id) const
void log_FATAL_PrmDbFull(U32 Id) const
virtual void lock()
Lock the guarded mutex.
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
void log_ACTIVITY_HI_PrmFileLoadComplete(U32 records) const
void log_ACTIVITY_HI_PrmFileSaveComplete(U32 records) const
void log_WARNING_HI_PrmFileReadError(Svc::PrmDb_PrmReadError stage, I32 record, I32 error) const
void log_WARNING_LO_PrmIdNotFound(U32 Id)
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void log_ACTIVITY_HI_PrmIdAdded(U32 Id) const
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