F´ Flight Software - C/C++ Documentation  devel
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 
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::init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance) {
54  PrmDbComponentBase::init(queueDepth,instance);
55  }
56 
57  void PrmDbImpl::clearDb() {
58  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
59  this->m_db[entry].used = false;
60  this->m_db[entry].id = 0;
61  }
62  }
63 
64  // If ports are no longer guarded, these accesses need to be protected from each other
65  // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
66 
67  Fw::ParamValid PrmDbImpl::getPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
68  // search for entry
70 
71  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
72  if (this->m_db[entry].used) {
73  if (this->m_db[entry].id == id) {
74  val = this->m_db[entry].val;
75  stat = Fw::ParamValid::VALID;
76  break;
77  }
78  }
79  }
80 
81  // if unable to find parameter, send error message
82  if (Fw::ParamValid::INVALID == stat.e) {
84  }
85 
86  return stat;
87  }
88 
89  void PrmDbImpl::setPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
90 
91  this->lock();
92 
93  // search for existing entry
94 
95  bool existingEntry = false;
96  bool noSlots = true;
97 
98  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
99  if ((this->m_db[entry].used) && (id == this->m_db[entry].id)) {
100  this->m_db[entry].val = val;
101  existingEntry = true;
102  break;
103  }
104  }
105 
106  // if there is no existing entry, add one
107  if (!existingEntry) {
108  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
109  if (!(this->m_db[entry].used)) {
110  this->m_db[entry].val = val;
111  this->m_db[entry].id = id;
112  this->m_db[entry].used = true;
113  noSlots = false;
114  break;
115  }
116  }
117  }
118 
119  this->unLock();
120 
121  if (existingEntry) {
123  } else if (noSlots) {
124  this->log_FATAL_PrmDbFull(id);
125  } else {
126  this->log_ACTIVITY_HI_PrmIdAdded(id);
127  }
128 
129  }
130 
131  void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
132  FW_ASSERT(this->m_fileName.length() > 0);
133  Os::File paramFile;
134  WorkingBuffer buff;
135 
136  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_WRITE);
137  if (stat != Os::File::OP_OK) {
140  return;
141  }
142 
143  this->lock();
144 
145  // Traverse the parameter list, saving each entry
146 
147  U32 numRecords = 0;
148 
149  for (NATIVE_UINT_TYPE entry = 0; entry < FW_NUM_ARRAY_ELEMENTS(this->m_db); entry++) {
150  if (this->m_db[entry].used) {
151  // write delimiter
152  static const U8 delim = PRMDB_ENTRY_DELIMITER;
153  NATIVE_INT_TYPE writeSize = sizeof(delim);
154  stat = paramFile.write(&delim,writeSize,true);
155  if (stat != Os::File::OP_OK) {
156  this->unLock();
159  return;
160  }
161  if (writeSize != sizeof(delim)) {
162  this->unLock();
165  return;
166  }
167  // serialize record size = id field + data
168  U32 recordSize = sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength();
169 
170  // reset buffer
171  buff.resetSer();
172  Fw::SerializeStatus serStat = buff.serialize(recordSize);
173  // should always work
174  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
175 
176  // write record size
177  writeSize = buff.getBuffLength();
178  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
179  if (stat != Os::File::OP_OK) {
180  this->unLock();
183  return;
184  }
185  if (writeSize != sizeof(writeSize)) {
186  this->unLock();
189  return;
190  }
191 
192  // reset buffer
193  buff.resetSer();
194 
195  // serialize parameter id
196 
197  serStat = buff.serialize(this->m_db[entry].id);
198  // should always work
199  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
200 
201  // write parameter ID
202  writeSize = buff.getBuffLength();
203  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
204  if (stat != Os::File::OP_OK) {
205  this->unLock();
208  return;
209  }
210  if (writeSize != static_cast<NATIVE_INT_TYPE>(buff.getBuffLength())) {
211  this->unLock();
214  return;
215  }
216 
217  // write serialized parameter value
218 
219  writeSize = this->m_db[entry].val.getBuffLength();
220  stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,true);
221  if (stat != Os::File::OP_OK) {
222  this->unLock();
225  return;
226  }
227  if (writeSize != static_cast<NATIVE_INT_TYPE>(this->m_db[entry].val.getBuffLength())) {
228  this->unLock();
231  return;
232  }
233  numRecords++;
234  } // end if record in use
235  } // end for each record
236 
237  this->unLock();
238  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
239  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
240 
241  }
242 
244  }
245 
247  FW_ASSERT(this->m_fileName.length() > 0);
248  // load file. FIXME: Put more robust file checking, such as a CRC.
249  Os::File paramFile;
250 
251  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_READ);
252  if (stat != Os::File::OP_OK) {
254  return;
255  }
256 
257  WorkingBuffer buff;
258 
259  U32 recordNum = 0;
260 
261  this->clearDb();
262 
263  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
264 
265  U8 delimiter;
266  NATIVE_INT_TYPE readSize = sizeof(delimiter);
267 
268  // read delimiter
269  Os::File::Status fStat = paramFile.read(&delimiter,readSize,true);
270 
271  // check for end of file (read size 0)
272  if (0 == readSize) {
273  break;
274  }
275 
276  if (fStat != Os::File::OP_OK) {
278  return;
279  }
280 
281  if (sizeof(delimiter) != readSize) {
283  return;
284  }
285 
286  if (PRMDB_ENTRY_DELIMITER != delimiter) {
288  return;
289  }
290 
291  U32 recordSize = 0;
292  // read record size
293  readSize = sizeof(recordSize);
294 
295  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
296  if (fStat != Os::File::OP_OK) {
298  return;
299  }
300  if (sizeof(recordSize) != readSize) {
302  return;
303  }
304  // set serialized size to read size
305  Fw::SerializeStatus desStat = buff.setBuffLen(readSize);
306  // should never fail
307  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
308  // reset deserialization
309  buff.resetDeser();
310  // deserialize, since record size is serialized in file
311  desStat = buff.deserialize(recordSize);
312  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
313 
314  // sanity check value. It can't be larger than the maximum parameter buffer size + id
315  // or smaller than the record id
316  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
318  return;
319  }
320 
321  // read the parameter ID
322  FwPrmIdType parameterId = 0;
323  readSize = sizeof(FwPrmIdType);
324 
325  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
326  if (fStat != Os::File::OP_OK) {
328  return;
329  }
330  if (sizeof(parameterId) != static_cast<NATIVE_INT_TYPE>(readSize)) {
332  return;
333  }
334 
335  // set serialized size to read parameter ID
336  desStat = buff.setBuffLen(readSize);
337  // should never fail
338  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
339  // reset deserialization
340  buff.resetDeser();
341  // deserialize, since parameter ID is serialized in file
342  desStat = buff.deserialize(parameterId);
343  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
344 
345  // copy parameter
346  this->m_db[entry].used = true;
347  this->m_db[entry].id = parameterId;
348  readSize = recordSize-sizeof(parameterId);
349 
350  fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
351 
352  if (fStat != Os::File::OP_OK) {
354  return;
355  }
356  if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
358  return;
359  }
360 
361  // set serialized size to read size
362  desStat = this->m_db[entry].val.setBuffLen(readSize);
363  // should never fail
364  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
365  recordNum++;
366 
367  }
368 
369  this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
370  }
371 
372  void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
373  // respond to ping
374  this->pingOut_out(0,key);
375  }
376 
377 
378 
379 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition: BasicTypes.h:66
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
#define FW_PARAM_BUFFER_MAX_SIZE
Definition: FpConfig.h:274
U32 FwOpcodeType
Definition: FpConfig.h:56
U32 FwPrmIdType
Definition: FpConfig.h:65
Component for managing parameters.
@ EXECUTION_ERROR
Command had execution error.
@ OK
Command successfully executed.
void init()
Object initializer.
Definition: ObjBase.cpp:27
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 getBuffLength() const
returns current buffer size
NATIVE_UINT_TYPE length() const
Get length of string.
Definition: StringType.cpp:123
const char * toChar() const
gets char buffer
Definition: String.cpp:48
Status
Definition: File.hpp:23
@ OP_OK
Operation was successful.
Definition: File.hpp:24
Status write(const void *buffer, NATIVE_INT_TYPE &size, bool waitForDone=true)
write size; will return amount written or errno
Definition: File.cpp:32
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:16
@ OPEN_READ
Open file for reading.
Definition: File.hpp:15
Status open(const char *fileName, Mode mode)
open file. Writing creates file if it doesn't exist
Definition: File.cpp:12
Status read(void *buffer, NATIVE_INT_TYPE &size, bool waitForFull=true)
waitForFull = true to wait for all bytes to be read
Definition: File.cpp:28
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(NATIVE_INT_TYPE 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:246
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:243
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