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 #include <Os/SandboxedFile.hpp>
13 #include <Utils/Hash/Hash.hpp>
14 
15 #include <cstdio>
16 #include <cstring>
17 
18 static_assert(std::numeric_limits<FwSizeType>::max() >= PRMDB_NUM_DB_ENTRIES,
19  "PRMDB_NUM_DB_ENTRIES must fit within range of FwSizeType");
20 
21 namespace Svc {
22 
23 // anonymous namespace for buffer declaration
24 namespace {
25 class WorkingBuffer : public Fw::LinearBufferBase {
26  public:
27  WorkingBuffer() : Fw::LinearBufferBase(m_buff, sizeof(m_buff)) {}
28 
29  private:
30  // Set to max of parameter buffer + id
31  U8 m_buff[FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)];
32  static_assert(sizeof(m_buff) >= sizeof(U32), "Size of parameter buffer storage must be >= sizeof(U32)");
33 };
34 } // namespace
35 
39 PrmDbImpl::PrmDbImpl(const char* name) : PrmDbComponentBase(name), m_state(PrmDbFileLoadState::IDLE) {
40  this->m_activeDb = &this->m_dbStore1;
41  this->m_stagingDb = &this->m_dbStore2;
42 
43  this->clearDb(PrmDbType::DB_ACTIVE);
44  this->clearDb(PrmDbType::DB_STAGING);
45 }
46 
48 
49 void PrmDbImpl::configure(const char* file) {
50  FW_ASSERT(file != nullptr);
51  this->m_fileName = file;
52 }
53 
54 void PrmDbImpl::configureLoadSandbox(const char* directory) {
55  FW_ASSERT(directory != nullptr);
56  this->m_sandboxDir = directory;
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(false, 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 void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
122  // Reject PRM_SAVE_FILE command during non-idle file load states
123  if (m_state != PrmDbFileLoadState::IDLE) {
125  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
126  return;
127  }
128 
129  FW_ASSERT(this->m_fileName.length() > 0);
130 
131  Os::File paramFile;
132  WorkingBuffer buff;
133 
134  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE, Os::File::OVERWRITE);
135  if (stat != Os::File::OP_OK) {
137  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
138  return;
139  }
140 
141  // write placeholder for the CRC
142  Utils::Hash crc;
143  U32 crcInitial = 0xFFFFFFFF;
144  buff.resetSer();
145  Fw::SerializeStatus serStat = buff.serializeFrom(crcInitial);
146  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
147  FwSizeType writeSize = static_cast<FwSizeType>(buff.getSize());
148  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
149 
150  if (stat != Os::File::OP_OK) {
152  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
153  return;
154  }
155 
156  this->lock();
157  auto db = getDbPtr(PrmDbType::DB_ACTIVE);
158  FW_ASSERT(db != nullptr);
159 
160  // Traverse the parameter list, saving each entry
161 
162  U32 numRecords = 0;
163 
164  for (const auto& entry : *db) {
165  // write delimiter
166  static const U8 delim = PRMDB_ENTRY_DELIMITER;
167  writeSize = static_cast<FwSizeType>(sizeof(delim));
168  stat = paramFile.write(&delim, writeSize, Os::File::WaitType::WAIT);
169  if (stat != Os::File::OP_OK) {
170  this->unLock();
171  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER, static_cast<I32>(numRecords), stat);
172  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
173  return;
174  }
175  if (writeSize != sizeof(delim)) {
176  this->unLock();
177  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER_SIZE, static_cast<I32>(numRecords),
178  static_cast<I32>(writeSize));
179  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
180  return;
181  }
182 
183  // add delimiter to CRC
184  crc.update(&delim, sizeof(delim));
185 
186  // serialize record size = id field + data
187  U32 recordSize = static_cast<U32>(sizeof(FwPrmIdType) + entry.getValue().getSize());
188 
189  // reset buffer
190  buff.resetSer();
191  serStat = buff.serializeFrom(recordSize);
192  // should always work
193  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
194 
195  // write record size
196  writeSize = static_cast<FwSizeType>(buff.getSize());
197  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
198  if (stat != Os::File::OP_OK) {
199  this->unLock();
200  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE, static_cast<I32>(numRecords), stat);
201  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
202  return;
203  }
204  if (writeSize != sizeof(recordSize)) {
205  this->unLock();
206  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE_SIZE, static_cast<I32>(numRecords),
207  static_cast<I32>(writeSize));
208  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
209  return;
210  }
211 
212  // add recordSize to CRC
213  if (buff.getBuffAddr() != nullptr && writeSize != 0) {
214  crc.update(buff.getBuffAddr(), writeSize);
215  }
216 
217  // reset buffer
218  buff.resetSer();
219 
220  // serialize parameter id
221 
222  serStat = buff.serializeFrom(entry.getKey());
223  // should always work
224  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
225 
226  // write parameter ID
227  writeSize = static_cast<FwSizeType>(buff.getSize());
228  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
229  if (stat != Os::File::OP_OK) {
230  this->unLock();
231  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID, static_cast<I32>(numRecords), stat);
232  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
233  return;
234  }
235  if (writeSize != static_cast<FwSizeType>(buff.getSize())) {
236  this->unLock();
237  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID_SIZE, static_cast<I32>(numRecords),
238  static_cast<I32>(writeSize));
239  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
240  return;
241  }
242 
243  // add parameter ID to CRC
244  if (buff.getBuffAddr() != nullptr && writeSize != 0) {
245  crc.update(buff.getBuffAddr(), writeSize);
246  }
247 
248  // write serialized parameter value
249 
250  writeSize = static_cast<FwSizeType>(entry.getValue().getSize());
251  stat = paramFile.write(entry.getValue().getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
252  if (stat != Os::File::OP_OK) {
253  this->unLock();
254  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE, static_cast<I32>(numRecords), stat);
255  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
256  return;
257  }
258  if (writeSize != static_cast<FwSizeType>(entry.getValue().getSize())) {
259  this->unLock();
260  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE_SIZE, static_cast<I32>(numRecords),
261  static_cast<I32>(writeSize));
262  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
263  return;
264  }
265 
266  // add serialized parameter value to crc
267  if (entry.getValue().getBuffAddr() != nullptr && writeSize != 0) {
268  crc.update(entry.getValue().getBuffAddr(), writeSize);
269  }
270 
271  numRecords++;
272  }
273 
274  this->unLock();
275 
276  // save current location of pointer in paramFile
277  FwSizeType currPosInParamFile;
278 
279  stat = paramFile.position(currPosInParamFile);
280  if (stat != Os::File::OP_OK) {
282  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
283  return;
284  }
285 
286  // seek to beginning and write CRC value
287  stat = paramFile.seek(0, Os::File::SeekType::ABSOLUTE);
288  if (stat != Os::File::OP_OK) {
290  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
291  return;
292  }
293  buff.resetSer();
294  U32 crcFinal = 0;
295  crc.finalize(crcFinal);
296  crcFinal = ~crcFinal;
297  serStat = buff.serializeFrom(crcFinal);
298 
299  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
300  writeSize = static_cast<FwSizeType>(buff.getSize());
301 
302  stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
303  if (stat != Os::File::OP_OK) {
305  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
306  return;
307  }
308 
309  // Restore pointer to previously saved location
310  stat = paramFile.seek(static_cast<FwSignedSizeType>(currPosInParamFile), Os::File::SeekType::ABSOLUTE);
311  if (stat != Os::File::OP_OK) {
313  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
314  return;
315  }
316 
317  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
318  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
319 }
320 
321 void PrmDbImpl::PRM_LOAD_FILE_cmdHandler(FwOpcodeType opCode,
322  U32 cmdSeq,
323  const Fw::CmdStringArg& fileName,
324  const PrmDb_Merge& merge) {
325  // Reject PRM_LOAD_FILE command during non-idle file load states
326  if (m_state != PrmDbFileLoadState::IDLE) {
328  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
329  return;
330  }
331 
332  // Set state to loading
334 
335  // If reset is true, clear the staging database first
336  if (merge == PrmDb_Merge::MERGE) {
337  // Copy active to staging for merging
339  } else {
340  // reset staging db, all file contents will be loaded but no old parameters will be retained
341  this->clearDb(PrmDbType::DB_STAGING);
342  }
343 
344  // Load the file into staging database
345  // The readParamFileImpl will emit the relevant EVR if the file load fails
346  // and also if it succeeds will emit EVRs with the number of records
347  PrmDbImpl::PrmLoadStatus success = PrmDbImpl::readParamFileImpl(fileName, PrmDbType::DB_STAGING);
348 
349  if (success == PrmLoadStatus::SUCCESS) {
350  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
352  } else {
354  // clear the staging DB and reset to an IDLE state in case of issues
355  this->clearDb(PrmDbType::DB_STAGING);
356  m_state = PrmDbFileLoadState::IDLE;
357  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
358  }
359 }
360 
361 void PrmDbImpl::PRM_COMMIT_STAGED_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
362  // Verify we are in the correct state
365  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
366  return;
367  }
368 
369  // Swap active and staging databases, safely w.r.t. prmGet
370  this->lock();
371  PrmDbStore* temp = this->m_activeDb;
372  this->m_activeDb = this->m_stagingDb;
373  this->unLock();
374  this->m_stagingDb = temp;
375 
376  // Clear the new staging database
377  this->clearDb(PrmDbType::DB_STAGING);
378 
379  // Set file load state to idle
380  m_state = PrmDbFileLoadState::IDLE;
381 
383  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
384 }
385 
389 
390 PrmDbImpl::PrmLoadStatus PrmDbImpl::readParamFileImpl(const Fw::StringBase& fileName, PrmDbType dbType) {
391  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
392  FW_ASSERT(fileName.length() > 0);
393 
394  // Commanded loads (staging) may carry a ground-supplied path; restrict them
395  // to the configured sandbox directory to prevent path traversal
396  if ((dbType == PrmDbType::DB_STAGING) && (this->m_sandboxDir.length() > 0)) {
397  Os::SandboxedFile paramFile;
398  paramFile.configure(this->m_sandboxDir.toChar());
399  return this->readParamFileWork(paramFile, fileName, dbType);
400  }
401  Os::File paramFile;
402  return this->readParamFileWork(paramFile, fileName, dbType);
403 }
404 
405 template <typename FileType>
406 PrmDbImpl::PrmLoadStatus PrmDbImpl::readParamFileWork(FileType& paramFile,
407  const Fw::StringBase& fileName,
408  PrmDbType dbType) {
409  Fw::String dbString = getDbString(dbType);
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  U32 recordNumDropped = 0;
467 
468  for (FwSizeType entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
469  U8 delimiter;
470  readSize = static_cast<FwSizeType>(sizeof(delimiter));
471 
472  // read delimiter
473  Os::File::Status fStat = paramFile.read(&delimiter, readSize, Os::File::WaitType::WAIT);
474 
475  // check for end of file (successful read of size 0); a failed read can
476  // also yield size 0 and must not be mistaken for a clean EOF
477  if ((Os::File::OP_OK == fStat) && (0 == readSize)) {
478  break;
479  }
480 
481  if (fStat != Os::File::OP_OK) {
482  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER, static_cast<I32>(recordNumTotal), fStat);
483  return PrmLoadStatus::ERROR;
484  }
485 
486  if (sizeof(delimiter) != readSize) {
487  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE, static_cast<I32>(recordNumTotal),
488  static_cast<I32>(readSize));
489  return PrmLoadStatus::ERROR;
490  }
491 
492  if (PRMDB_ENTRY_DELIMITER != delimiter) {
493  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE, static_cast<I32>(recordNumTotal),
494  delimiter);
495  return PrmLoadStatus::ERROR;
496  }
497 
498  U32 recordSize = 0;
499 
500  // read record size
501  readSize = sizeof(recordSize);
502 
503  fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
504  if (fStat != Os::File::OP_OK) {
505  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE, static_cast<I32>(recordNumTotal), fStat);
506  return PrmLoadStatus::ERROR;
507  }
508  if (sizeof(recordSize) != readSize) {
509  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE, static_cast<I32>(recordNumTotal),
510  static_cast<I32>(readSize));
511  return PrmLoadStatus::ERROR;
512  }
513  // set serialized size to read size
514  Fw::SerializeStatus desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
515  // should never fail
516  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
517  // reset deserialization
518  buff.resetDeser();
519  // deserialize, since record size is serialized in file
520  desStat = buff.deserializeTo(recordSize);
521  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
522 
523  // sanity check value. It can't be larger than the maximum parameter buffer size + id
524  // or smaller than the record id
525  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)) or (recordSize < sizeof(FwPrmIdType))) {
526  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE, static_cast<I32>(recordNumTotal),
527  static_cast<I32>(recordSize));
528  return PrmLoadStatus::ERROR;
529  }
530 
531  // read the parameter ID
532  FwPrmIdType parameterId = 0;
533  readSize = static_cast<FwSizeType>(sizeof(FwPrmIdType));
534 
535  fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
536  if (fStat != Os::File::OP_OK) {
537  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID, static_cast<I32>(recordNumTotal), fStat);
538  return PrmLoadStatus::ERROR;
539  }
540  if (sizeof(parameterId) != static_cast<FwSizeType>(readSize)) {
541  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE, static_cast<I32>(recordNumTotal),
542  static_cast<I32>(readSize));
543  return PrmLoadStatus::ERROR;
544  }
545 
546  // set serialized size to read parameter ID
547  desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
548  // should never fail
549  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
550  // reset deserialization
551  buff.resetDeser();
552  // deserialize, since parameter ID is serialized in file
553  desStat = buff.deserializeTo(parameterId);
554  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
555 
556  // copy parameter value from file into a temporary buffer
557  Fw::ParamBuffer tmpParamBuffer; // temporary param buffer to read parameter value from file
558  readSize = recordSize - sizeof(parameterId);
559  desStat = tmpParamBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
560  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat)); // should never fail
561  fStat = paramFile.read(tmpParamBuffer.getBuffAddr(), readSize);
562 
563  if (fStat != Os::File::OP_OK) {
564  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE, static_cast<I32>(recordNumTotal),
565  fStat);
566  return PrmLoadStatus::ERROR;
567  }
568  if (static_cast<U32>(readSize) != recordSize - sizeof(parameterId)) {
569  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE, static_cast<I32>(recordNumTotal),
570  static_cast<I32>(readSize));
571  return PrmLoadStatus::ERROR;
572  }
573 
574  // Actually update or add parameter
575  PrmUpdateType updateStatus = updateAddPrmImpl(parameterId, tmpParamBuffer, dbType);
576  if (updateStatus == PARAM_ADDED) {
577  recordNumAdded++;
578  } else if (updateStatus == PARAM_UPDATED) {
579  recordNumUpdated++;
580  }
581 
582  if (updateStatus == NO_SLOTS) {
583  this->log_WARNING_HI_PrmDbFull(parameterId);
584  recordNumDropped++;
585  }
586  recordNumTotal++;
587  }
588 
589  // Dropped records mean the database does not reflect the file: report an error
590  if (recordNumDropped > 0) {
591  return PrmLoadStatus::ERROR;
592  }
593 
594  this->log_ACTIVITY_HI_PrmFileLoadComplete(dbString, recordNumTotal, recordNumAdded, recordNumUpdated);
595  return PrmLoadStatus::SUCCESS;
596 }
597 
598 PrmDbImpl::PrmUpdateType PrmDbImpl::updateAddPrmImpl(FwPrmIdType id, Fw::ParamBuffer& val, PrmDbType prmDbType) {
599  auto* db = getDbPtr(prmDbType);
600 
601  PrmUpdateType updateStatus = NO_SLOTS;
602 
603  this->lock();
604 
605  auto prevSize = db->getSize();
606  switch (db->insert(id, val)) {
608  updateStatus = NO_SLOTS;
609  break;
611  if (prevSize < db->getSize()) {
612  updateStatus = PARAM_ADDED;
613  } else {
614  FW_ASSERT(prevSize == db->getSize(), static_cast<FwAssertArgType>(prevSize),
615  static_cast<FwAssertArgType>(db->getSize()));
616  updateStatus = PARAM_UPDATED;
617  }
618  break;
619  default:
620  FW_ASSERT(false);
621  }
622 
623  this->unLock();
624  return updateStatus;
625 }
626 
630 
631 void PrmDbImpl::clearDb(PrmDbType prmDbType) {
632  getDbPtr(prmDbType)->clear();
633 }
634 
635 void PrmDbImpl::dbCopy(PrmDbType dest, PrmDbType src) {
636  *getDbPtr(dest) = *getDbPtr(src);
637  this->log_ACTIVITY_HI_PrmDbCopyAllComplete(getDbString(src), getDbString(dest));
638 }
639 
640 PrmDbImpl::PrmDbStore* PrmDbImpl::getDbPtr(PrmDbType dbType) {
641  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
642  if (dbType == PrmDbType::DB_ACTIVE) {
643  return m_activeDb;
644  }
645  return m_stagingDb;
646 }
647 
648 Fw::String PrmDbImpl::getDbString(PrmDbType dbType) {
649  FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
650  if (dbType == PrmDbType::DB_ACTIVE) {
651  return Fw::String("ACTIVE");
652  }
653  return Fw::String("STAGING");
654 }
655 
656 } // namespace Svc
void update(const void *const data, const FwSizeType len)
Definition: HashImpl.cpp:34
Serialization/Deserialization operation was successful.
Parameter already in database, updated parameter.
Definition: PrmDbImpl.hpp:83
void configure(const char *allowedDirectory)
Configure the allowed sandbox directory.
State of parameter DB file load operations.
FwIdType FwOpcodeType
The type of a command opcode.
Representing success.
void pingOut_out(FwIndexType portNum, U32 key) const
Invoke output port pingOut.
PlatformSizeType FwSizeType
void log_WARNING_LO_PrmDbFileLoadInvalidAction(const Svc::PrmDb_PrmDbFileLoadState &currentState, const Svc::PrmDb_PrmLoadAction &attemptedAction) const
Operation failed.
Definition: Os.hpp:28
void log_ACTIVITY_HI_PrmIdUpdated(FwPrmIdType Id) const
void readParamFile()
PrmDb file read function.
Definition: PrmDbImpl.cpp:59
StringTemplate< FW_FIXED_LENGTH_STRING_SIZE > String
Definition: String.hpp:14
FwIdType FwPrmIdType
The type of a parameter identifier.
void log_WARNING_HI_PrmFileReadError(const Svc::PrmDb_PrmReadError &stage, I32 record, I32 error) const
void log_ACTIVITY_HI_PrmFileSaveComplete(U32 records) const
void log_WARNING_HI_PrmFileWriteError(const Svc::PrmDb_PrmWriteError &stage, I32 record, I32 error) const
A wrapper around Os::File that restricts file access to an allowed directory.
virtual const CHAR * toChar() const =0
Convert to a C-style char*.
Overwrite file when it exists and creation was requested.
Definition: File.hpp:60
Open file for writing.
Definition: File.hpp:35
PrmDbImpl(const char *name)
PrmDb constructor.
Definition: PrmDbImpl.cpp:39
PrmDb_PrmDbType PrmDbType
Definition: PrmDbImpl.hpp:29
Parameter added to database.
Definition: PrmDbImpl.hpp:82
void log_ACTIVITY_HI_PrmFileLoadComplete(const Fw::StringBase &databaseString, U32 recordsTotal, U32 recordsAdded, U32 recordsUpdated) const
SerializeStatus
forward declaration for string
virtual void lock()
Lock the guarded mutex.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:50
void log_ACTIVITY_HI_PrmDbCommitComplete() const
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
void clear() override
Clear the map.
Definition: ArrayMap.hpp:73
virtual void unLock()
Unlock the guarded mutex.
void log_ACTIVITY_HI_PrmIdAdded(FwPrmIdType Id) const
A generic interface for creating and comparing hash values.
Definition: Hash.hpp:24
void log_ACTIVITY_HI_PrmDbCopyAllComplete(const Fw::StringBase &databaseStringSrc, const Fw::StringBase &databaseStringDest) const
const char * toChar() const
Convert to a C-style char*.
void configure(const char *file)
PrmDb configure method.
Definition: PrmDbImpl.cpp:49
Representing failure.
Command successfully executed.
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:54
void log_WARNING_HI_PrmDbFull(FwPrmIdType Id) const
SerializeStatus setBuffLen(Serializable::SizeType length) override
Set buffer length manually.
Auto-generated base for PrmDb component.
void configureLoadSandbox(const char *directory)
PrmDb load sandbox configure method.
Definition: PrmDbImpl.cpp:54
Command had execution error.
void log_WARNING_LO_PrmIdNotFound(FwPrmIdType Id)
Operation was successful.
Definition: File.hpp:42
Success find(const K &key, V &value) const override
Definition: ArrayMap.hpp:81
PlatformIndexType FwIndexType
Open file for reading.
Definition: File.hpp:33
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.
Implementation of malloc based allocator.
No slots available to add new parameter.
Definition: PrmDbImpl.hpp:81
void finalize(HashBuffer &buffer) const
Definition: HashImpl.cpp:40
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:47
#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