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