F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
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 
16 namespace 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;
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) {
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 {
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) {
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  FwSignedSizeType writeSize = static_cast<FwSignedSizeType>(sizeof(delim));
154  stat = paramFile.write(&delim,writeSize,Os::File::WaitType::WAIT);
155  if (stat != Os::File::OP_OK) {
156  this->unLock();
157  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER,static_cast<I32>(numRecords),stat);
159  return;
160  }
161  if (writeSize != sizeof(delim)) {
162  this->unLock();
165  static_cast<I32>(numRecords),
166  static_cast<I32>(writeSize));
168  return;
169  }
170  // serialize record size = id field + data
171  U32 recordSize = static_cast<U32>(sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength());
172 
173  // reset buffer
174  buff.resetSer();
175  Fw::SerializeStatus serStat = buff.serialize(recordSize);
176  // should always work
177  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
178 
179  // write record size
180  writeSize = buff.getBuffLength();
181  stat = paramFile.write(buff.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
182  if (stat != Os::File::OP_OK) {
183  this->unLock();
184  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE,static_cast<I32>(numRecords),stat);
186  return;
187  }
188  if (writeSize != sizeof(recordSize)) {
189  this->unLock();
192  static_cast<I32>(numRecords),
193  static_cast<I32>(writeSize));
195  return;
196  }
197 
198  // reset buffer
199  buff.resetSer();
200 
201  // serialize parameter id
202 
203  serStat = buff.serialize(this->m_db[entry].id);
204  // should always work
205  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
206 
207  // write parameter ID
208  writeSize = buff.getBuffLength();
209  stat = paramFile.write(buff.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
210  if (stat != Os::File::OP_OK) {
211  this->unLock();
212  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID,static_cast<I32>(numRecords),stat);
214  return;
215  }
216  if (writeSize != static_cast<FwSignedSizeType>(buff.getBuffLength())) {
217  this->unLock();
220  static_cast<I32>(numRecords),
221  static_cast<I32>(writeSize));
223  return;
224  }
225 
226  // write serialized parameter value
227 
228  writeSize = this->m_db[entry].val.getBuffLength();
229  stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,Os::File::WaitType::WAIT);
230  if (stat != Os::File::OP_OK) {
231  this->unLock();
232  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE,static_cast<I32>(numRecords),stat);
234  return;
235  }
236  if (writeSize != static_cast<FwSignedSizeType>(this->m_db[entry].val.getBuffLength())) {
237  this->unLock();
240  static_cast<I32>(numRecords),
241  static_cast<I32>(writeSize));
243  return;
244  }
245  numRecords++;
246  } // end if record in use
247  } // end for each record
248 
249  this->unLock();
250  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
251  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
252 
253  }
254 
256  }
257 
259  FW_ASSERT(this->m_fileName.length() > 0);
260  // load file. FIXME: Put more robust file checking, such as a CRC.
261  Os::File paramFile;
262 
263  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_READ);
264  if (stat != Os::File::OP_OK) {
266  return;
267  }
268 
269  WorkingBuffer buff;
270 
271  U32 recordNum = 0;
272 
273  this->clearDb();
274 
275  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
276 
277  U8 delimiter;
278  FwSignedSizeType readSize = static_cast<FwSignedSizeType>(sizeof(delimiter));
279 
280  // read delimiter
281  Os::File::Status fStat = paramFile.read(&delimiter,readSize,Os::File::WaitType::WAIT);
282 
283  // check for end of file (read size 0)
284  if (0 == readSize) {
285  break;
286  }
287 
288  if (fStat != Os::File::OP_OK) {
289  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER,static_cast<I32>(recordNum),fStat);
290  return;
291  }
292 
293  if (sizeof(delimiter) != readSize) {
294  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
295  return;
296  }
297 
298  if (PRMDB_ENTRY_DELIMITER != delimiter) {
299  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE,static_cast<I32>(recordNum),delimiter);
300  return;
301  }
302 
303  U32 recordSize = 0;
304  // read record size
305  readSize = sizeof(recordSize);
306 
307  fStat = paramFile.read(buff.getBuffAddr(),readSize,Os::File::WaitType::WAIT);
308  if (fStat != Os::File::OP_OK) {
309  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE,static_cast<I32>(recordNum),fStat);
310  return;
311  }
312  if (sizeof(recordSize) != readSize) {
313  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
314  return;
315  }
316  // set serialized size to read size
317  Fw::SerializeStatus desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
318  // should never fail
319  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
320  // reset deserialization
321  buff.resetDeser();
322  // deserialize, since record size is serialized in file
323  desStat = buff.deserialize(recordSize);
324  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
325 
326  // sanity check value. It can't be larger than the maximum parameter buffer size + id
327  // or smaller than the record id
328  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
329  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE,static_cast<I32>(recordNum),static_cast<I32>(recordSize));
330  return;
331  }
332 
333  // read the parameter ID
334  FwPrmIdType parameterId = 0;
335  readSize = static_cast<FwSignedSizeType>(sizeof(FwPrmIdType));
336 
337  fStat = paramFile.read(buff.getBuffAddr(),readSize,Os::File::WaitType::WAIT);
338  if (fStat != Os::File::OP_OK) {
339  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID,static_cast<I32>(recordNum),fStat);
340  return;
341  }
342  if (sizeof(parameterId) != static_cast<FwSizeType>(readSize)) {
343  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
344  return;
345  }
346 
347  // set serialized size to read parameter ID
348  desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
349  // should never fail
350  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
351  // reset deserialization
352  buff.resetDeser();
353  // deserialize, since parameter ID is serialized in file
354  desStat = buff.deserialize(parameterId);
355  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
356 
357  // copy parameter
358  this->m_db[entry].used = true;
359  this->m_db[entry].id = parameterId;
360  readSize = recordSize-sizeof(parameterId);
361 
362  fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
363 
364  if (fStat != Os::File::OP_OK) {
365  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE,static_cast<I32>(recordNum),fStat);
366  return;
367  }
368  if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
369  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE,static_cast<I32>(recordNum),static_cast<I32>(readSize));
370  return;
371  }
372 
373  // set serialized size to read size
374  desStat = this->m_db[entry].val.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
375  // should never fail
376  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
377  recordNum++;
378 
379  }
380 
381  this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
382  }
383 
384  void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
385  // respond to ping
386  this->pingOut_out(0,key);
387  }
388 
389 
390 
391 }
#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
PlatformSignedSizeType FwSignedSizeType
Definition: FpConfig.h:25
#define FW_PARAM_BUFFER_MAX_SIZE
Definition: FpConfig.h:315
U32 FwOpcodeType
Definition: FpConfig.h:78
PlatformSizeType FwSizeType
Definition: FpConfig.h:30
U32 FwPrmIdType
Definition: FpConfig.h:90
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.
NATIVE_UINT_TYPE SizeType
Serializable::SizeType getBuffLength() const
returns current buffer size
SizeType length() const
Get length of string.
Definition: StringBase.cpp:116
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:142
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:162
@ 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_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(FwIndexType 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 log_ACTIVITY_HI_PrmIdAdded(U32 Id)
void readParamFile()
PrmDb file read function.
Definition: PrmDbImpl.cpp:258
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:255
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