F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
DpWriter.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title DpWriter.cpp
3 // \author bocchino
4 // \brief cpp file for DpWriter component implementation class
5 // ======================================================================
6 
8 #include "Fw/Com/ComPacket.hpp"
12 #include "Os/File.hpp"
13 #include "Utils/Hash/Hash.hpp"
14 #include "config/DpCfg.hpp"
15 
16 namespace Svc {
17 
18 // ----------------------------------------------------------------------
19 // Construction, initialization, and destruction
20 // ----------------------------------------------------------------------
21 
22 DpWriter::DpWriter(const char* const compName) : DpWriterComponentBase(compName), m_dpFileNamePrefix() {}
23 
25 
26 void DpWriter::configure(const Fw::ConstStringBase& dpFileNamePrefix) {
27  this->m_dpFileNamePrefix = dpFileNamePrefix;
28 }
29 
30 // ----------------------------------------------------------------------
31 // Handler implementations for user-defined typed input ports
32 // ----------------------------------------------------------------------
33 
34 void DpWriter::bufferSendIn_handler(const FwIndexType portNum, Fw::Buffer& buffer) {
36  // Update num buffers received
37  ++this->m_numBuffersReceived;
38  // Check that the buffer is valid
39  if (!buffer.isValid()) {
41  status = Fw::Success::FAILURE;
42  }
43  // Check that the buffer is large enough to hold a data product packet
44  const FwSizeType bufferSize = buffer.getSize();
45  if (status == Fw::Success::SUCCESS) {
46  if (bufferSize < Fw::DpContainer::MIN_PACKET_SIZE) {
47  this->log_WARNING_HI_BufferTooSmallForPacket(static_cast<U32>(bufferSize),
49 
50  status = Fw::Success::FAILURE;
51  }
52  }
53  // Set up the container and check that the header hash is valid
54  Fw::DpContainer container;
55  if (status == Fw::Success::SUCCESS) {
56  container.setBuffer(buffer);
57  Utils::HashBuffer storedHash;
58  Utils::HashBuffer computedHash;
59  status = container.checkHeaderHash(storedHash, computedHash);
60  if (status != Fw::Success::SUCCESS) {
61  this->log_WARNING_HI_InvalidHeaderHash(static_cast<U32>(bufferSize), storedHash.asBigEndianU32(),
62  computedHash.asBigEndianU32());
63  }
64  }
65  // Deserialize the packet header
66  if (status == Fw::Success::SUCCESS) {
67  status = this->deserializePacketHeader(buffer, container);
68  }
69  // Check that the packet size fits in the buffer
70  if (status == Fw::Success::SUCCESS) {
71  const FwSizeType packetSize = container.getPacketSize();
72  if (bufferSize < packetSize) {
73  this->log_WARNING_HI_BufferTooSmallForData(static_cast<U32>(bufferSize), static_cast<U32>(packetSize));
74  status = Fw::Success::FAILURE;
75  }
76  }
77  // Perform the requested processing
78  if (status == Fw::Success::SUCCESS) {
79  this->performProcessing(container);
80  }
81  // Construct the file name
82  Fw::FileNameString fileName;
83  if (status == Fw::Success::SUCCESS) {
84  const FwDpIdType containerId = container.getId();
85  const Fw::Time timeTag = container.getTimeTag();
86  const Fw::FormatStatus formatStatus = fileName.format(DP_FILENAME_FORMAT, this->m_dpFileNamePrefix.toChar(),
87  containerId, timeTag.getSeconds(), timeTag.getUSeconds());
88  if (formatStatus != Fw::FormatStatus::SUCCESS) {
89  this->log_WARNING_HI_FileNameFormatError(static_cast<Fw::StringFormatStatus::T>(formatStatus));
90  status = Fw::Success::FAILURE;
91  }
92  }
93  // Calculate and populate the file data checksum
94  if (status == Fw::Success::SUCCESS) {
95  container.updateDataHash();
96  }
97  // Write the file
98  FwSizeType fileSize = 0;
99  if (status == Fw::Success::SUCCESS) {
100  status = this->writeFile(container, fileName, fileSize);
101  }
102  // Send the DpWritten notification on the path matching the input port
103  if (status == Fw::Success::SUCCESS) {
104  this->sendNotification(portNum, container, fileName, fileSize);
105  }
106  // Return the buffer on the path matching the input port
107  if (buffer.isValid()) {
108  this->deallocBufferSendOut_out(portNum, buffer);
109  }
110  // Update the error count
111  if (status != Fw::Success::SUCCESS) {
112  this->m_numErrors++;
113  }
114 }
115 
116 void DpWriter::schedIn_handler(const FwIndexType portNum, U32 context) {
117  // portNum and context are not used
118  (void)portNum;
119  (void)context;
120  // Write telemetry
121  this->tlmWrite_NumBuffersReceived(this->m_numBuffersReceived);
122  this->tlmWrite_NumBytesWritten(this->m_numBytesWritten);
123  this->tlmWrite_NumSuccessfulWrites(this->m_numSuccessfulWrites);
124  this->tlmWrite_NumFailedWrites(this->m_numFailedWrites);
125  this->tlmWrite_NumErrors(this->m_numErrors);
126 }
127 
128 // ----------------------------------------------------------------------
129 // Handler implementations for commands
130 // ----------------------------------------------------------------------
131 
132 void DpWriter::CLEAR_EVENT_THROTTLE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
133  // opCode and cmdSeq are not used
134  (void)opCode;
135  (void)cmdSeq;
136  // Clear throttling
144  // Return command response
145  this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
146 }
147 
148 // ----------------------------------------------------------------------
149 // Private helper functions
150 // ----------------------------------------------------------------------
151 
152 Fw::Success::T DpWriter::deserializePacketHeader(Fw::Buffer& buffer, Fw::DpContainer& container) {
154  container.setBuffer(buffer);
155  const Fw::SerializeStatus serialStatus = container.deserializeHeader();
156  if (serialStatus != Fw::FW_SERIALIZE_OK) {
157  this->log_WARNING_HI_InvalidHeader(static_cast<U32>(buffer.getSize()), static_cast<U32>(serialStatus));
158  status = Fw::Success::FAILURE;
159  }
160  return status;
161 }
162 
163 void DpWriter::performProcessing(Fw::DpContainer& container) {
164  // Get the buffer
165  Fw::Buffer buffer = container.getBuffer();
166  // Get the bit mask for the processing types
167  const Fw::DpCfg::ProcType::SerialType procTypes = container.getProcTypes();
168  // Do the processing
169  bool did_process = false;
170  for (FwIndexType portNum = 0; portNum < NUM_PROCBUFFERSENDOUT_OUTPUT_PORTS; ++portNum) {
171  if ((procTypes & (1 << portNum)) != 0) {
172  this->procBufferSendOut_out(portNum, buffer);
173  did_process = true;
174  }
175  }
176 
177  if (did_process) {
178  // Updated DpContainer object state with the returned value in the
179  // container buffer
180  Fw::SerializeStatus stat = container.deserializeHeader();
181  FW_ASSERT(stat == Fw::FW_SERIALIZE_OK, stat);
182 
183  // Check that the buffer size is compatible with the packet size in
184  // the container header
185  FW_ASSERT(container.getPacketSize() <= buffer.getSize(),
186  static_cast<FwAssertArgType>(container.getPacketSize()),
187  static_cast<FwAssertArgType>(buffer.getSize()));
188 
189  // Re-compute and serialize the container header into the buffer
190  container.updateHeaderHash();
191  container.serializeHeader();
192 
193  // Shrink internal Fw::Buffer
194  container.shrinkBufferSize();
195  }
196 }
197 
198 Fw::Success::T DpWriter::writeFile(const Fw::DpContainer& container,
199  const Fw::FileNameString& fileName,
200  FwSizeType& fileSize) {
202  // Get the buffer
203  Fw::Buffer buffer = container.getBuffer();
204  // Get the file size
205  fileSize = container.getPacketSize();
206  // Open the file
207  Os::File file;
208  Os::File::Status fileStatus = file.open(fileName.toChar(), Os::File::OPEN_CREATE);
209  if (fileStatus != Os::File::OP_OK) {
210  this->log_WARNING_HI_FileOpenError(static_cast<U32>(fileStatus), fileName);
211  status = Fw::Success::FAILURE;
212  }
213  // Write the file
214  if (status == Fw::Success::SUCCESS) {
215  // Set write size to file size
216  // On entry to the write call, this is the number of bytes to write
217  // On return from the write call, this is the number of bytes written
218  FwSizeType writeSize = static_cast<FwSizeType>(fileSize);
219  fileStatus = file.write(buffer.getData(), writeSize);
220  // If a successful write occurred, then update the number of bytes written
221  if (fileStatus == Os::File::OP_OK) {
222  this->m_numBytesWritten += static_cast<U64>(writeSize);
223  }
224  if ((fileStatus == Os::File::OP_OK) and (writeSize == static_cast<FwSizeType>(fileSize))) {
225  // If the write status is success, and the number of bytes written
226  // is the expected number, then record the success
227  this->log_ACTIVITY_LO_FileWritten(static_cast<U32>(writeSize), fileName);
228  } else {
229  // Otherwise record the failure
230  this->log_WARNING_HI_FileWriteError(static_cast<U32>(fileStatus), static_cast<U32>(writeSize),
231  static_cast<U32>(fileSize), fileName);
232  status = Fw::Success::FAILURE;
233  }
234  }
235  // Update the count of successful or failed writes
236  if (status == Fw::Success::SUCCESS) {
237  this->m_numSuccessfulWrites++;
238  } else {
239  this->m_numFailedWrites++;
240  }
241  // Return the status
242  return status;
243 }
244 
245 void DpWriter::sendNotification(FwIndexType portNum,
246  const Fw::DpContainer& container,
247  const Fw::FileNameString& fileName,
248  FwSizeType fileSize) {
250  // Get the priority
251  const FwDpPriorityType priority = container.getPriority();
252  this->dpWrittenOut_out(portNum, fileName, priority, fileSize);
253  }
254 }
255 
256 } // end namespace Svc
Serialization/Deserialization operation was successful.
A data product Container.
Definition: DpContainer.hpp:26
FwDpPriorityType getPriority() const
FwIdType FwOpcodeType
The type of a command opcode.
void log_WARNING_HI_BufferTooSmallForData(FwSizeType bufferSize, U32 minSize)
Representing success.
PlatformSizeType FwSizeType
U32 FwDpPriorityType
The type of a data product priority.
static constexpr FwSizeType MIN_PACKET_SIZE
Definition: DpContainer.hpp:65
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
U8 * getData() const
Definition: Buffer.cpp:82
void setBuffer(const Buffer &buffer)
Set the packet buffer.
void tlmWrite_NumErrors(U32 arg, Fw::Time _tlmTime=Fw::Time())
bool isConnected_dpWrittenOut_OutputPort(FwIndexType portNum) const
SerializeStatus
forward declaration for string
void deallocBufferSendOut_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port deallocBufferSendOut.
void log_WARNING_HI_InvalidBuffer_ThrottleClear()
Reset throttle value for InvalidBuffer.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Definition: File.cpp:50
void tlmWrite_NumFailedWrites(U32 arg, Fw::Time _tlmTime=Fw::Time())
void log_WARNING_HI_FileWriteError_ThrottleClear()
Reset throttle value for FileWriteError.
void updateHeaderHash()
Compute and set the header hash.
bool isValid() const
Definition: Buffer.cpp:78
void dpWrittenOut_out(FwIndexType portNum, const Fw::StringBase &fileName, FwDpPriorityType priority, FwSizeType size) const
Invoke output port dpWrittenOut.
void log_WARNING_HI_InvalidHeaderHash(FwSizeType bufferSize, U32 storedHash, U32 computedHash)
T
The raw enum type.
U32 getSeconds() const
Definition: Time.cpp:128
constexpr const char * DP_FILENAME_FORMAT
Definition: DpCfg.hpp:21
void tlmWrite_NumBuffersReceived(U32 arg, Fw::Time _tlmTime=Fw::Time())
Fw::Time getTimeTag() const
void procBufferSendOut_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port procBufferSendOut.
void shrinkBufferSize()
void log_WARNING_HI_BufferTooSmallForData_ThrottleClear()
Reset throttle value for BufferTooSmallForData.
void log_WARNING_HI_FileOpenError_ThrottleClear()
Reset throttle value for FileOpenError.
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
Definition: File.cpp:213
const char * toChar() const
Convert to a C-style char*.
void log_WARNING_HI_FileOpenError(U32 status, const Fw::StringBase &file)
void log_WARNING_HI_InvalidHeader_ThrottleClear()
Reset throttle value for InvalidHeader.
void log_WARNING_HI_FileNameFormatError(const Fw::StringFormatStatus &status)
FwSizeType getPacketSize() const
Get the packet size corresponding to the data size.
Representing failure.
Fw::Buffer getBuffer() const
void log_WARNING_HI_InvalidHeaderHash_ThrottleClear()
Reset throttle value for InvalidHeaderHash.
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
Definition: StringBase.cpp:58
Command successfully executed.
void log_WARNING_HI_BufferTooSmallForPacket(FwSizeType bufferSize, U32 minSize)
U8 SerialType
The serial representation type.
FwSizeType getSize() const
Definition: Buffer.cpp:90
DpCfg::ProcType::SerialType getProcTypes() const
FwIdType FwDpIdType
The type of a data product identifier.
void updateDataHash()
Update the data hash.
void log_ACTIVITY_LO_FileWritten(U32 bytes, const Fw::StringBase &file) const
Operation was successful.
Definition: File.hpp:42
U32 getUSeconds() const
Definition: Time.cpp:132
A read-only abstract superclass for StringBase.
PlatformIndexType FwIndexType
void serializeHeader()
Definition: DpContainer.cpp:89
void configure(const Fw::ConstStringBase &dpFileNamePrefix)
Configure writer.
Definition: DpWriter.cpp:26
U32 asBigEndianU32() const
Convert bytes 0 through 3 of the hash data to a big-Endian U32 value.
void log_WARNING_HI_FileWriteError(U32 status, U32 bytesWritten, U32 bytesToWrite, const Fw::StringBase &file)
A container class for holding a hash buffer.
Definition: HashBuffer.hpp:26
Success::T checkHeaderHash(Utils::HashBuffer &storedHash, Utils::HashBuffer &computedHash) const
Check the header hash.
RateGroupDivider component implementation.
Fw::SerializeStatus deserializeHeader()
Definition: DpContainer.cpp:38
void tlmWrite_NumBytesWritten(U64 arg, Fw::Time _tlmTime=Fw::Time())
void log_WARNING_HI_InvalidHeader(FwSizeType bufferSize, U32 errorCode)
FwDpIdType getId() const
void tlmWrite_NumSuccessfulWrites(U32 arg, Fw::Time _tlmTime=Fw::Time())
void log_WARNING_HI_BufferTooSmallForPacket_ThrottleClear()
Reset throttle value for BufferTooSmallForPacket.
DpWriter(const char *const compName)
Definition: DpWriter.cpp:22
#define FW_ASSERT(...)
Definition: Assert.hpp:14
Auto-generated base for DpWriter component.
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.
FormatStatus
status of string format calls
Definition: format.hpp:18
Open file for writing and truncates file if it exists, ie same flags as creat()
Definition: File.hpp:34