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 
8 #include <Fw/Types/Assert.hpp>
10 
11 #include <Os/File.hpp>
12 extern "C" {
14 }
15 
16 #include <cstdio>
17 #include <cstring>
18 
19 static_assert(std::numeric_limits<FwSizeType>::max() >= PRMDB_NUM_DB_ENTRIES,
20  "PRMDB_NUM_DB_ENTRIES must fit within range of FwSizeType");
21 
22 namespace Svc {
23 
24 // anonymous namespace for buffer declaration
25 namespace {
26 class WorkingBuffer : public Fw::SerializeBufferBase {
27  public:
28  FwSizeType getCapacity() const { return sizeof(m_buff); }
29 
30  U8* getBuffAddr() { return m_buff; }
31 
32  const U8* getBuffAddr() const { return m_buff; }
33 
34  private:
35  // Set to max of parameter buffer + id
36  U8 m_buff[FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)];
37  static_assert(sizeof(m_buff) >= sizeof(U32), "Size of parameter buffer storage must be >= sizeof(U32)");
38 };
39 } // namespace
40 
44 PrmDbImpl::PrmDbImpl(const char* name) : PrmDbComponentBase(name), m_state(PrmDbFileLoadState::IDLE) {
45  this->m_activeDb = &this->m_dbStore1;
46  this->m_stagingDb = &this->m_dbStore2;
47 
48  this->clearDb(PrmDbType::DB_ACTIVE);
49  this->clearDb(PrmDbType::DB_STAGING);
50 }
51 
53 
54 void PrmDbImpl::configure(const char* file) {
55  FW_ASSERT(file != nullptr);
56  this->m_fileName = file;
57 }
58 
60  // Assumed to run at initialization time
61  // State should be IDLE upon entry
62  FW_ASSERT(static_cast<FwAssertArgType>(m_state == PrmDbFileLoadState::IDLE));
63 
64  // Clear databases
65  this->clearDb(PrmDbType::DB_ACTIVE);
66  this->clearDb(PrmDbType::DB_STAGING);
67 
68  // Read parameter file to active database
69  (void)readParamFileImpl(this->m_fileName, PrmDbType::DB_ACTIVE);
70 }
71 
75 
76 // If ports are no longer guarded, these accesses need to be protected from each other
77 // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
78 
79 Fw::ParamValid PrmDbImpl::getPrm_handler(FwIndexType portNum, FwPrmIdType id, Fw::ParamBuffer& val) {
80  // search for entry
81  auto success = this->m_activeDb->find(id, val);
82 
83  switch (success.e) {
85  // if unable to find parameter, send error message
89  return Fw::ParamValid::VALID;
90  default:
91  FW_ASSERT(0, success.e);
93  }
94 }
95 
96 void PrmDbImpl::setPrm_handler(FwIndexType portNum, FwPrmIdType id, Fw::ParamBuffer& val) {
97  // Reject parameter updates during non-idle file load states
98  if (m_state != PrmDbFileLoadState::IDLE) {
100  return;
101  }
102 
103  // Update the parameter in the active database
104  PrmUpdateType update_status = updateAddPrmImpl(id, val, PrmDbType::DB_ACTIVE);
105 
106  // Issue relevant EVR
107  if (update_status == PARAM_UPDATED) {
109  } else if (update_status == NO_SLOTS) {
110  this->log_WARNING_HI_PrmDbFull(id);
111  } else {
112  this->log_ACTIVITY_HI_PrmIdAdded(id);
113  }
114 }
115 
116 void PrmDbImpl::pingIn_handler(FwIndexType portNum, U32 key) {
117  // respond to ping
118  this->pingOut_out(0, key);
119 }
120 
121 U32 PrmDbImpl::computeCrc(U32 crc, const BYTE* buff, FwSizeType size) {
122  // Note: The crc parameter accepts any U32 value as valid input.
123  // This is correct behavior for CRC32 accumulation functions where:
124  // - Initial CRC values are typically 0x00000000 or 0xFFFFFFFF
125  // - Intermediate CRC values (from prior computeCrc calls) can be any U32 value
126 
127  // Check for null pointer before dereferencing
128  if (buff == nullptr) {
129  // Return the input CRC unchanged if buffer is null
130  return crc;
131  }
132 
133  // Check for zero size to avoid unnecessary processing
134  if (size == 0) {
135  return crc;
136  }
137  for (FwSizeType byte = 0; byte < size; byte++) {
138  crc = static_cast<U32>(update_crc_32(crc, static_cast<char>(buff[byte])));
139  }
140  return crc;
141 }
142 
143 void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
144  // Reject PRM_SAVE_FILE command during non-idle file load states
145  if (m_state != PrmDbFileLoadState::IDLE) {
147  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
148  return;
149  }
150 
151  FW_ASSERT(this->m_fileName.length() > 0);
152 
153  Os::File paramFile;
154  WorkingBuffer buff;
155 
156  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE);
157  if (stat != Os::File::OP_OK) {
159  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
160  return;
161  }
162 
163  // write placeholder for the CRC
164  U32 crc = 0xFFFFFFFF;
165  buff.resetSer();
166  Fw::SerializeStatus serStat = buff.serializeFrom(crc);
167  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
168  FwSizeType writeSize = static_cast<FwSizeType>(buff.getSize());
169  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
170 
171  if (stat != Os::File::OP_OK) {
173  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
174  return;
175  }
176 
177  this->lock();
178  auto db = getDbPtr(PrmDbType::DB_ACTIVE);
179  FW_ASSERT(db != nullptr);
180 
181  // Traverse the parameter list, saving each entry
182 
183  U32 numRecords = 0;
184 
185  for (const auto& entry : *db) {
186  // write delimiter
187  static const U8 delim = PRMDB_ENTRY_DELIMITER;
188  writeSize = static_cast<FwSizeType>(sizeof(delim));
189  stat = paramFile.write(&delim, writeSize, Os::File::WaitType::WAIT);
190  if (stat != Os::File::OP_OK) {
191  this->unLock();
192  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER, static_cast<I32>(numRecords), stat);
193  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
194  return;
195  }
196  if (writeSize != sizeof(delim)) {
197  this->unLock();
198  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER_SIZE, static_cast<I32>(numRecords),
199  static_cast<I32>(writeSize));
200  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
201  return;
202  }
203 
204  // add delimiter to CRC
205  crc = this->computeCrc(crc, &delim, sizeof(delim));
206 
207  // serialize record size = id field + data
208  U32 recordSize = static_cast<U32>(sizeof(FwPrmIdType) + entry.getValue().getSize());
209 
210  // reset buffer
211  buff.resetSer();
212  serStat = buff.serializeFrom(recordSize);
213  // should always work
214  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
215 
216  // write record size
217  writeSize = static_cast<FwSizeType>(buff.getSize());
218  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
219  if (stat != Os::File::OP_OK) {
220  this->unLock();
221  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE, static_cast<I32>(numRecords), stat);
222  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
223  return;
224  }
225  if (writeSize != sizeof(recordSize)) {
226  this->unLock();
227  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE_SIZE, static_cast<I32>(numRecords),
228  static_cast<I32>(writeSize));
229  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
230  return;
231  }
232 
233  // add recordSize to CRC
234  crc = this->computeCrc(crc, buff.getBuffAddr(), writeSize);
235 
236  // reset buffer
237  buff.resetSer();
238 
239  // serialize parameter id
240 
241  serStat = buff.serializeFrom(entry.getKey());
242  // should always work
243  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
244 
245  // write parameter ID
246  writeSize = static_cast<FwSizeType>(buff.getSize());
247  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
248  if (stat != Os::File::OP_OK) {
249  this->unLock();
250  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID, static_cast<I32>(numRecords), stat);
251  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
252  return;
253  }
254  if (writeSize != static_cast<FwSizeType>(buff.getSize())) {
255  this->unLock();
256  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID_SIZE, static_cast<I32>(numRecords),
257  static_cast<I32>(writeSize));
258  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
259  return;
260  }
261 
262  // add parameter ID to CRC
263  crc = this->computeCrc(crc, buff.getBuffAddr(), writeSize);
264 
265  // write serialized parameter value
266 
267  writeSize = static_cast<FwSizeType>(entry.getValue().getSize());
268  stat = paramFile.write(entry.getValue().getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
269  if (stat != Os::File::OP_OK) {
270  this->unLock();
271  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE, static_cast<I32>(numRecords), stat);
272  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
273  return;
274  }
275  if (writeSize != static_cast<FwSizeType>(entry.getValue().getSize())) {
276  this->unLock();
277  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE_SIZE, static_cast<I32>(numRecords),
278  static_cast<I32>(writeSize));
279  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
280  return;
281  }
282 
283  // add serialized parameter value to crc
284  crc = this->computeCrc(crc, entry.getValue().getBuffAddr(), writeSize);
285 
286  numRecords++;
287  }
288 
289  this->unLock();
290 
291  // save current location of pointer in paramFile
292  FwSizeType currPosInParamFile;
293 
294  stat = paramFile.position(currPosInParamFile);
295  if (stat != Os::File::OP_OK) {
297  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
298  return;
299  }
300 
301  // seek to beginning and write CRC value
302  stat = paramFile.seek(0, Os::File::SeekType::ABSOLUTE);
303  if (stat != Os::File::OP_OK) {
305  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
306  return;
307  }
308  buff.resetSer();
309  serStat = buff.serializeFrom(crc);
310 
311  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
312  writeSize = static_cast<FwSizeType>(buff.getSize());
313 
314  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
315  if (stat != Os::File::OP_OK) {
317  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
318  return;
319  }
320 
321  // Restore pointer to previously saved location
322  stat = paramFile.seek(static_cast<FwSignedSizeType>(currPosInParamFile), Os::File::SeekType::ABSOLUTE);
323  if (stat != Os::File::OP_OK) {
325  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
326  return;
327  }
328 
329  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
330  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
331 }
332 
333 void PrmDbImpl::PRM_LOAD_FILE_cmdHandler(FwOpcodeType opCode,
334  U32 cmdSeq,
335  const Fw::CmdStringArg& fileName,
336  PrmDb_Merge merge) {
337  // Reject PRM_LOAD_FILE command during non-idle file load states
338  if (m_state != PrmDbFileLoadState::IDLE) {
340  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
341  return;
342  }
343 
344  // Set state to loading
346 
347  // If reset is true, clear the staging database first
348  if (merge == PrmDb_Merge::MERGE) {
349  // Copy active to staging for merging
351  } else {
352  // reset staging db, all file contents will be loaded but no old parameters will be retained
353  this->clearDb(PrmDbType::DB_STAGING);
354  }
355 
356  // Load the file into staging database
357  // The readParamFileImpl will emit the relevant EVR if the file load fails
358  // and also if it succeeds will emit EVRs with the number of records
359  PrmDbImpl::PrmLoadStatus success = PrmDbImpl::readParamFileImpl(fileName, PrmDbType::DB_STAGING);
360 
361  if (success == PrmLoadStatus::SUCCESS) {
362  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
364  } else {
366  // clear the staging DB and reset to an IDLE state in case of issues
367  this->clearDb(PrmDbType::DB_STAGING);
368  m_state = PrmDbFileLoadState::IDLE;
369  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
370  }
371 }
372 
373 void PrmDbImpl::PRM_COMMIT_STAGED_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
374  // Verify we are in the correct state
377  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
378  return;
379  }
380 
381  // Swap active and staging databases, safely w.r.t. prmGet
382  this->lock();
383  PrmDbStore* temp = this->m_activeDb;
384  this->m_activeDb = this->m_stagingDb;
385  this->unLock();
386  this->m_stagingDb = temp;
387 
388  // Clear the new staging database
389  this->clearDb(PrmDbType::DB_STAGING);
390 
391  // Set file load state to idle
392  m_state = PrmDbFileLoadState::IDLE;
393 
395  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
396 }
397 
401 
402 PrmDbImpl::PrmLoadStatus PrmDbImpl::readParamFileImpl(const Fw::StringBase& fileName, PrmDbType dbType) {
403  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
404  FW_ASSERT(fileName.length() > 0);
405 
406  Fw::String dbString = getDbString(dbType);
407 
408  // load file. FIXME: Put more robust file checking, such as a CRC.
409  Os::File paramFile;
410 
411  Os::File::Status stat = paramFile.open(fileName.toChar(), Os::File::OPEN_READ);
412  if (stat != Os::File::OP_OK) {
414  return PrmLoadStatus::ERROR;
415  }
416  //===========================================================================
417  // read CRC from beginning of file
418  WorkingBuffer buff;
419  U32 fileCrc;
420  FwSizeType readSize = static_cast<FwSizeType>(sizeof(fileCrc));
421 
422  // Read raw CRC bytes from file
423  stat = paramFile.read(buff.getBuffAddr(), readSize);
424  if (stat != Os::File::OP_OK) {
425  this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC, static_cast<I32>(0), stat);
426  return PrmLoadStatus::ERROR;
427  }
428 
429  if (readSize != sizeof(fileCrc)) {
430  this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC_SIZE, static_cast<I32>(0), static_cast<I32>(readSize));
431  return PrmLoadStatus::ERROR;
432  }
433 
434  // Deserialize the CRC in a portable way
435  Fw::SerializeStatus serStat = buff.setBuffLen(readSize);
436  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
437  buff.resetDeser();
438  serStat = buff.deserializeTo(fileCrc);
439  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
440 
441  U32 crc = 0xFFFFFFFF;
442  // read into CRC buffer for checking
443 
444  Os::File::Status status = paramFile.calculateCrc(crc);
445  if (status != Os::File::OP_OK) {
446  this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC_BUFFER, static_cast<I32>(0), status);
447  return PrmLoadStatus::ERROR;
448  }
449 
450  if (fileCrc != crc) {
451  this->log_WARNING_HI_PrmFileBadCrc(fileCrc, crc);
452  return PrmLoadStatus::ERROR;
453  }
454 
455  // seek back to just after CRC
456  stat = paramFile.seek(sizeof(fileCrc), Os::File::SeekType::ABSOLUTE);
457  if (stat != Os::File::OP_OK) {
459  return PrmLoadStatus::ERROR;
460  }
461  //===========================================================================
462 
463  U32 recordNumTotal = 0;
464  U32 recordNumAdded = 0;
465  U32 recordNumUpdated = 0;
466 
467  for (FwSizeType entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
468  U8 delimiter;
469  readSize = static_cast<FwSizeType>(sizeof(delimiter));
470 
471  // read delimiter
472  Os::File::Status fStat = paramFile.read(&delimiter, readSize, Os::File::WaitType::WAIT);
473 
474  // check for end of file (read size 0)
475  if (0 == readSize) {
476  break;
477  }
478 
479  if (fStat != Os::File::OP_OK) {
480  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER, static_cast<I32>(recordNumTotal), fStat);
481  return PrmLoadStatus::ERROR;
482  }
483 
484  if (sizeof(delimiter) != readSize) {
485  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE, static_cast<I32>(recordNumTotal),
486  static_cast<I32>(readSize));
487  return PrmLoadStatus::ERROR;
488  }
489 
490  if (PRMDB_ENTRY_DELIMITER != delimiter) {
491  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE, static_cast<I32>(recordNumTotal),
492  delimiter);
493  return PrmLoadStatus::ERROR;
494  }
495 
496  U32 recordSize = 0;
497 
498  // read record size
499  readSize = sizeof(recordSize);
500 
501  fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
502  if (fStat != Os::File::OP_OK) {
503  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE, static_cast<I32>(recordNumTotal), fStat);
504  return PrmLoadStatus::ERROR;
505  }
506  if (sizeof(recordSize) != readSize) {
507  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE, static_cast<I32>(recordNumTotal),
508  static_cast<I32>(readSize));
509  return PrmLoadStatus::ERROR;
510  }
511  // set serialized size to read size
512  Fw::SerializeStatus desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
513  // should never fail
514  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
515  // reset deserialization
516  buff.resetDeser();
517  // deserialize, since record size is serialized in file
518  desStat = buff.deserializeTo(recordSize);
519  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
520 
521  // sanity check value. It can't be larger than the maximum parameter buffer size + id
522  // or smaller than the record id
523  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
524  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE, static_cast<I32>(recordNumTotal),
525  static_cast<I32>(recordSize));
526  return PrmLoadStatus::ERROR;
527  }
528 
529  // read the parameter ID
530  FwPrmIdType parameterId = 0;
531  readSize = static_cast<FwSizeType>(sizeof(FwPrmIdType));
532 
533  fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
534  if (fStat != Os::File::OP_OK) {
535  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID, static_cast<I32>(recordNumTotal), fStat);
536  return PrmLoadStatus::ERROR;
537  }
538  if (sizeof(parameterId) != static_cast<FwSizeType>(readSize)) {
539  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE, static_cast<I32>(recordNumTotal),
540  static_cast<I32>(readSize));
541  return PrmLoadStatus::ERROR;
542  }
543 
544  // set serialized size to read parameter ID
545  desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
546  // should never fail
547  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
548  // reset deserialization
549  buff.resetDeser();
550  // deserialize, since parameter ID is serialized in file
551  desStat = buff.deserializeTo(parameterId);
552  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
553 
554  // copy parameter value from file into a temporary buffer
555  Fw::ParamBuffer tmpParamBuffer; // temporary param buffer to read parameter value from file
556  readSize = recordSize - sizeof(parameterId);
557  desStat = tmpParamBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
558  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat)); // should never fail
559  fStat = paramFile.read(tmpParamBuffer.getBuffAddr(), readSize);
560 
561  if (fStat != Os::File::OP_OK) {
562  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE, static_cast<I32>(recordNumTotal),
563  fStat);
564  return PrmLoadStatus::ERROR;
565  }
566  if (static_cast<U32>(readSize) != recordSize - sizeof(parameterId)) {
567  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE, static_cast<I32>(recordNumTotal),
568  static_cast<I32>(readSize));
569  return PrmLoadStatus::ERROR;
570  }
571 
572  // Actually update or add parameter
573  PrmUpdateType updateStatus = updateAddPrmImpl(parameterId, tmpParamBuffer, dbType);
574  if (updateStatus == PARAM_ADDED) {
575  recordNumAdded++;
576  } else if (updateStatus == PARAM_UPDATED) {
577  recordNumUpdated++;
578  }
579 
580  if (updateStatus == NO_SLOTS) {
581  this->log_WARNING_HI_PrmDbFull(parameterId);
582  }
583  recordNumTotal++;
584  }
585 
586  this->log_ACTIVITY_HI_PrmFileLoadComplete(dbString, recordNumTotal, recordNumAdded, recordNumUpdated);
587  return PrmLoadStatus::SUCCESS;
588 }
589 
590 PrmDbImpl::PrmUpdateType PrmDbImpl::updateAddPrmImpl(FwPrmIdType id, Fw::ParamBuffer& val, PrmDbType prmDbType) {
591  auto* db = getDbPtr(prmDbType);
592 
593  PrmUpdateType updateStatus = NO_SLOTS;
594 
595  this->lock();
596 
597  auto prevSize = db->getSize();
598  switch (db->insert(id, val)) {
600  updateStatus = NO_SLOTS;
601  break;
603  if (prevSize < db->getSize()) {
604  updateStatus = PARAM_ADDED;
605  } else {
606  FW_ASSERT(prevSize == db->getSize(), static_cast<FwAssertArgType>(prevSize),
607  static_cast<FwAssertArgType>(db->getSize()));
608  updateStatus = PARAM_UPDATED;
609  }
610  break;
611  default:
612  FW_ASSERT(false);
613  }
614 
615  this->unLock();
616  return updateStatus;
617 }
618 
622 
623 void PrmDbImpl::clearDb(PrmDbType prmDbType) {
624  getDbPtr(prmDbType)->clear();
625 }
626 
627 void PrmDbImpl::dbCopy(PrmDbType dest, PrmDbType src) {
628  *getDbPtr(dest) = *getDbPtr(src);
629  this->log_ACTIVITY_HI_PrmDbCopyAllComplete(getDbString(src), getDbString(dest));
630 }
631 
632 PrmDbImpl::PrmDbStore* PrmDbImpl::getDbPtr(PrmDbType dbType) {
633  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
634  if (dbType == PrmDbType::DB_ACTIVE) {
635  return m_activeDb;
636  }
637  return m_stagingDb;
638 }
639 
640 Fw::String PrmDbImpl::getDbString(PrmDbType dbType) {
641  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
642  if (dbType == PrmDbType::DB_ACTIVE) {
643  return Fw::String("ACTIVE");
644  }
645  return Fw::String("STAGING");
646 }
647 
648 } // namespace Svc
Serialization/Deserialization operation was successful.
Parameter already in database, updated parameter.
Definition: PrmDbImpl.hpp:75
State of parameter DB file load operations.
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
Definition: PrmBuffer.cpp:42
FwIdType FwOpcodeType
The type of a command opcode.
Status calculateCrc(U32 &crc)
calculate the CRC32 of the entire file
Definition: File.cpp:212
Representing success.
PlatformSizeType FwSizeType
Operation failed.
Definition: Os.hpp:27
void log_ACTIVITY_HI_PrmIdUpdated(FwPrmIdType Id) const
void readParamFile()
PrmDb file read function.
Definition: PrmDbImpl.cpp:59
const char * toChar() const
Convert to a C-style char*.
Definition: String.hpp:50
FwIdType FwPrmIdType
The type of a parameter identifier.
void log_ACTIVITY_HI_PrmFileSaveComplete(U32 records) const
virtual const CHAR * toChar() const =0
Convert to a C-style char*.
Open file for writing.
Definition: File.hpp:33
PrmDbImpl(const char *name)
PrmDb constructor.
Definition: PrmDbImpl.cpp:44
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
PrmDb_PrmDbType PrmDbType
Definition: PrmDbImpl.hpp:29
void log_WARNING_HI_PrmFileWriteError(Svc::PrmDb_PrmWriteError stage, I32 record, I32 error) const
Parameter added to database.
Definition: PrmDbImpl.hpp:74
void log_ACTIVITY_HI_PrmFileLoadComplete(const Fw::StringBase &databaseString, U32 recordsTotal, U32 recordsAdded, U32 recordsUpdated) const
SerializeStatus
forward declaration for string
unsigned long update_crc_32(unsigned long crc, char c)
Definition: lib_crc.c:272
virtual void lock()
Lock the guarded mutex.
void log_WARNING_HI_PrmFileReadError(Svc::PrmDb_PrmReadError stage, I32 record, I32 error) const
void log_ACTIVITY_HI_PrmDbCommitComplete() const
void clear() override
Clear the map.
Definition: ArrayMap.hpp:73
void log_WARNING_LO_PrmDbFileLoadInvalidAction(Svc::PrmDb_PrmDbFileLoadState currentState, Svc::PrmDb_PrmLoadAction attemptedAction) const
Status seek(FwSignedSizeType offset, SeekType seekType) override
seek the file pointer to the given offset
Definition: File.cpp:117
virtual void unLock()
Unlock the guarded mutex.
void log_ACTIVITY_HI_PrmIdAdded(FwPrmIdType Id) const
void log_ACTIVITY_HI_PrmDbCopyAllComplete(const Fw::StringBase &databaseStringSrc, const Fw::StringBase &databaseStringDest) const
void configure(const char *file)
PrmDb configure method.
Definition: PrmDbImpl.cpp:54
Representing failure.
Command successfully executed.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
void log_WARNING_HI_PrmDbFull(FwPrmIdType Id) const
void pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Definition: File.cpp:169
Auto-generated base for PrmDb component.
Command had execution error.
void log_WARNING_LO_PrmIdNotFound(FwPrmIdType Id)
Operation was successful.
Definition: File.hpp:40
Success find(const K &key, V &value) const override
Definition: ArrayMap.hpp:81
PlatformIndexType FwIndexType
Open file for reading.
Definition: File.hpp:31
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
Command failed validation.
RateGroupDivider component implementation.
virtual SizeType length() const
Get the length of the string.
Enum representing parameter validity.
U8 BYTE
byte type
Definition: BasicTypes.h:56
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
No slots available to add new parameter.
Definition: PrmDbImpl.hpp:73
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:52
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Component for managing parameters.
void log_WARNING_HI_PrmFileBadCrc(U32 readCrc, U32 compCrc) const
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.
void log_WARNING_HI_PrmDbFileLoadFailed() const