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