F´ Flight Software - C/C++ Documentation  NASA-v2.1.0
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 <stdio.h>
15 
16 namespace Svc {
17 
18  // anonymous namespace for buffer declaration
19  namespace {
20  class WorkingBuffer : public Fw::SerializeBufferBase {
21  public:
22 
23  NATIVE_UINT_TYPE getBuffCapacity(void) const {
24  return sizeof(m_buff);
25  }
26 
27  U8* getBuffAddr(void) {
28  return m_buff;
29  }
30 
31  const U8* getBuffAddr(void) const {
32  return m_buff;
33  }
34 
35  private:
36  // Set to max of parameter buffer + id
37  U8 m_buff[FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)];
38  };
39  }
40 
41  PrmDbImpl::PrmDbImpl(const char* name, const char* file) : PrmDbComponentBase(name) {
42  this->clearDb();
43  this->m_fileName = file;
44  }
45 
46  void PrmDbImpl::init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance) {
47  PrmDbComponentBase::init(queueDepth,instance);
48  }
49 
50  void PrmDbImpl::clearDb(void) {
51  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
52  this->m_db[entry].used = false;
53  this->m_db[entry].id = 0;
54  }
55  }
56 
57  // If ports are no longer guarded, these accesses need to be protected from each other
58  // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
59 
60  Fw::ParamValid PrmDbImpl::getPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
61  // search for entry
62  Fw::ParamValid stat = Fw::PARAM_INVALID;
63 
64  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
65  if (this->m_db[entry].used) {
66  if (this->m_db[entry].id == id) {
67  val = this->m_db[entry].val;
68  stat = Fw::PARAM_VALID;
69  break;
70  }
71  }
72  }
73 
74  // if unable to find parameter, send error message
75  if (Fw::PARAM_INVALID == stat) {
76  this->log_WARNING_LO_PrmIdNotFound(id);
77  }
78 
79  return stat;
80  }
81 
82  void PrmDbImpl::setPrm_handler(NATIVE_INT_TYPE portNum, FwPrmIdType id, Fw::ParamBuffer &val) {
83 
84  this->lock();
85 
86  // search for existing entry
87 
88  bool existingEntry = false;
89  bool noSlots = true;
90 
91  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
92  if ((this->m_db[entry].used) && (id == this->m_db[entry].id)) {
93  this->m_db[entry].val = val;
94  existingEntry = true;
95  break;
96  }
97  }
98 
99  // if there is no existing entry, add one
100  if (!existingEntry) {
101  for (I32 entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
102  if (!(this->m_db[entry].used)) {
103  this->m_db[entry].val = val;
104  this->m_db[entry].id = id;
105  this->m_db[entry].used = true;
106  noSlots = false;
107  break;
108  }
109  }
110  }
111 
112  this->unLock();
113 
114  if (existingEntry) {
115  this->log_ACTIVITY_HI_PrmIdUpdated(id);
116  } else if (noSlots) {
117  this->log_FATAL_PrmDbFull(id);
118  } else {
119  this->log_ACTIVITY_HI_PrmIdAdded(id);
120  }
121 
122  }
123 
124  void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
125 
126  Os::File paramFile;
127  WorkingBuffer buff;
128 
129  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_WRITE);
130  if (stat != Os::File::OP_OK) {
131  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_OPEN,0,stat);
132  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
133  return;
134  }
135 
136  this->lock();
137 
138  // Traverse the parameter list, saving each entry
139 
140  U32 numRecords = 0;
141 
142  for (NATIVE_UINT_TYPE entry = 0; entry < FW_NUM_ARRAY_ELEMENTS(this->m_db); entry++) {
143  if (this->m_db[entry].used) {
144  // write delimiter
145  static const U8 delim = PRMDB_ENTRY_DELIMITER;
146  NATIVE_INT_TYPE writeSize = sizeof(delim);
147  stat = paramFile.write(&delim,writeSize,true);
148  if (stat != Os::File::OP_OK) {
149  this->unLock();
150  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_DELIMITER,numRecords,stat);
151  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
152  return;
153  }
154  if (writeSize != sizeof(delim)) {
155  this->unLock();
156  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_DELIMITER_SIZE,numRecords,writeSize);
157  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
158  return;
159  }
160  // serialize record size = id field + data
161  U32 recordSize = sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength();
162 
163  // reset buffer
164  buff.resetSer();
165  Fw::SerializeStatus serStat = buff.serialize(recordSize);
166  // should always work
167  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,(NATIVE_INT_TYPE)serStat);
168 
169  // write record size
170  writeSize = buff.getBuffLength();
171  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
172  if (stat != Os::File::OP_OK) {
173  this->unLock();
174  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_RECORD_SIZE,numRecords,stat);
175  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
176  return;
177  }
178  if (writeSize != sizeof(writeSize)) {
179  this->unLock();
180  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_RECORD_SIZE_SIZE,numRecords,writeSize);
181  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
182  return;
183  }
184 
185  // reset buffer
186  buff.resetSer();
187 
188  // serialize parameter id
189 
190  serStat = buff.serialize(this->m_db[entry].id);
191  // should always work
192  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,(NATIVE_INT_TYPE)serStat);
193 
194  // write parameter ID
195  writeSize = buff.getBuffLength();
196  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
197  if (stat != Os::File::OP_OK) {
198  this->unLock();
199  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_PARAMETER_ID,numRecords,stat);
200  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
201  return;
202  }
203  if (writeSize != (NATIVE_INT_TYPE)buff.getBuffLength()) {
204  this->unLock();
205  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_PARAMETER_ID_SIZE,numRecords,writeSize);
206  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
207  return;
208  }
209 
210  // write serialized parameter value
211 
212  writeSize = this->m_db[entry].val.getBuffLength();
213  stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,true);
214  if (stat != Os::File::OP_OK) {
215  this->unLock();
216  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_PARAMETER_VALUE,numRecords,stat);
217  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
218  return;
219  }
220  if (writeSize != (NATIVE_INT_TYPE)this->m_db[entry].val.getBuffLength()) {
221  this->unLock();
222  this->log_WARNING_HI_PrmFileWriteError(PRM_WRITE_PARAMETER_VALUE_SIZE,numRecords,writeSize);
223  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_EXECUTION_ERROR);
224  return;
225  }
226  numRecords++;
227  } // end if record in use
228  } // end for each record
229 
230  this->unLock();
231  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
232  this->cmdResponse_out(opCode,cmdSeq,Fw::COMMAND_OK);
233 
234  }
235 
237  }
238 
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) {
245  this->log_WARNING_HI_PrmFileReadError(PRM_READ_OPEN,0,stat);
246  return;
247  }
248 
249  WorkingBuffer buff;
250 
251  U32 recordNum = 0;
252 
253  this->clearDb();
254 
255  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
256 
257  U8 delimiter;
258  NATIVE_INT_TYPE readSize = sizeof(delimiter);
259 
260  // read delimiter
261  Os::File::Status fStat = paramFile.read(&delimiter,readSize,true);
262 
263  // check for end of file (read size 0)
264  if (0 == readSize) {
265  break;
266  }
267 
268  if (fStat != Os::File::OP_OK) {
269  this->log_WARNING_HI_PrmFileReadError(PRM_READ_DELIMITER,recordNum,fStat);
270  return;
271  }
272 
273  if (sizeof(delimiter) != readSize) {
274  this->log_WARNING_HI_PrmFileReadError(PRM_READ_DELIMITER_SIZE,recordNum,readSize);
275  return;
276  }
277 
278  if (PRMDB_ENTRY_DELIMITER != delimiter) {
279  this->log_WARNING_HI_PrmFileReadError(PRM_READ_DELIMITER_VALUE,recordNum,delimiter);
280  return;
281  }
282 
283  U32 recordSize = 0;
284  // read record size
285  readSize = sizeof(recordSize);
286 
287  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
288  if (fStat != Os::File::OP_OK) {
289  this->log_WARNING_HI_PrmFileReadError(PRM_READ_RECORD_SIZE,recordNum,fStat);
290  return;
291  }
292  if (sizeof(recordSize) != readSize) {
293  this->log_WARNING_HI_PrmFileReadError(PRM_READ_RECORD_SIZE_SIZE,recordNum,readSize);
294  return;
295  }
296  // set serialized size to read size
297  Fw::SerializeStatus desStat = buff.setBuffLen(readSize);
298  // should never fail
299  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,(NATIVE_INT_TYPE)desStat);
300  // reset deserialization
301  buff.resetDeser();
302  // deserialize, since record size is serialized in file
303  FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(recordSize));
304 
305  // sanity check value. It can't be larger than the maximum parameter buffer size + id
306  // or smaller than the record id
307  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
308  this->log_WARNING_HI_PrmFileReadError(PRM_READ_RECORD_SIZE_VALUE,recordNum,recordSize);
309  return;
310  }
311 
312  // read the parameter ID
313  FwPrmIdType parameterId = 0;
314  readSize = sizeof(FwPrmIdType);
315 
316  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
317  if (fStat != Os::File::OP_OK) {
318  this->log_WARNING_HI_PrmFileReadError(PRM_READ_PARAMETER_ID,recordNum,fStat);
319  return;
320  }
321  if (sizeof(parameterId) != static_cast<NATIVE_INT_TYPE>(readSize)) {
322  this->log_WARNING_HI_PrmFileReadError(PRM_READ_PARAMETER_ID_SIZE,recordNum,readSize);
323  return;
324  }
325 
326  // set serialized size to read parameter ID
327  desStat = buff.setBuffLen(readSize);
328  // should never fail
329  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,(NATIVE_INT_TYPE)desStat);
330  // reset deserialization
331  buff.resetDeser();
332  // deserialize, since parameter ID is serialized in file
333  FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(parameterId));
334 
335  // copy parameter
336  this->m_db[entry].used = true;
337  this->m_db[entry].id = parameterId;
338  readSize = recordSize-sizeof(parameterId);
339 
340  fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
341 
342  if (fStat != Os::File::OP_OK) {
343  this->log_WARNING_HI_PrmFileReadError(PRM_READ_PARAMETER_VALUE,recordNum,fStat);
344  return;
345  }
346  if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
347  this->log_WARNING_HI_PrmFileReadError(PRM_READ_PARAMETER_VALUE_SIZE,recordNum,readSize);
348  return;
349  }
350 
351  // set serialized size to read size
352  desStat = this->m_db[entry].val.setBuffLen(readSize);
353  // should never fail
354  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,(NATIVE_INT_TYPE)desStat);
355  recordNum++;
356 
357  }
358 
359  this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
360  }
361 
362  void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
363  // respond to ping
364  this->pingOut_out(0,key);
365  }
366 
367 
368 
369 }
Fw::SerializeBufferBase
Definition: Serializable.hpp:43
Fw::SerializeStatus
SerializeStatus
forward declaration for string
Definition: Serializable.hpp:14
FW_NUM_ARRAY_ELEMENTS
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition: BasicTypes.hpp:158
Os::File::read
Status read(void *buffer, NATIVE_INT_TYPE &size, bool waitForFull=true)
waitForFull = true to wait for all bytes to be read
Definition: File.cpp:29
U8
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.hpp:76
Svc::PrmDbImpl::readParamFile
void readParamFile(void)
PrmDb file read function.
Definition: PrmDbImpl.cpp:239
Fw::ParamBuffer::getBuffAddr
U8 * getBuffAddr(void)
gets buffer address for data filling
Definition: PrmBuffer.cpp:36
Fw::String::toChar
const char * toChar() const
gets char buffer
Definition: String.cpp:40
Assert.hpp
Fw::FW_SERIALIZE_OK
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
Definition: Serializable.hpp:15
Svc::PrmDbImpl::~PrmDbImpl
virtual ~PrmDbImpl()
PrmDb destructor.
Definition: PrmDbImpl.cpp:236
Os::File::write
Status write(const void *buffer, NATIVE_INT_TYPE &size, bool waitForDone=true)
write size; will return amount written or errno
Definition: File.cpp:33
FW_PARAM_BUFFER_MAX_SIZE
#define FW_PARAM_BUFFER_MAX_SIZE
Definition: FpConfig.hpp:270
FwOpcodeType
#define FwOpcodeType
Type representation for a command opcode.
Definition: FpConfig.hpp:62
Os::File::OPEN_WRITE
@ OPEN_WRITE
Open file for writing.
Definition: File.hpp:17
NATIVE_UINT_TYPE
unsigned int NATIVE_UINT_TYPE
native unsigned integer type declaration
Definition: BasicTypes.hpp:30
FW_ASSERT
#define FW_ASSERT(...)
Definition: Assert.hpp:9
Os::File::open
Status open(const char *fileName, Mode mode)
open file. Writing creates file if it doesn't exist
Definition: File.cpp:13
Fw::SerializeBufferBase::getBuffLength
NATIVE_UINT_TYPE getBuffLength() const
returns current buffer size
Definition: Serializable.cpp:587
Fw::ParamBuffer
Definition: PrmBuffer.hpp:22
Svc::PrmDbImpl::PrmDbImpl
PrmDbImpl(const char *name, const char *file)
PrmDb constructor.
Definition: PrmDbImpl.cpp:41
File.hpp
Svc
Definition: ActiveRateGroupImplCfg.hpp:18
Os::File::Status
Status
Definition: File.hpp:24
FwPrmIdType
#define FwPrmIdType
Type representation for a parameter id.
Definition: FpConfig.hpp:74
PrmDbImpl.hpp
Component for managing parameters.
Os::File::OP_OK
@ OP_OK
Operation was successful.
Definition: File.hpp:25
Svc::PrmDbImpl::init
void init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance)
PrmDb initialization function.
Definition: PrmDbImpl.cpp:46
NATIVE_INT_TYPE
int NATIVE_INT_TYPE
native integer type declaration
Definition: BasicTypes.hpp:29
Os::File::OPEN_READ
@ OPEN_READ
Open file for reading.
Definition: File.hpp:16
Os::File
Definition: File.hpp:11