mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 00:44:37 -06:00
* Pull in framework changes from data-products branch * Pull in changes to DpManager from data-products branch * Pull in DpWriter from data-products branch * Fix spelling * Revise FileNameString * Fix warnings in CI * Fix static analysis warnings * Fix static analysis warnings * Revise formatting and comments * Revise banner comments * Revise FileNameString per PR comment * Revise path names in config headers If a header H.hpp exists in the F Prime source base, then is dangerous. Because [project root] and [fprime root] are both in the list of include paths, it's not clear whether this means "include [project root]/config/H.hpp" or "include [fprime root]/config/H.hpp." On the other hand, or has no such ambiguity, because only one of [project root]/config and [fprime root]/config is in the list of include paths. * Revise path names in config headers If a header H.hpp exists in the F Prime source base, then `#include "config/H.hpp"` is dangerous. Because [project root] and [fprime root] are both in the list of include paths, it's not clear whether this means "include [project root]/config/H.hpp" or "include [fprime root]/config/H.hpp." On the other hand, include <config/H.hpp> or `#include "config/H.hpp"` has no such ambiguity, because only one of [project root]/config and [fprime root]/config is in the list of include paths.
222 lines
8.9 KiB
C++
222 lines
8.9 KiB
C++
// ======================================================================
|
|
// \title DpWriter.cpp
|
|
// \author bocchino
|
|
// \brief cpp file for DpWriter component implementation class
|
|
// ======================================================================
|
|
|
|
#include "Fw/Com/ComPacket.hpp"
|
|
#include "Fw/Types/Serializable.hpp"
|
|
#include "Os/File.hpp"
|
|
#include "Svc/DpWriter/DpWriter.hpp"
|
|
#include "Utils/Hash/Hash.hpp"
|
|
#include "config/DpCfg.hpp"
|
|
#include "config/FpConfig.hpp"
|
|
|
|
namespace Svc {
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Construction, initialization, and destruction
|
|
// ----------------------------------------------------------------------
|
|
|
|
DpWriter::DpWriter(const char* const compName) : DpWriterComponentBase(compName) {}
|
|
|
|
DpWriter::~DpWriter() {}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Handler implementations for user-defined typed input ports
|
|
// ----------------------------------------------------------------------
|
|
|
|
void DpWriter::bufferSendIn_handler(const NATIVE_INT_TYPE portNum, Fw::Buffer& buffer) {
|
|
Fw::Success::T status = Fw::Success::SUCCESS;
|
|
// portNum is unused
|
|
(void)portNum;
|
|
// Update num buffers received
|
|
++this->m_numBuffersReceived;
|
|
// Check that the buffer is valid
|
|
if (!buffer.isValid()) {
|
|
this->log_WARNING_HI_InvalidBuffer();
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
// Check that the buffer is large enough to hold a data product packet
|
|
const FwSizeType bufferSize = buffer.getSize();
|
|
if (status == Fw::Success::SUCCESS) {
|
|
if (bufferSize < Fw::DpContainer::MIN_PACKET_SIZE) {
|
|
this->log_WARNING_HI_BufferTooSmallForPacket(bufferSize, Fw::DpContainer::MIN_PACKET_SIZE);
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
}
|
|
// Set up the container and check that the header hash is valid
|
|
Fw::DpContainer container;
|
|
if (status == Fw::Success::SUCCESS) {
|
|
container.setBuffer(buffer);
|
|
Utils::HashBuffer storedHash;
|
|
Utils::HashBuffer computedHash;
|
|
status = container.checkHeaderHash(storedHash, computedHash);
|
|
if (status != Fw::Success::SUCCESS) {
|
|
this->log_WARNING_HI_InvalidHeaderHash(bufferSize, storedHash.asBigEndianU32(),
|
|
computedHash.asBigEndianU32());
|
|
}
|
|
}
|
|
// Deserialize the packet header
|
|
if (status == Fw::Success::SUCCESS) {
|
|
status = this->deserializePacketHeader(buffer, container);
|
|
}
|
|
// Check that the packet size fits in the buffer
|
|
if (status == Fw::Success::SUCCESS) {
|
|
const FwSizeType packetSize = container.getPacketSize();
|
|
if (bufferSize < packetSize) {
|
|
this->log_WARNING_HI_BufferTooSmallForData(bufferSize, packetSize);
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
}
|
|
// Perform the requested processing
|
|
if (status == Fw::Success::SUCCESS) {
|
|
this->performProcessing(container);
|
|
}
|
|
// Construct the file name
|
|
Fw::FileNameString fileName;
|
|
if (status == Fw::Success::SUCCESS) {
|
|
const FwDpIdType containerId = container.getId();
|
|
const Fw::Time timeTag = container.getTimeTag();
|
|
fileName.format(DP_FILENAME_FORMAT, containerId, timeTag.getSeconds(), timeTag.getUSeconds());
|
|
}
|
|
FwSizeType fileSize = 0;
|
|
// Write the file
|
|
if (status == Fw::Success::SUCCESS) {
|
|
status = this->writeFile(container, fileName, fileSize);
|
|
}
|
|
// Send the DpWritten notification
|
|
if (status == Fw::Success::SUCCESS) {
|
|
this->sendNotification(container, fileName, fileSize);
|
|
}
|
|
// Deallocate the buffer
|
|
if (buffer.isValid()) {
|
|
this->deallocBufferSendOut_out(0, buffer);
|
|
}
|
|
// Update the error count
|
|
if (status != Fw::Success::SUCCESS) {
|
|
this->m_numErrors++;
|
|
}
|
|
}
|
|
|
|
void DpWriter::schedIn_handler(const NATIVE_INT_TYPE portNum, U32 context) {
|
|
// portNum and context are not used
|
|
(void)portNum;
|
|
(void)context;
|
|
// Write telemetry
|
|
this->tlmWrite_NumBuffersReceived(this->m_numBuffersReceived);
|
|
this->tlmWrite_NumBytesWritten(this->m_numBytesWritten);
|
|
this->tlmWrite_NumSuccessfulWrites(this->m_numSuccessfulWrites);
|
|
this->tlmWrite_NumFailedWrites(this->m_numFailedWrites);
|
|
this->tlmWrite_NumErrors(this->m_numErrors);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Handler implementations for commands
|
|
// ----------------------------------------------------------------------
|
|
|
|
void DpWriter::CLEAR_EVENT_THROTTLE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
|
|
// opCode and cmdSeq are not used
|
|
(void)opCode;
|
|
(void)cmdSeq;
|
|
// Clear throttling
|
|
this->log_WARNING_HI_BufferTooSmallForData_ThrottleClear();
|
|
this->log_WARNING_HI_BufferTooSmallForPacket_ThrottleClear();
|
|
this->log_WARNING_HI_FileOpenError_ThrottleClear();
|
|
this->log_WARNING_HI_FileWriteError_ThrottleClear();
|
|
this->log_WARNING_HI_InvalidBuffer_ThrottleClear();
|
|
this->log_WARNING_HI_InvalidHeaderHash_ThrottleClear();
|
|
this->log_WARNING_HI_InvalidHeader_ThrottleClear();
|
|
// Return command response
|
|
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// Private helper functions
|
|
// ----------------------------------------------------------------------
|
|
|
|
Fw::Success::T DpWriter::deserializePacketHeader(Fw::Buffer& buffer, Fw::DpContainer& container) {
|
|
Fw::Success::T status = Fw::Success::SUCCESS;
|
|
container.setBuffer(buffer);
|
|
const Fw::SerializeStatus serialStatus = container.deserializeHeader();
|
|
if (serialStatus != Fw::FW_SERIALIZE_OK) {
|
|
this->log_WARNING_HI_InvalidHeader(static_cast<U32>(buffer.getSize()), static_cast<U32>(serialStatus));
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
void DpWriter::performProcessing(const Fw::DpContainer& container) {
|
|
// Get the buffer
|
|
Fw::Buffer buffer = container.getBuffer();
|
|
// Get the bit mask for the processing types
|
|
const Fw::DpCfg::ProcType::SerialType procTypes = container.getProcTypes();
|
|
// Do the processing
|
|
for (FwIndexType portNum = 0; portNum < NUM_PROCBUFFERSENDOUT_OUTPUT_PORTS; ++portNum) {
|
|
if ((procTypes & (1 << portNum)) != 0) {
|
|
this->procBufferSendOut_out(portNum, buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
Fw::Success::T DpWriter::writeFile(const Fw::DpContainer& container,
|
|
const Fw::FileNameString& fileName,
|
|
FwSizeType& fileSize) {
|
|
Fw::Success::T status = Fw::Success::SUCCESS;
|
|
// Get the buffer
|
|
Fw::Buffer buffer = container.getBuffer();
|
|
// Get the file size
|
|
fileSize = container.getPacketSize();
|
|
// Open the file
|
|
Os::File file;
|
|
Os::File::Status fileStatus = file.open(fileName.toChar(), Os::File::OPEN_CREATE);
|
|
if (fileStatus != Os::File::OP_OK) {
|
|
this->log_WARNING_HI_FileOpenError(static_cast<U32>(fileStatus), fileName.toChar());
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
// Write the file
|
|
if (status == Fw::Success::SUCCESS) {
|
|
// Set write size to file size
|
|
// On entry to the write call, this is the number of bytes to write
|
|
// On return from the write call, this is the number of bytes written
|
|
FwSignedSizeType writeSize = fileSize;
|
|
fileStatus = file.write(buffer.getData(), writeSize);
|
|
// If a successful write occurred, then update the number of bytes written
|
|
if (fileStatus == Os::File::OP_OK) {
|
|
this->m_numBytesWritten += writeSize;
|
|
}
|
|
if ((fileStatus == Os::File::OP_OK) and (writeSize == static_cast<FwSignedSizeType>(fileSize))) {
|
|
// If the write status is success, and the number of bytes written
|
|
// is the expected number, then record the success
|
|
this->log_ACTIVITY_LO_FileWritten(writeSize, fileName.toChar());
|
|
} else {
|
|
// Otherwise record the failure
|
|
this->log_WARNING_HI_FileWriteError(static_cast<U32>(fileStatus), static_cast<U32>(writeSize),
|
|
static_cast<U32>(fileSize), fileName.toChar());
|
|
status = Fw::Success::FAILURE;
|
|
}
|
|
}
|
|
// Update the count of successful or failed writes
|
|
if (status == Fw::Success::SUCCESS) {
|
|
this->m_numSuccessfulWrites++;
|
|
} else {
|
|
this->m_numFailedWrites++;
|
|
}
|
|
// Return the status
|
|
return status;
|
|
}
|
|
|
|
void DpWriter::sendNotification(const Fw::DpContainer& container,
|
|
const Fw::FileNameString& fileName,
|
|
FwSizeType fileSize) {
|
|
if (isConnected_dpWrittenOut_OutputPort(0)) {
|
|
// Construct the file name
|
|
fileNameString portFileName(fileName.toChar());
|
|
// Get the priority
|
|
const FwDpPriorityType priority = container.getPriority();
|
|
this->dpWrittenOut_out(0, portFileName, priority, fileSize);
|
|
}
|
|
}
|
|
|
|
} // end namespace Svc
|