F´ Flight Software - C/C++ Documentation  NASA-v2.1.0
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 <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