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