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