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
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
19 typedef PrmDb_PrmWriteError PrmWriteError;
20 typedef PrmDb_PrmReadError PrmReadError;
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
69 Fw::ParamValid stat = Fw::ParamValid::INVALID;
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;
75 stat = Fw::ParamValid::VALID;
76 break;
77 }
78 }
79 }
80
81 // if unable to find parameter, send error message
82 if (Fw::ParamValid::INVALID == stat.e) {
83 this->log_WARNING_LO_PrmIdNotFound(id);
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) {
122 this->log_ACTIVITY_HI_PrmIdUpdated(id);
123 } else if (noSlots) {
124 this->log_FATAL_PrmDbFull(id);
125 } else {
126 this->log_ACTIVITY_HI_PrmIdAdded(id);
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) {
138 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::OPEN,0,stat);
139 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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();
157 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER,numRecords,stat);
158 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
159 return;
160 }
161 if (writeSize != sizeof(delim)) {
162 this->unLock();
163 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER_SIZE,numRecords,writeSize);
164 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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();
181 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE,numRecords,stat);
182 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
183 return;
184 }
185 if (writeSize != sizeof(writeSize)) {
186 this->unLock();
187 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE_SIZE,numRecords,writeSize);
188 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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();
206 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID,numRecords,stat);
207 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
208 return;
209 }
210 if (writeSize != static_cast<NATIVE_INT_TYPE>(buff.getBuffLength())) {
211 this->unLock();
212 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID_SIZE,numRecords,writeSize);
213 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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();
223 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE,numRecords,stat);
224 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
225 return;
226 }
227 if (writeSize != static_cast<NATIVE_INT_TYPE>(this->m_db[entry].val.getBuffLength())) {
228 this->unLock();
229 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE_SIZE,numRecords,writeSize);
230 this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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
244 }
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) {
253 this->log_WARNING_HI_PrmFileReadError(PrmReadError::OPEN,0,stat);
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) {
277 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER,recordNum,fStat);
278 return;
279 }
280
281 if (sizeof(delimiter) != readSize) {
282 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE,recordNum,readSize);
283 return;
284 }
285
286 if (PRMDB_ENTRY_DELIMITER != delimiter) {
287 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE,recordNum,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) {
297 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE,recordNum,fStat);
298 return;
299 }
300 if (sizeof(recordSize) != readSize) {
301 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE,recordNum,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 FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(recordSize));
312
313 // sanity check value. It can't be larger than the maximum parameter buffer size + id
314 // or smaller than the record id
315 if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
316 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE,recordNum,recordSize);
317 return;
318 }
319
320 // read the parameter ID
321 FwPrmIdType parameterId = 0;
322 readSize = sizeof(FwPrmIdType);
323
324 fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
325 if (fStat != Os::File::OP_OK) {
326 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID,recordNum,fStat);
327 return;
328 }
329 if (sizeof(parameterId) != static_cast<NATIVE_INT_TYPE>(readSize)) {
330 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE,recordNum,readSize);
331 return;
332 }
333
334 // set serialized size to read parameter ID
335 desStat = buff.setBuffLen(readSize);
336 // should never fail
337 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
338 // reset deserialization
339 buff.resetDeser();
340 // deserialize, since parameter ID is serialized in file
341 FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(parameterId));
342
343 // copy parameter
344 this->m_db[entry].used = true;
345 this->m_db[entry].id = parameterId;
346 readSize = recordSize-sizeof(parameterId);
347
348 fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
349
350 if (fStat != Os::File::OP_OK) {
351 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE,recordNum,fStat);
352 return;
353 }
354 if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
355 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE,recordNum,readSize);
356 return;
357 }
358
359 // set serialized size to read size
360 desStat = this->m_db[entry].val.setBuffLen(readSize);
361 // should never fail
362 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
363 recordNum++;
364
365 }
366
367 this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
368 }
369
370 void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
371 // respond to ping
372 this->pingOut_out(0,key);
373 }
374
375
376
377}
#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
#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:266
U32 FwOpcodeType
Definition FpConfig.h:56
U32 FwPrmIdType
Definition FpConfig.h:65
Component for managing parameters.
U8 * getBuffAddr()
gets buffer address for data filling
Definition PrmBuffer.cpp:40
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
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
void init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance)
PrmDb initialization function.
Definition PrmDbImpl.cpp:53
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