F´ Flight Software - C/C++ Documentation  NASA-v1.6.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 <cstdio>
15 
16 namespace Svc {
17 
18 
19  typedef PrmDb_PrmWriteError PrmWriteError;
20  typedef PrmDb_PrmReadError PrmReadError;
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, const char* file) : PrmDbComponentBase(name) {
45  this->clearDb();
46  this->m_fileName = file;
47  }
48 
49  void PrmDbImpl::init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance) {
50  PrmDbComponentBase::init(queueDepth,instance);
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
65  Fw::ParamValid stat = Fw::ParamValid::INVALID;
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) {
79  this->log_WARNING_LO_PrmIdNotFound(id);
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) {
118  this->log_ACTIVITY_HI_PrmIdUpdated(id);
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 
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) {
134  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::OPEN,0,stat);
135  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
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  NATIVE_INT_TYPE writeSize = sizeof(delim);
150  stat = paramFile.write(&delim,writeSize,true);
151  if (stat != Os::File::OP_OK) {
152  this->unLock();
153  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER,numRecords,stat);
154  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
155  return;
156  }
157  if (writeSize != sizeof(delim)) {
158  this->unLock();
159  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER_SIZE,numRecords,writeSize);
160  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
161  return;
162  }
163  // serialize record size = id field + data
164  U32 recordSize = sizeof(FwPrmIdType) + this->m_db[entry].val.getBuffLength();
165 
166  // reset buffer
167  buff.resetSer();
168  Fw::SerializeStatus serStat = buff.serialize(recordSize);
169  // should always work
170  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
171 
172  // write record size
173  writeSize = buff.getBuffLength();
174  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
175  if (stat != Os::File::OP_OK) {
176  this->unLock();
177  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE,numRecords,stat);
178  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
179  return;
180  }
181  if (writeSize != sizeof(writeSize)) {
182  this->unLock();
183  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE_SIZE,numRecords,writeSize);
184  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
185  return;
186  }
187 
188  // reset buffer
189  buff.resetSer();
190 
191  // serialize parameter id
192 
193  serStat = buff.serialize(this->m_db[entry].id);
194  // should always work
195  FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat,static_cast<NATIVE_INT_TYPE>(serStat));
196 
197  // write parameter ID
198  writeSize = buff.getBuffLength();
199  stat = paramFile.write(buff.getBuffAddr(),writeSize,true);
200  if (stat != Os::File::OP_OK) {
201  this->unLock();
202  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID,numRecords,stat);
203  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
204  return;
205  }
206  if (writeSize != static_cast<NATIVE_INT_TYPE>(buff.getBuffLength())) {
207  this->unLock();
208  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID_SIZE,numRecords,writeSize);
209  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
210  return;
211  }
212 
213  // write serialized parameter value
214 
215  writeSize = this->m_db[entry].val.getBuffLength();
216  stat = paramFile.write(this->m_db[entry].val.getBuffAddr(),writeSize,true);
217  if (stat != Os::File::OP_OK) {
218  this->unLock();
219  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE,numRecords,stat);
220  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
221  return;
222  }
223  if (writeSize != static_cast<NATIVE_INT_TYPE>(this->m_db[entry].val.getBuffLength())) {
224  this->unLock();
225  this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE_SIZE,numRecords,writeSize);
226  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::EXECUTION_ERROR);
227  return;
228  }
229  numRecords++;
230  } // end if record in use
231  } // end for each record
232 
233  this->unLock();
234  this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
235  this->cmdResponse_out(opCode,cmdSeq,Fw::CmdResponse::OK);
236 
237  }
238 
240  }
241 
243  // load file. FIXME: Put more robust file checking, such as a CRC.
244  Os::File paramFile;
245 
246  Os::File::Status stat = paramFile.open(this->m_fileName.toChar(),Os::File::OPEN_READ);
247  if (stat != Os::File::OP_OK) {
248  this->log_WARNING_HI_PrmFileReadError(PrmReadError::OPEN,0,stat);
249  return;
250  }
251 
252  WorkingBuffer buff;
253 
254  U32 recordNum = 0;
255 
256  this->clearDb();
257 
258  for (NATIVE_INT_TYPE entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
259 
260  U8 delimiter;
261  NATIVE_INT_TYPE readSize = sizeof(delimiter);
262 
263  // read delimiter
264  Os::File::Status fStat = paramFile.read(&delimiter,readSize,true);
265 
266  // check for end of file (read size 0)
267  if (0 == readSize) {
268  break;
269  }
270 
271  if (fStat != Os::File::OP_OK) {
272  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER,recordNum,fStat);
273  return;
274  }
275 
276  if (sizeof(delimiter) != readSize) {
277  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE,recordNum,readSize);
278  return;
279  }
280 
281  if (PRMDB_ENTRY_DELIMITER != delimiter) {
282  this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE,recordNum,delimiter);
283  return;
284  }
285 
286  U32 recordSize = 0;
287  // read record size
288  readSize = sizeof(recordSize);
289 
290  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
291  if (fStat != Os::File::OP_OK) {
292  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE,recordNum,fStat);
293  return;
294  }
295  if (sizeof(recordSize) != readSize) {
296  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE,recordNum,readSize);
297  return;
298  }
299  // set serialized size to read size
300  Fw::SerializeStatus desStat = buff.setBuffLen(readSize);
301  // should never fail
302  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
303  // reset deserialization
304  buff.resetDeser();
305  // deserialize, since record size is serialized in file
306  FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(recordSize));
307 
308  // sanity check value. It can't be larger than the maximum parameter buffer size + id
309  // or smaller than the record id
310  if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(U32)) or (recordSize < sizeof(U32))) {
311  this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE,recordNum,recordSize);
312  return;
313  }
314 
315  // read the parameter ID
316  FwPrmIdType parameterId = 0;
317  readSize = sizeof(FwPrmIdType);
318 
319  fStat = paramFile.read(buff.getBuffAddr(),readSize,true);
320  if (fStat != Os::File::OP_OK) {
321  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID,recordNum,fStat);
322  return;
323  }
324  if (sizeof(parameterId) != static_cast<NATIVE_INT_TYPE>(readSize)) {
325  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE,recordNum,readSize);
326  return;
327  }
328 
329  // set serialized size to read parameter ID
330  desStat = buff.setBuffLen(readSize);
331  // should never fail
332  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
333  // reset deserialization
334  buff.resetDeser();
335  // deserialize, since parameter ID is serialized in file
336  FW_ASSERT(Fw::FW_SERIALIZE_OK == buff.deserialize(parameterId));
337 
338  // copy parameter
339  this->m_db[entry].used = true;
340  this->m_db[entry].id = parameterId;
341  readSize = recordSize-sizeof(parameterId);
342 
343  fStat = paramFile.read(this->m_db[entry].val.getBuffAddr(),readSize);
344 
345  if (fStat != Os::File::OP_OK) {
346  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE,recordNum,fStat);
347  return;
348  }
349  if (static_cast<U32>(readSize) != recordSize-sizeof(parameterId)) {
350  this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE,recordNum,readSize);
351  return;
352  }
353 
354  // set serialized size to read size
355  desStat = this->m_db[entry].val.setBuffLen(readSize);
356  // should never fail
357  FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat,static_cast<NATIVE_INT_TYPE>(desStat));
358  recordNum++;
359 
360  }
361 
362  this->log_ACTIVITY_HI_PrmFileLoadComplete(recordNum);
363  }
364 
365  void PrmDbImpl::pingIn_handler(NATIVE_INT_TYPE portNum, U32 key) {
366  // respond to ping
367  this->pingOut_out(0,key);
368  }
369 
370 
371 
372 }
Fw::SerializeBufferBase
Definition: Serializable.hpp:43
Fw::SerializeStatus
SerializeStatus
forward declaration for string
Definition: Serializable.hpp:14
Svc::PrmReadError
PrmDb_PrmReadError PrmReadError
Definition: PrmDbImpl.cpp:20
FW_NUM_ARRAY_ELEMENTS
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Definition: BasicTypes.hpp:101
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
Svc::PrmDbImpl::readParamFile
void readParamFile()
PrmDb file read function.
Definition: PrmDbImpl.cpp:242
U8
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.hpp:76
Fw::String::toChar
const char * toChar() const
gets char buffer
Definition: String.cpp:48
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:239
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:267
FwOpcodeType
#define FwOpcodeType
Type representation for a command opcode.
Definition: FpConfig.hpp:58
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:8
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:591
Fw::ParamBuffer
Definition: PrmBuffer.hpp:22
Svc::PrmDbImpl::PrmDbImpl
PrmDbImpl(const char *name, const char *file)
PrmDb constructor.
Definition: PrmDbImpl.cpp:44
File.hpp
OK
@ OK
Definition: StandardTypes.hpp:14
Svc
Definition: ActiveRateGroupImplCfg.hpp:18
Svc::PrmWriteError
PrmDb_PrmWriteError PrmWriteError
Definition: PrmDbImpl.cpp:19
Os::File::Status
Status
Definition: File.hpp:24
FwPrmIdType
#define FwPrmIdType
Type representation for a parameter id.
Definition: FpConfig.hpp:70
PrmDbImpl.hpp
Component for managing parameters.
Os::File::OP_OK
@ OP_OK
Operation was successful.
Definition: File.hpp:25
Fw::ParamBuffer::getBuffAddr
U8 * getBuffAddr()
gets buffer address for data filling
Definition: PrmBuffer.cpp:36
Svc::PrmDbImpl::init
void init(NATIVE_INT_TYPE queueDepth, NATIVE_INT_TYPE instance)
PrmDb initialization function.
Definition: PrmDbImpl.cpp:49
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