GCC Code Coverage Report


Directory: Svc/PrmDb/
File: PrmDbImpl.cpp
Date: 2026-09-23 21:14:51
Exec Total Coverage
Lines: 336 361 93.1%
Functions: 18 19 94.7%
Branches: 337 379 88.9%

Line Branch Exec Source
1 /*
2 * PrmDbImpl.cpp
3 *
4 * Created on: March 9, 2015
5 * Author: Timothy Canham
6 */
7
8 #include <Fw/Types/Assert.hpp>
9 #include <Svc/PrmDb/PrmDbImpl.hpp>
10
11 #include <Os/File.hpp>
12 #include <Utils/Hash/Hash.hpp>
13
14 #include <cstdio>
15 #include <cstring>
16
17 static_assert(std::numeric_limits<FwSizeType>::max() >= PRMDB_NUM_DB_ENTRIES,
18 "PRMDB_NUM_DB_ENTRIES must fit within range of FwSizeType");
19
20 namespace Svc {
21
22 // anonymous namespace for buffer declaration
23 namespace {
24 class WorkingBuffer : public Fw::LinearBufferBase {
25 public:
26 47 WorkingBuffer() : Fw::LinearBufferBase(m_buff, sizeof(m_buff)) {}
27
28 private:
29 // Set to max of parameter buffer + id
30 U8 m_buff[FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)];
31 static_assert(sizeof(m_buff) >= sizeof(U32), "Size of parameter buffer storage must be >= sizeof(U32)");
32 };
33 } // namespace
34
35 //! ----------------------------------------------------------------------
36 //! Construction, initialization, and destruction
37 //! ----------------------------------------------------------------------
38
5/5
✓ Branch 10 taken 15 times.
✓ Branch 16 taken 15 times.
✓ Branch 22 taken 15 times.
✓ Branch 28 taken 15 times.
✓ Branch 34 taken 15 times.
15 PrmDbImpl::PrmDbImpl(const char* name) : PrmDbComponentBase(name), m_state(PrmDbFileLoadState::IDLE) {
39 15 this->m_activeDb = &this->m_dbStore1;
40 15 this->m_stagingDb = &this->m_dbStore2;
41
42
2/2
✓ Branch 5 taken 15 times.
✓ Branch 8 taken 15 times.
15 this->clearDb(PrmDbType::DB_ACTIVE);
43
2/2
✓ Branch 5 taken 15 times.
✓ Branch 8 taken 15 times.
15 this->clearDb(PrmDbType::DB_STAGING);
44 15 }
45
46 30 PrmDbImpl::~PrmDbImpl() {}
47
48 15 void PrmDbImpl::configure(const char* file) {
49 15 FW_ASSERT(file != nullptr);
50 15 this->m_fileName = file;
51 15 }
52
53 15 void PrmDbImpl::configureSandbox(const char* directory) {
54 15 FW_ASSERT(directory != nullptr);
55 15 this->m_sandboxDir = directory;
56 15 }
57
58 53 void PrmDbImpl::applySandbox(Os::SandboxedFile& file) const {
59 // Left unconfigured (fail-closed) when configureSandbox() was never called
60
2/2
✓ Branch 11 taken 50 times.
✓ Branch 12 taken 3 times.
53 if (this->m_sandboxDir.length() > 0) {
61 50 file.configure(this->m_sandboxDir.toChar());
62 }
63 53 }
64
65 24 void PrmDbImpl::readParamFile() {
66 // Assumed to run at initialization time
67 // State should be IDLE upon entry
68 24 FW_ASSERT(static_cast<FwAssertArgType>(m_state == PrmDbFileLoadState::IDLE));
69
70 // Clear databases
71
2/2
✓ Branch 5 taken 24 times.
✓ Branch 8 taken 24 times.
24 this->clearDb(PrmDbType::DB_ACTIVE);
72
2/2
✓ Branch 5 taken 24 times.
✓ Branch 8 taken 24 times.
24 this->clearDb(PrmDbType::DB_STAGING);
73
74 // Read parameter file to active database
75
2/2
✓ Branch 5 taken 24 times.
✓ Branch 11 taken 24 times.
24 (void)readParamFileImpl(this->m_fileName, PrmDbType::DB_ACTIVE);
76 24 }
77
78 //! ----------------------------------------------------------------------
79 //! Port & Command Handlers
80 //! ----------------------------------------------------------------------
81
82 // If ports are no longer guarded, these accesses need to be protected from each other
83 // If there are a lot of accesses, perhaps an interrupt lock could be used instead of guarded ports
84
85 31 Fw::ParamValid PrmDbImpl::getPrm_handler(FwIndexType portNum, FwPrmIdType id, Fw::ParamBuffer& val) {
86 // search for entry
87
1/1
✓ Branch 7 taken 31 times.
31 auto success = this->m_activeDb->find(id, val);
88
89
3/5
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
31 switch (success.e) {
90 3 case Fw::Success::FAILURE:
91 // if unable to find parameter, send error message
92
1/1
✓ Branch 5 taken 3 times.
3 this->log_WARNING_LO_PrmIdNotFound(id);
93
1/1
✓ Branch 1 taken 3 times.
3 return Fw::ParamValid::INVALID;
94 28 case Fw::Success::SUCCESS:
95
1/1
✓ Branch 1 taken 28 times.
28 return Fw::ParamValid::VALID;
96 ✗ default:
97 ✗ FW_ASSERT(false, success.e);
98 ✗ return Fw::ParamValid::INVALID;
99 }
100 31 }
101
102 59 void PrmDbImpl::setPrm_handler(FwIndexType portNum, FwPrmIdType id, Fw::ParamBuffer& val) {
103 // Reject parameter updates during non-idle file load states
104
2/2
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 57 times.
59 if (m_state != PrmDbFileLoadState::IDLE) {
105
2/2
✓ Branch 6 taken 2 times.
✓ Branch 13 taken 2 times.
2 this->log_WARNING_LO_PrmDbFileLoadInvalidAction(m_state, PrmDb_PrmLoadAction::SET_PARAMETER);
106 2 return;
107 }
108
109 // Update the parameter in the active database
110
2/2
✓ Branch 5 taken 57 times.
✓ Branch 8 taken 57 times.
57 PrmUpdateType update_status = updateAddPrmImpl(id, val, PrmDbType::DB_ACTIVE);
111
112 // Issue relevant EVR
113
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 49 times.
57 if (update_status == PARAM_UPDATED) {
114 8 this->log_ACTIVITY_HI_PrmIdUpdated(id);
115
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 48 times.
49 } else if (update_status == NO_SLOTS) {
116 1 this->log_WARNING_HI_PrmDbFull(id);
117 } else {
118 48 this->log_ACTIVITY_HI_PrmIdAdded(id);
119 }
120 }
121
122 ✗ void PrmDbImpl::pingIn_handler(FwIndexType portNum, U32 key) {
123 // respond to ping
124 ✗ this->pingOut_out(0, key);
125 ✗ }
126
127 25 void PrmDbImpl::PRM_SAVE_FILE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
128 // Reject PRM_SAVE_FILE command during non-idle file load states
129
2/2
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 23 times.
25 if (m_state != PrmDbFileLoadState::IDLE) {
130
2/2
✓ Branch 6 taken 2 times.
✓ Branch 13 taken 2 times.
2 this->log_WARNING_LO_PrmDbFileLoadInvalidAction(m_state, PrmDb_PrmLoadAction::SAVE_FILE_COMMAND);
131
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
132 2 return;
133 }
134
135 23 FW_ASSERT(this->m_fileName.length() > 0);
136
137
1/1
✓ Branch 2 taken 23 times.
23 Os::SandboxedFile paramFile;
138
1/1
✓ Branch 4 taken 23 times.
23 this->applySandbox(paramFile);
139
1/1
✓ Branch 2 taken 23 times.
23 WorkingBuffer buff;
140
141
1/1
✓ Branch 7 taken 23 times.
23 Os::File::Status stat = paramFile.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE, Os::File::OVERWRITE);
142
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23 if (stat != Os::File::OP_OK) {
143
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::OPEN, 0, stat);
144
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
145 2 return;
146 }
147
148 // write placeholder for the CRC
149
1/1
✓ Branch 2 taken 21 times.
21 Utils::Hash crc;
150 21 U32 crcInitial = 0xFFFFFFFF;
151
1/1
✓ Branch 2 taken 21 times.
21 buff.resetSer();
152
1/1
✓ Branch 2 taken 21 times.
21 Fw::SerializeStatus serStat = buff.serializeFrom(crcInitial);
153 21 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
154
1/1
✓ Branch 3 taken 21 times.
21 FwSizeType writeSize = static_cast<FwSizeType>(buff.getSize());
155
1/1
✓ Branch 3 taken 21 times.
21 stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
156
157
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (stat != Os::File::OP_OK) {
158
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::CRC_PLACE, 0, stat);
159
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
160 2 return;
161 }
162
163
1/1
✓ Branch 5 taken 19 times.
19 this->lock();
164
2/2
✓ Branch 5 taken 19 times.
✓ Branch 8 taken 19 times.
19 auto db = getDbPtr(PrmDbType::DB_ACTIVE);
165 19 FW_ASSERT(db != nullptr);
166
167 // Traverse the parameter list, saving each entry
168
169 19 U32 numRecords = 0;
170
171
6/6
✓ Branch 3 taken 19 times.
✓ Branch 7 taken 19 times.
✓ Branch 10 taken 26 times.
✓ Branch 14 taken 33 times.
✓ Branch 16 taken 26 times.
✓ Branch 17 taken 7 times.
33 for (const auto& entry : *db) {
172 // write delimiter
173 static const U8 delim = PRMDB_ENTRY_DELIMITER;
174 26 writeSize = static_cast<FwSizeType>(sizeof(delim));
175
1/1
✓ Branch 1 taken 26 times.
26 stat = paramFile.write(&delim, writeSize, Os::File::WaitType::WAIT);
176
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 24 times.
26 if (stat != Os::File::OP_OK) {
177
1/1
✓ Branch 5 taken 2 times.
2 this->unLock();
178
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER, static_cast<I32>(numRecords), stat);
179
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
180 2 return;
181 }
182
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
24 if (writeSize != sizeof(delim)) {
183
1/1
✓ Branch 5 taken 1 times.
1 this->unLock();
184
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::DELIMITER_SIZE, static_cast<I32>(numRecords),
185 static_cast<I32>(writeSize));
186
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
187 1 return;
188 }
189
190 // add delimiter to CRC
191
1/1
✓ Branch 1 taken 23 times.
23 crc.update(&delim, sizeof(delim));
192
193 // serialize record size = id field + data
194
2/2
✓ Branch 7 taken 23 times.
✓ Branch 14 taken 23 times.
23 U32 recordSize = static_cast<U32>(sizeof(FwPrmIdType) + entry.getValue().getSize());
195
196 // reset buffer
197
1/1
✓ Branch 2 taken 23 times.
23 buff.resetSer();
198
1/1
✓ Branch 2 taken 23 times.
23 serStat = buff.serializeFrom(recordSize);
199 // should always work
200 23 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
201
202 // write record size
203
1/1
✓ Branch 2 taken 23 times.
23 writeSize = static_cast<FwSizeType>(buff.getSize());
204
1/1
✓ Branch 3 taken 23 times.
23 stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
205
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23 if (stat != Os::File::OP_OK) {
206
1/1
✓ Branch 5 taken 2 times.
2 this->unLock();
207
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE, static_cast<I32>(numRecords), stat);
208
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
209 2 return;
210 }
211
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (writeSize != sizeof(recordSize)) {
212
1/1
✓ Branch 5 taken 1 times.
1 this->unLock();
213
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::RECORD_SIZE_SIZE, static_cast<I32>(numRecords),
214 static_cast<I32>(writeSize));
215
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
216 1 return;
217 }
218
219 // add recordSize to CRC
220
3/6
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 if (buff.getBuffAddr() != nullptr && writeSize != 0) {
221
1/1
✓ Branch 3 taken 20 times.
20 crc.update(buff.getBuffAddr(), writeSize);
222 }
223
224 // reset buffer
225
1/1
✓ Branch 2 taken 20 times.
20 buff.resetSer();
226
227 // serialize parameter id
228
229
2/2
✓ Branch 8 taken 20 times.
✓ Branch 12 taken 20 times.
20 serStat = buff.serializeFrom(entry.getKey());
230 // should always work
231 20 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
232
233 // write parameter ID
234
1/1
✓ Branch 2 taken 20 times.
20 writeSize = static_cast<FwSizeType>(buff.getSize());
235
1/1
✓ Branch 3 taken 20 times.
20 stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
236
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (stat != Os::File::OP_OK) {
237
1/1
✓ Branch 5 taken 2 times.
2 this->unLock();
238
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID, static_cast<I32>(numRecords), stat);
239
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
240 2 return;
241 }
242
3/3
✓ Branch 2 taken 18 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17 times.
18 if (writeSize != static_cast<FwSizeType>(buff.getSize())) {
243
1/1
✓ Branch 5 taken 1 times.
1 this->unLock();
244
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_ID_SIZE, static_cast<I32>(numRecords),
245 static_cast<I32>(writeSize));
246
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
247 1 return;
248 }
249
250 // add parameter ID to CRC
251
3/6
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
17 if (buff.getBuffAddr() != nullptr && writeSize != 0) {
252
1/1
✓ Branch 3 taken 17 times.
17 crc.update(buff.getBuffAddr(), writeSize);
253 }
254
255 // write serialized parameter value
256
257
2/2
✓ Branch 7 taken 17 times.
✓ Branch 14 taken 17 times.
17 writeSize = static_cast<FwSizeType>(entry.getValue().getSize());
258
2/2
✓ Branch 7 taken 17 times.
✓ Branch 15 taken 17 times.
17 stat = paramFile.write(entry.getValue().getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
259
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
17 if (stat != Os::File::OP_OK) {
260
1/1
✓ Branch 5 taken 2 times.
2 this->unLock();
261
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE, static_cast<I32>(numRecords), stat);
262
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
263 2 return;
264 }
265
4/4
✓ Branch 7 taken 15 times.
✓ Branch 14 taken 15 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 14 times.
15 if (writeSize != static_cast<FwSizeType>(entry.getValue().getSize())) {
266
1/1
✓ Branch 5 taken 1 times.
1 this->unLock();
267
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::PARAMETER_VALUE_SIZE, static_cast<I32>(numRecords),
268 static_cast<I32>(writeSize));
269
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
270 1 return;
271 }
272
273 // add serialized parameter value to crc
274
4/7
✓ Branch 7 taken 14 times.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 14 times.
✗ Branch 19 not taken.
14 if (entry.getValue().getBuffAddr() != nullptr && writeSize != 0) {
275
2/2
✓ Branch 7 taken 14 times.
✓ Branch 15 taken 14 times.
14 crc.update(entry.getValue().getBuffAddr(), writeSize);
276 }
277
278
1/1
✓ Branch 1 taken 14 times.
14 numRecords++;
279 31 }
280
281
1/1
✓ Branch 5 taken 7 times.
7 this->unLock();
282
283 // save current location of pointer in paramFile
284 7 FwSizeType currPosInParamFile;
285
286
1/1
✓ Branch 1 taken 7 times.
7 stat = paramFile.position(currPosInParamFile);
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (stat != Os::File::OP_OK) {
288 ✗ this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::CURR_POSITION, 0, stat);
289 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
290 ✗ return;
291 }
292
293 // seek to beginning and write CRC value
294
1/1
✓ Branch 1 taken 7 times.
7 stat = paramFile.seek(0, Os::File::SeekType::ABSOLUTE);
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (stat != Os::File::OP_OK) {
296 ✗ this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::SEEK_ZERO, 0, stat);
297 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
298 ✗ return;
299 }
300
1/1
✓ Branch 2 taken 7 times.
7 buff.resetSer();
301 7 U32 crcFinal = 0;
302
1/1
✓ Branch 1 taken 7 times.
7 crc.finalize(crcFinal);
303 7 crcFinal = ~crcFinal;
304
1/1
✓ Branch 2 taken 7 times.
7 serStat = buff.serializeFrom(crcFinal);
305
306 7 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
307
1/1
✓ Branch 2 taken 7 times.
7 writeSize = static_cast<FwSizeType>(buff.getSize());
308
309
1/1
✓ Branch 3 taken 7 times.
7 stat = paramFile.write(buff.getBuffAddr(), writeSize, Os::File::WaitType::WAIT);
310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (stat != Os::File::OP_OK) {
311 ✗ this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::CRC_REAL, 0, stat);
312 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
313 ✗ return;
314 }
315
316 // Restore pointer to previously saved location
317
1/1
✓ Branch 1 taken 7 times.
7 stat = paramFile.seek(static_cast<FwSignedSizeType>(currPosInParamFile), Os::File::SeekType::ABSOLUTE);
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (stat != Os::File::OP_OK) {
319 ✗ this->log_WARNING_HI_PrmFileWriteError(PrmWriteError::SEEK_POSITION, 0, stat);
320 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
321 ✗ return;
322 }
323
324
1/1
✓ Branch 5 taken 7 times.
7 this->log_ACTIVITY_HI_PrmFileSaveComplete(numRecords);
325
2/2
✓ Branch 6 taken 7 times.
✓ Branch 9 taken 7 times.
7 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
326 53 }
327
328 10 void PrmDbImpl::PRM_LOAD_FILE_cmdHandler(FwOpcodeType opCode,
329 U32 cmdSeq,
330 const Fw::CmdStringArg& fileName,
331 const PrmDb_Merge& merge) {
332 // Reject PRM_LOAD_FILE command during non-idle file load states
333
2/2
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 8 times.
10 if (m_state != PrmDbFileLoadState::IDLE) {
334
2/2
✓ Branch 6 taken 2 times.
✓ Branch 13 taken 2 times.
2 this->log_WARNING_LO_PrmDbFileLoadInvalidAction(m_state, PrmDb_PrmLoadAction::LOAD_FILE_COMMAND);
335
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::BUSY);
336 2 return;
337 }
338
339 // Reject an empty file name before touching the staging database
340
2/2
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 6 times.
8 if (fileName.length() == 0) {
341 2 this->log_WARNING_HI_PrmDbFileLoadFailed();
342
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
343 2 return;
344 }
345
346 // Set state to loading
347 6 m_state = PrmDbFileLoadState::LOADING_FILE_UPDATES;
348
349 // If reset is true, clear the staging database first
350
2/2
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
6 if (merge == PrmDb_Merge::MERGE) {
351 // Copy active to staging for merging
352
3/3
✓ Branch 5 taken 2 times.
✓ Branch 9 taken 2 times.
✓ Branch 12 taken 2 times.
2 dbCopy(PrmDbType::DB_STAGING, PrmDbType::DB_ACTIVE);
353 } else {
354 // reset staging db, all file contents will be loaded but no old parameters will be retained
355
2/2
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
4 this->clearDb(PrmDbType::DB_STAGING);
356 }
357
358 // Load the file into staging database
359 // The readParamFileImpl will emit the relevant EVR if the file load fails
360 // and also if it succeeds will emit EVRs with the number of records
361
2/2
✓ Branch 5 taken 6 times.
✓ Branch 11 taken 6 times.
6 PrmDbImpl::PrmLoadStatus success = PrmDbImpl::readParamFileImpl(fileName, PrmDbType::DB_STAGING);
362
363
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (success == PrmLoadStatus::SUCCESS) {
364
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
365 1 m_state = PrmDbFileLoadState::FILE_UPDATES_STAGED;
366 } else {
367 5 this->log_WARNING_HI_PrmDbFileLoadFailed();
368 // clear the staging DB and reset to an IDLE state in case of issues
369
2/2
✓ Branch 5 taken 5 times.
✓ Branch 8 taken 5 times.
5 this->clearDb(PrmDbType::DB_STAGING);
370 5 m_state = PrmDbFileLoadState::IDLE;
371
2/2
✓ Branch 6 taken 5 times.
✓ Branch 9 taken 5 times.
5 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
372 }
373 }
374
375 5 void PrmDbImpl::PRM_COMMIT_STAGED_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
376 // Verify we are in the correct state
377
2/2
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 2 times.
5 if (m_state != PrmDbFileLoadState::FILE_UPDATES_STAGED) {
378
2/2
✓ Branch 6 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->log_WARNING_LO_PrmDbFileLoadInvalidAction(m_state, PrmDb_PrmLoadAction::COMMIT_STAGED_COMMAND);
379
2/2
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
380 3 return;
381 }
382
383 // Swap active and staging databases, safely w.r.t. prmGet
384 2 this->lock();
385 2 PrmDbStore* temp = this->m_activeDb;
386 2 this->m_activeDb = this->m_stagingDb;
387 2 this->unLock();
388 2 this->m_stagingDb = temp;
389
390 // Clear the new staging database
391
2/2
✓ Branch 5 taken 2 times.
✓ Branch 8 taken 2 times.
2 this->clearDb(PrmDbType::DB_STAGING);
392
393 // Set file load state to idle
394 2 m_state = PrmDbFileLoadState::IDLE;
395
396 2 this->log_ACTIVITY_HI_PrmDbCommitComplete();
397
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
398 }
399
400 //! ----------------------------------------------------------------------
401 //! Helpers for construction/destruction, init, & handlers
402 //! ----------------------------------------------------------------------
403
404 30 PrmDbImpl::PrmLoadStatus PrmDbImpl::readParamFileImpl(const Fw::StringBase& fileName, PrmDbType dbType) {
405 30 FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
406 30 FW_ASSERT(fileName.length() > 0);
407
408
2/2
✓ Branch 3 taken 30 times.
✓ Branch 6 taken 30 times.
30 Fw::String dbString = getDbString(dbType);
409
410
1/1
✓ Branch 2 taken 30 times.
30 Os::SandboxedFile paramFile;
411
1/1
✓ Branch 4 taken 30 times.
30 this->applySandbox(paramFile);
412
413
2/2
✓ Branch 11 taken 30 times.
✓ Branch 14 taken 30 times.
30 Os::File::Status stat = paramFile.open(fileName.toChar(), Os::File::OPEN_READ);
414
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 if (stat != Os::File::OP_OK) {
415
2/2
✓ Branch 6 taken 6 times.
✓ Branch 10 taken 6 times.
6 this->log_WARNING_HI_PrmFileReadError(PrmReadError::OPEN, 0, stat);
416 6 return PrmLoadStatus::ERROR;
417 }
418 //===========================================================================
419 // read CRC from beginning of file
420
1/1
✓ Branch 2 taken 24 times.
24 WorkingBuffer buff;
421 24 U32 fileCrc;
422 24 FwSizeType readSize = static_cast<FwSizeType>(sizeof(fileCrc));
423
424 // Read raw CRC bytes from file
425
1/1
✓ Branch 3 taken 24 times.
24 stat = paramFile.read(buff.getBuffAddr(), readSize);
426
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
24 if (stat != Os::File::OP_OK) {
427
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC, static_cast<I32>(0), stat);
428 2 return PrmLoadStatus::ERROR;
429 }
430
431
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21 times.
22 if (readSize != sizeof(fileCrc)) {
432
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC_SIZE, static_cast<I32>(0), static_cast<I32>(readSize));
433 1 return PrmLoadStatus::ERROR;
434 }
435
436 // Deserialize the CRC in a portable way
437
1/1
✓ Branch 2 taken 21 times.
21 Fw::SerializeStatus serStat = buff.setBuffLen(readSize);
438 21 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
439
1/1
✓ Branch 2 taken 21 times.
21 buff.resetDeser();
440
1/1
✓ Branch 2 taken 21 times.
21 serStat = buff.deserializeTo(fileCrc);
441 21 FW_ASSERT(Fw::FW_SERIALIZE_OK == serStat, static_cast<FwAssertArgType>(serStat));
442
443 21 U32 crc = 0xFFFFFFFF;
444 // read into CRC buffer for checking
445
446
1/1
✓ Branch 1 taken 21 times.
21 Os::File::Status status = paramFile.calculateCrc(crc);
447
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (status != Os::File::OP_OK) {
448
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::CRC_BUFFER, static_cast<I32>(0), status);
449 2 return PrmLoadStatus::ERROR;
450 }
451
452
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (fileCrc != crc) {
453
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_PrmFileBadCrc(fileCrc, crc);
454 1 return PrmLoadStatus::ERROR;
455 }
456
457 // seek back to just after CRC
458
1/1
✓ Branch 1 taken 18 times.
18 stat = paramFile.seek(sizeof(fileCrc), Os::File::SeekType::ABSOLUTE);
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (stat != Os::File::OP_OK) {
460 ✗ this->log_WARNING_HI_PrmFileReadError(PrmReadError::SEEK_ZERO, 0, stat);
461 ✗ return PrmLoadStatus::ERROR;
462 }
463 //===========================================================================
464
465 18 U32 recordNumTotal = 0;
466 18 U32 recordNumAdded = 0;
467 18 U32 recordNumUpdated = 0;
468 18 U32 recordNumDropped = 0;
469
470
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 for (FwSizeType entry = 0; entry < PRMDB_NUM_DB_ENTRIES; entry++) {
471 25 U8 delimiter;
472 25 readSize = static_cast<FwSizeType>(sizeof(delimiter));
473
474 // read delimiter
475
1/1
✓ Branch 1 taken 25 times.
25 Os::File::Status fStat = paramFile.read(&delimiter, readSize, Os::File::WaitType::WAIT);
476
477 // check for end of file (successful read of size 0); a failed read can
478 // also yield size 0 and must not be mistaken for a clean EOF
479
4/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 19 times.
25 if ((Os::File::OP_OK == fStat) && (0 == readSize)) {
480 4 break;
481 }
482
483
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
21 if (fStat != Os::File::OP_OK) {
484
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER, static_cast<I32>(recordNumTotal), fStat);
485 2 return PrmLoadStatus::ERROR;
486 }
487
488
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 if (sizeof(delimiter) != readSize) {
489
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_SIZE, static_cast<I32>(recordNumTotal),
490 static_cast<I32>(readSize));
491 1 return PrmLoadStatus::ERROR;
492 }
493
494
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 17 times.
18 if (PRMDB_ENTRY_DELIMITER != delimiter) {
495
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::DELIMITER_VALUE, static_cast<I32>(recordNumTotal),
496 delimiter);
497 1 return PrmLoadStatus::ERROR;
498 }
499
500 17 U32 recordSize = 0;
501
502 // read record size
503 17 readSize = sizeof(recordSize);
504
505
1/1
✓ Branch 3 taken 17 times.
17 fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
506
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
17 if (fStat != Os::File::OP_OK) {
507
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE, static_cast<I32>(recordNumTotal), fStat);
508 2 return PrmLoadStatus::ERROR;
509 }
510
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 14 times.
15 if (sizeof(recordSize) != readSize) {
511
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_SIZE, static_cast<I32>(recordNumTotal),
512 static_cast<I32>(readSize));
513 1 return PrmLoadStatus::ERROR;
514 }
515 // set serialized size to read size
516
1/1
✓ Branch 2 taken 14 times.
14 Fw::SerializeStatus desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
517 // should never fail
518 14 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
519 // reset deserialization
520
1/1
✓ Branch 2 taken 14 times.
14 buff.resetDeser();
521 // deserialize, since record size is serialized in file
522
1/1
✓ Branch 2 taken 14 times.
14 desStat = buff.deserializeTo(recordSize);
523 14 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
524
525 // sanity check value. It can't be larger than the maximum parameter buffer size + id
526 // or smaller than the record id
527
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
14 if ((recordSize > FW_PARAM_BUFFER_MAX_SIZE + sizeof(FwPrmIdType)) or (recordSize < sizeof(FwPrmIdType))) {
528
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::RECORD_SIZE_VALUE, static_cast<I32>(recordNumTotal),
529 static_cast<I32>(recordSize));
530 1 return PrmLoadStatus::ERROR;
531 }
532
533 // read the parameter ID
534 13 FwPrmIdType parameterId = 0;
535 13 readSize = static_cast<FwSizeType>(sizeof(FwPrmIdType));
536
537
1/1
✓ Branch 3 taken 13 times.
13 fStat = paramFile.read(buff.getBuffAddr(), readSize, Os::File::WaitType::WAIT);
538
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (fStat != Os::File::OP_OK) {
539
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID, static_cast<I32>(recordNumTotal), fStat);
540 2 return PrmLoadStatus::ERROR;
541 }
542
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (sizeof(parameterId) != static_cast<FwSizeType>(readSize)) {
543
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_ID_SIZE, static_cast<I32>(recordNumTotal),
544 static_cast<I32>(readSize));
545 1 return PrmLoadStatus::ERROR;
546 }
547
548 // set serialized size to read parameter ID
549
1/1
✓ Branch 2 taken 10 times.
10 desStat = buff.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
550 // should never fail
551 10 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat));
552 // reset deserialization
553
1/1
✓ Branch 2 taken 10 times.
10 buff.resetDeser();
554 // deserialize, since parameter ID is serialized in file
555
1/1
✓ Branch 2 taken 10 times.
10 desStat = buff.deserializeTo(parameterId);
556 10 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat);
557
558 // copy parameter value from file into a temporary buffer
559
1/1
✓ Branch 2 taken 10 times.
10 Fw::ParamBuffer tmpParamBuffer; // temporary param buffer to read parameter value from file
560 10 readSize = recordSize - sizeof(parameterId);
561
1/1
✓ Branch 2 taken 10 times.
10 desStat = tmpParamBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readSize));
562 10 FW_ASSERT(Fw::FW_SERIALIZE_OK == desStat, static_cast<FwAssertArgType>(desStat)); // should never fail
563
1/1
✓ Branch 3 taken 10 times.
10 fStat = paramFile.read(tmpParamBuffer.getBuffAddr(), readSize);
564
565
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (fStat != Os::File::OP_OK) {
566
2/2
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
2 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE, static_cast<I32>(recordNumTotal),
567 fStat);
568 2 return PrmLoadStatus::ERROR;
569 }
570
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (static_cast<U32>(readSize) != recordSize - sizeof(parameterId)) {
571
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_PrmFileReadError(PrmReadError::PARAMETER_VALUE_SIZE, static_cast<I32>(recordNumTotal),
572 static_cast<I32>(readSize));
573 1 return PrmLoadStatus::ERROR;
574 }
575
576 // Actually update or add parameter
577
2/2
✓ Branch 5 taken 7 times.
✓ Branch 8 taken 7 times.
7 PrmUpdateType updateStatus = updateAddPrmImpl(parameterId, tmpParamBuffer, dbType);
578
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (updateStatus == PARAM_ADDED) {
579 6 recordNumAdded++;
580
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (updateStatus == PARAM_UPDATED) {
581 1 recordNumUpdated++;
582 }
583
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (updateStatus == NO_SLOTS) {
585 ✗ this->log_WARNING_HI_PrmDbFull(parameterId);
586 ✗ recordNumDropped++;
587 }
588 7 recordNumTotal++;
589 10 }
590
591 // Dropped records mean the database does not reflect the file: report an error
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (recordNumDropped > 0) {
593 ✗ return PrmLoadStatus::ERROR;
594 }
595
596
1/1
✓ Branch 5 taken 4 times.
4 this->log_ACTIVITY_HI_PrmFileLoadComplete(dbString, recordNumTotal, recordNumAdded, recordNumUpdated);
597 4 return PrmLoadStatus::SUCCESS;
598 30 }
599
600 82 PrmDbImpl::PrmUpdateType PrmDbImpl::updateAddPrmImpl(FwPrmIdType id, Fw::ParamBuffer& val, PrmDbType prmDbType) {
601
2/2
✓ Branch 5 taken 82 times.
✓ Branch 8 taken 82 times.
82 auto* db = getDbPtr(prmDbType);
602
603 82 PrmUpdateType updateStatus = NO_SLOTS;
604
605 82 this->lock();
606
607 82 auto prevSize = db->getSize();
608
3/4
✓ Branch 3 taken 82 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 81 times.
✗ Branch 14 not taken.
82 switch (db->insert(id, val)) {
609 1 case Fw::Success::FAILURE:
610 1 updateStatus = NO_SLOTS;
611 1 break;
612 81 case Fw::Success::SUCCESS:
613
2/2
✓ Branch 4 taken 70 times.
✓ Branch 5 taken 11 times.
81 if (prevSize < db->getSize()) {
614 70 updateStatus = PARAM_ADDED;
615 } else {
616 11 FW_ASSERT(prevSize == db->getSize(), static_cast<FwAssertArgType>(prevSize),
617 static_cast<FwAssertArgType>(db->getSize()));
618 11 updateStatus = PARAM_UPDATED;
619 }
620 81 break;
621 ✗ default:
622 ✗ FW_ASSERT(false);
623 }
624
625 82 this->unLock();
626 82 return updateStatus;
627 }
628
629 //! ----------------------------------------------------------------------
630 //! Helpers for database management
631 //! ----------------------------------------------------------------------
632
633 114 void PrmDbImpl::clearDb(PrmDbType prmDbType) {
634
3/3
✓ Branch 5 taken 114 times.
✓ Branch 8 taken 114 times.
✓ Branch 14 taken 114 times.
114 getDbPtr(prmDbType)->clear();
635 114 }
636
637 3 void PrmDbImpl::dbCopy(PrmDbType dest, PrmDbType src) {
638
5/5
✓ Branch 5 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 16 taken 3 times.
✓ Branch 19 taken 3 times.
✓ Branch 25 taken 3 times.
3 *getDbPtr(dest) = *getDbPtr(src);
639
5/5
✓ Branch 7 taken 3 times.
✓ Branch 10 taken 3 times.
✓ Branch 16 taken 3 times.
✓ Branch 19 taken 3 times.
✓ Branch 23 taken 3 times.
3 this->log_ACTIVITY_HI_PrmDbCopyAllComplete(getDbString(src), getDbString(dest));
640 3 }
641
642 237 PrmDbImpl::PrmDbStore* PrmDbImpl::getDbPtr(PrmDbType dbType) {
643 237 FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
644
2/2
✓ Branch 3 taken 160 times.
✓ Branch 4 taken 77 times.
237 if (dbType == PrmDbType::DB_ACTIVE) {
645 160 return m_activeDb;
646 }
647 77 return m_stagingDb;
648 }
649
650 52 Fw::String PrmDbImpl::getDbString(PrmDbType dbType) {
651 52 FW_ASSERT(dbType == PrmDbType::DB_ACTIVE or dbType == PrmDbType::DB_STAGING);
652
2/2
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 17 times.
52 if (dbType == PrmDbType::DB_ACTIVE) {
653 35 return Fw::String("ACTIVE");
654 }
655 17 return Fw::String("STAGING");
656 }
657
658 } // namespace Svc
659