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