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