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::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;
71  stat = Fw::ParamValid::VALID;
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 {
122  this->log_ACTIVITY_HI_PrmIdAdded(id);
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 
252  }
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 
377  this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
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.
Definition: StringBase.cpp:125
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
@ 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:254
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:251
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