19 static_assert(
DP_MAX_DIRECTORIES > 0,
"Configuration DP_MAX_DIRECTORIES must be positive");
20 static_assert(
DP_MAX_FILES > 0,
"Configuration DP_MAX_FILES must be positive");
37 this->m_stateFile = stateFile;
42 static const FwSizeType slotSize =
sizeof(DpDstateFileEntry);
46 this->m_memPtr = allocator.
allocate(memId, this->m_memSize, notUsed);
49 if ((this->m_memSize >= slotSize) and (this->m_memPtr !=
nullptr)) {
53 const FwSizeType allocatedSlots = this->m_memSize / slotSize;
58 this->m_stateFileData =
static_cast<DpDstateFileEntry*
>(this->m_memPtr);
62 this->m_numDpSlots = 0;
66 for (
FwSizeType dir = 0; dir < numDirs; dir++) {
67 this->m_directories[dir] = directories[dir];
69 this->m_numDirectories = numDirs;
72 this->m_allocator = &allocator;
73 this->m_allocatorId = memId;
74 this->m_initialized =
true;
84 this->
configure(directoryArray, stateFile, memId, allocator);
87 void DpCatalog::resetCatalog() {
89 this->m_dpCatalog.
clear();
91 this->m_hasCurrentXmit =
false;
93 this->m_pendingFiles = 0;
94 this->m_pendingDpBytes = 0;
96 this->m_catalogBuilt =
false;
99 void DpCatalog::resetStateFileData() {
101 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
102 this->m_stateFileData[slot].used =
false;
103 this->m_stateFileData[slot].visited =
false;
104 (void)
new (&this->m_stateFileData[slot].entry.record) DpRecord();
106 this->m_stateFileEntries = 0;
110 FW_ASSERT(this->m_stateFileData !=
nullptr);
113 if (this->m_stateFile.
length() == 0) {
137 this->m_stateFileEntries = 0;
140 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
143 stat = stateFile.
read(buffer, size);
158 if (size !=
sizeof(buffer)) {
160 static_cast<I32>(size));
166 Fw::SerializeStatus serStat = entryBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(size));
169 entryBuffer.resetDeser();
176 Fw::SerializeStatus status = entryBuffer.deserializeTo(this->m_stateFileData[entry].entry.dir);
182 status = entryBuffer.deserializeTo(this->m_stateFileData[entry].entry.record);
188 this->m_stateFileData[entry].used =
true;
189 this->m_stateFileData[entry].visited =
false;
193 this->m_stateFileEntries++;
199 void DpCatalog::getFileState(DpStateEntry& entry) {
200 FW_ASSERT(this->m_stateFileData !=
nullptr);
202 for (
FwSizeType line = 0; line < this->m_stateFileEntries; line++) {
204 if (this->m_stateFileData[line].entry.dir == entry.dir && this->m_stateFileData[line].entry == entry) {
206 entry.record.set_state(this->m_stateFileData[line].entry.record.get_state());
207 entry.record.set_blocks(this->m_stateFileData[line].entry.record.get_blocks());
209 this->m_stateFileData[line].visited =
true;
215 void DpCatalog::pruneAndWriteStateFile() {
216 FW_ASSERT(this->m_stateFileData !=
nullptr);
240 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
242 if ((this->m_stateFileData[entry].used) and (this->m_stateFileData[entry].visited)) {
244 entryBuffer.resetSer();
246 Fw::SerializeStatus serStat = entryBuffer.serializeFrom(this->m_stateFileData[entry].entry.dir);
249 serStat = entryBuffer.serializeFrom(this->m_stateFileData[entry].entry.record);
255 stat = stateFile.
write(buffer, size);
268 void DpCatalog::appendFileState(
const DpStateEntry& entry) {
269 FW_ASSERT(this->m_stateFileData !=
nullptr);
270 FW_ASSERT(entry.dir < static_cast<FwIndexType>(this->m_numDirectories), static_cast<FwAssertArgType>(entry.dir),
271 static_cast<FwAssertArgType>(this->m_numDirectories));
290 entryBuffer.resetSer();
295 serStat = entryBuffer.serializeFrom(entry.record);
300 stat = stateFile.
write(buffer, size);
313 if (not this->checkInit()) {
318 if (0 == this->m_numDpSlots) {
324 if (this->m_xmitInProgress) {
330 this->resetStateFileData();
336 this->resetStateFileData();
341 this->resetCatalog();
344 response = this->fillBinaryTree();
347 this->resetCatalog();
348 this->resetStateFileData();
353 this->pruneAndWriteStateFile();
358 this->m_catalogBuilt =
true;
373 U32 filesProcessed = 0;
390 FW_ASSERT(filesRead <= this->m_numDpSlots - totalFiles, static_cast<FwAssertArgType>(filesRead),
391 static_cast<FwAssertArgType>(this->m_numDpSlots - totalFiles));
394 for (
FwSizeType file = 0; file < filesRead; file++) {
400 fileNameLength,
DP_EXT, dpExtLength);
403 if ((-1 == loc) || (static_cast<FwSizeType>(loc) + dpExtLength != fileNameLength)) {
409 fullFile.
format(
"%s/%s", this->m_directories[dir].toChar(), this->m_fileList[file].toChar());
412 static_cast<Fw::StringFormatStatus::T>(formatStatus));
416 const ProcessFileStatus ret = processFile(fullFile, dir);
417 if (ret == ProcessFileStatus::QUIT) {
421 if (ret == ProcessFileStatus::SUCCESS) {
427 totalFiles += filesProcessed;
430 this->m_pendingFiles, this->m_pendingDpBytes);
434 if (totalFiles == this->m_numDpSlots) {
460 for (
FwSizeType dir = 0; dir < this->m_numDirectories; dir++) {
478 DpCatalog::ProcessFileStatus DpCatalog::processFile(
const Fw::String& fullFile,
FwSizeType dir) {
495 return ProcessFileStatus::FAILED;
500 return ProcessFileStatus::FAILED;
506 return ProcessFileStatus::FAILED;
512 stat = dpFile.
read(dpBuff, size);
516 return ProcessFileStatus::FAILED;
523 return ProcessFileStatus::FAILED;
539 return ProcessFileStatus::FAILED;
546 return ProcessFileStatus::FAILED;
551 if (dataSize != expectedDataSize) {
553 return ProcessFileStatus::FAILED;
562 static_cast<Fw::StringFormatStatus::T>(canonicalFormatStatus));
563 return ProcessFileStatus::FAILED;
565 if (canonicalFileName != fullFile) {
567 return ProcessFileStatus::FAILED;
573 return ProcessFileStatus::FAILED;
579 entry.record.set_id(container.
getId());
580 entry.record.set_priority(container.
getPriority());
581 entry.record.set_state(container.
getState());
584 entry.record.set_size(static_cast<U64>(fileSize));
587 this->getFileState(entry);
592 return ProcessFileStatus::FAILED;
596 bool inserted = this->insertEntry(entry);
600 return ProcessFileStatus::QUIT;
604 this->m_pendingFiles++;
605 this->m_pendingDpBytes += entry.record.get_size();
608 if (this->m_pendingFiles > this->m_numDpSlots) {
610 return ProcessFileStatus::QUIT;
618 return ProcessFileStatus::SUCCESS;
624 I8 DpCatalog::DpStateEntry::compareEntries(
const DpStateEntry& left,
const DpStateEntry& right) {
626 if (left.record.get_priority() < right.record.get_priority()) {
628 }
else if (left.record.get_priority() > right.record.get_priority()) {
633 else if (left.record.get_tSec() < right.record.get_tSec()) {
635 }
else if (left.record.get_tSec() > right.record.get_tSec()) {
640 else if (left.record.get_tSub() < right.record.get_tSub()) {
642 }
else if (left.record.get_tSub() > right.record.get_tSub()) {
647 else if (left.record.get_id() < right.record.get_id()) {
649 }
else if (left.record.get_id() > right.record.get_id()) {
659 bool DpCatalog::DpStateEntry::operator==(
const DpStateEntry& other)
const {
660 return compareEntries(*
this, other) == 0;
662 bool DpCatalog::DpStateEntry::operator!=(
const DpStateEntry& other)
const {
663 return compareEntries(*
this, other) != 0;
666 bool DpCatalog::DpStateEntry::operator>(
const DpStateEntry& other)
const {
667 return compareEntries(*
this, other) > 0;
669 bool DpCatalog::DpStateEntry::operator<(
const DpStateEntry& other)
const {
670 return compareEntries(*
this, other) < 0;
673 bool DpCatalog::insertEntry(DpStateEntry& entry) {
680 void DpCatalog::sendNextEntry() {
682 if (this->m_xmitInProgress !=
true) {
688 if (!this->findNextEntry(entry)) {
690 this->m_xmitInProgress =
false;
697 this->m_currentXmitEntry = entry;
698 this->m_hasCurrentXmit =
true;
703 entry.record.get_id(), entry.record.get_tSec(), entry.record.get_tSub());
706 static_cast<Fw::StringFormatStatus::T>(formatStatus));
709 this->m_hasCurrentXmit =
false;
710 this->m_xmitInProgress =
false;
715 entry.record.get_priority());
721 this->m_hasCurrentXmit =
false;
722 this->m_xmitInProgress =
false;
727 bool DpCatalog::findNextEntry(DpStateEntry& entry) {
729 if (this->m_dpCatalog.
getSize() == 0) {
738 if (iter == this->m_dpCatalog.
end()) {
748 bool DpCatalog::checkInit() {
749 if (not this->m_initialized) {
752 }
else if (0 == this->m_numDpSlots) {
764 if ((this->m_allocator !=
nullptr) and (this->m_memPtr !=
nullptr)) {
765 this->m_allocator->
deallocate(this->m_allocatorId, this->m_memPtr);
777 this->m_xmitInProgress =
false;
783 if (!this->m_catalogBuilt) {
784 this->m_hasCurrentXmit =
false;
785 this->m_xmitInProgress =
false;
794 this->m_pendingDpBytes -= this->m_currentXmitEntry.record.get_size();
795 this->m_pendingFiles--;
802 this->appendFileState(this->m_currentXmitEntry);
804 this->m_xmitBytes += this->m_currentXmitEntry.record.get_size();
810 this->m_hasCurrentXmit =
false;
813 this->sendNextEntry();
816 void DpCatalog ::pingIn_handler(
FwIndexType portNum, U32 key) {
821 void DpCatalog ::addToCat_handler(
FwIndexType portNum,
826 if (not this->checkInit()) {
831 if (0 == this->m_numDpSlots) {
837 if (not this->m_catalogBuilt) {
848 FwSizeType dir = this->determineDirectory(fileName);
856 const ProcessFileStatus ret = processFile(fileName, dir);
858 if (ret == ProcessFileStatus::SUCCESS) {
860 if (!this->m_xmitInProgress && this->m_remainActive) {
861 this->m_xmitInProgress =
true;
862 this->sendNextEntry();
868 this->pruneAndWriteStateFile();
876 void DpCatalog ::BUILD_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
881 void DpCatalog ::START_XMIT_CATALOG_cmdHandler(
FwOpcodeType opCode,
885 this->m_remainActive = remainActive;
890 this->m_xmitCmdWait =
true;
891 this->m_xmitOpCode = opCode;
892 this->m_xmitCmdSeq = cmdSeq;
899 this->m_xmitCmdWait =
false;
900 this->m_xmitOpCode = 0;
901 this->m_xmitCmdSeq = 0;
910 if (not this->checkInit()) {
915 if (0 == this->m_numDpSlots) {
921 if (this->m_xmitInProgress) {
927 if (not this->m_catalogBuilt) {
933 this->m_xmitBytes = 0;
935 this->m_xmitInProgress =
true;
937 this->sendNextEntry();
941 void DpCatalog ::STOP_XMIT_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
942 if (not this->m_xmitInProgress) {
949 this->m_xmitInProgress =
false;
959 void DpCatalog ::CLEAR_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
960 this->resetCatalog();
961 this->resetStateFileData();
967 if (this->m_xmitCmdWait) {
968 this->
cmdResponse_out(this->m_xmitOpCode, this->m_xmitCmdSeq, response);
971 this->m_xmitCmdWait =
false;
972 this->m_xmitOpCode = 0;
973 this->m_xmitCmdSeq = 0;
Serialization/Deserialization operation was successful.
A data product Container.
void pingOut_out(FwIndexType portNum, U32 key) const
Invoke output port pingOut.
FwDpPriorityType getPriority() const
virtual void * allocate(const FwEnumStoreType identifier, FwSizeType &size, bool &recoverable, FwSizeType alignment=alignof(std::max_align_t))=0
void log_WARNING_HI_StateFileTruncated(const Fw::StringBase &file, I32 offset, I32 size) const
Log event StateFileTruncated.
void log_WARNING_HI_ComponentNoMemory()
FwIdType FwOpcodeType
The type of a command opcode.
void log_WARNING_HI_DirectoryOpenError(const Fw::StringBase &loc, I32 stat) const
PlatformSizeType FwSizeType
void log_WARNING_HI_DpFileXmitError(const Fw::StringBase &file, const Svc::SendFileStatus &stat)
Log event DpFileXmitError.
U32 FwDpPriorityType
The type of a data product priority.
void log_ACTIVITY_HI_NotLoaded(const Fw::StringBase &file) const
Log event NotLoaded.
Auto-generated base for DpCatalog component.
FwSignedSizeType substring_find(const CHAR *source_string, FwSizeType source_size, const CHAR *sub_string, FwSizeType sub_size)
find the first occurrence of a substring
void log_WARNING_HI_FileNameFormatError(const Fw::StringBase &file, const Fw::StringFormatStatus &status)
Wait or don't wait for something.
void log_WARNING_HI_DpInsertError(const Svc::DpRecord &dp)
static constexpr FwSizeType MIN_PACKET_SIZE
static const FwIndexType DP_MAX_DIRECTORIES
Svc::SendFileResponse fileOut_out(FwIndexType portNum, const Fw::StringBase &sourceFileName, const Fw::StringBase &destFileName, U32 offset, U32 length) const
Invoke output port fileOut.
int8_t I8
8-bit signed integer
ConstIterator begin() const override
Svc::SendFileStatus::T get_status() const
Get member status.
void configure(const Fw::ExternalArray< Fw::FileNameString > &directories, Fw::FileNameString &stateFile, FwEnumStoreType memId, Fw::MemAllocator &allocator)
Configure the DpCatalog.
enum T e
The raw enum value.
Overwrite file when it exists and creation was requested.
PlatformSignedSizeType FwSignedSizeType
void log_WARNING_HI_StateFileOpenError(const Fw::StringBase &file, I32 stat) const
Log event StateFileOpenError.
Enum representing a command response.
#define DIRECTORY_DELIMITER
void log_ACTIVITY_HI_DpFileAdded(const Fw::StringBase &file) const
void setBuffer(const Buffer &buffer)
Set the packet buffer.
bool isValid() const
Check raw enum value for validity.
void log_ACTIVITY_HI_CatalogBuildComplete() const
void log_WARNING_LO_DpXmitInProgress()
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
SerializeStatus
forward declaration for string
void log_WARNING_HI_FileCorruptedDataError(const Fw::StringBase &file, I32 stat) const
void log_WARNING_HI_FileOpenError(const Fw::StringBase &loc, I32 stat)
void log_ACTIVITY_LO_ProductComplete(const Fw::StringBase &file, U32 pending, U64 pending_bytes) const
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
void log_WARNING_HI_NoDpMemory() const
Log event NoDpMemory.
void log_WARNING_HI_FileSizeError(const Fw::StringBase &file, I32 stat)
void log_WARNING_HI_FileReadError(const Fw::StringBase &file, I32 stat)
void clear() override
Clear the set.
void log_ACTIVITY_HI_DpFileSkipped(const Fw::StringBase &file) const
void log_ACTIVITY_LO_ProcessingDirectory(const Fw::StringBase &directory) const
File doesn't exist (for read)
void log_ACTIVITY_HI_ProcessingDirectoryComplete(const Fw::StringBase &loc, U32 total, U32 pending, U64 pending_bytes) const
void log_ACTIVITY_LO_SendingProduct(const Fw::StringBase &file, U32 bytes, U32 prio) const
void log_WARNING_LO_NoStateFileSpecified() const
Log event NoStateFileSpecified.
External serialize buffer with no copy semantics.
void log_WARNING_LO_NoStateFile(const Fw::StringBase &file) const
Log event NoStateFile.
void log_WARNING_HI_ComponentNotInitialized()
constexpr const char * DP_FILENAME_FORMAT
Fw::Time getTimeTag() const
FwSizeType getSize() const override
void close() override
close the file, if not opened then do nothing
Status write(const U8 *buffer, FwSizeType &size)
write data to this file from the supplied buffer bounded by size
void log_WARNING_LO_XmitNotActive() const
Log event XmitNotActive.
const char * toChar() const
Convert to a C-style char*.
void log_ACTIVITY_HI_CatalogXmitCompleted(U64 bytes) const
void log_WARNING_HI_DpFileSendError(const Fw::StringBase &file, const Svc::SendFileStatus &stat)
Log event DpFileSendError.
void log_ACTIVITY_LO_ProcessingFile(const Fw::StringBase &file) const
static const FwIndexType DP_MAX_FILES
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
FwSizeType getSize() const
Command successfully executed.
The size of the serial representation.
void log_WARNING_HI_FileHdrError(const Fw::StringBase &file, const Svc::DpHdrField &field, U32 exp, U32 act)
void log_ACTIVITY_HI_CatalogXmitStopped(U64 bytes) const
uint8_t U8
8-bit unsigned integer
DpCatalog(const char *const compName)
DpCatalog constructor.
static Status getFileSize(const char *path, FwSizeType &size)
Get the size of the file (in bytes) at the specified path.
FwSignedSizeType substring_find_last(const CHAR *source_string, FwSizeType source_size, const CHAR *sub_string, FwSizeType sub_size)
find the last occurrence of a substring
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
Success remove(const T &element) override
Command had execution error.
Success find(const T &element) const override
void log_WARNING_HI_StateFileReadError(const Fw::StringBase &file, I32 stat, I32 offset) const
Log event StateFileReadError.
Fw::DpState getState() const
Get the product state.
void log_WARNING_HI_DirectoryNotManaged(const Fw::StringBase &file) const
Memory Allocation base class.
void log_WARNING_HI_CatalogFull(const Fw::StringBase &dir)
Operation was successful.
void log_WARNING_HI_XmitUnbuiltCatalog() const
Log event XmitUnbuiltCatalog.
Status readDirectory(Fw::ExternalArray< Fw::String > &filenameArray, FwSizeType &filenameCount)
Read the contents of the directory and store filenames in the supplied array.
PlatformIndexType FwIndexType
void log_WARNING_HI_FileHdrDesError(const Fw::StringBase &file, I32 stat)
Operation was successful.
Send file response struct.
U32 asBigEndianU32() const
Convert bytes 0 through 3 of the hash data to a big-Endian U32 value.
A container class for holding a hash buffer.
Success::T checkHeaderHash(Utils::HashBuffer &storedHash, Utils::HashBuffer &computedHash) const
Check the header hash.
Status open(const char *path, OpenMode mode) override
Open or create a directory.
Success insert(const T &element) override
RateGroupDivider component implementation.
ConstIterator end() const override
virtual SizeType length() const
Get the length of the string.
Fw::SerializeStatus deserializeHeader()
Operation was successful.
virtual void deallocate(const FwEnumStoreType identifier, void *ptr)=0
FwSizeType getDataSize() const
Don't wait for something.
void log_WARNING_HI_InvalidFileName(const Fw::StringBase &file, const Fw::StringBase &expected)
void log_WARNING_HI_DpCatalogFull(const Svc::DpRecord &dp)
void log_WARNING_HI_StateFileWriteError(const Fw::StringBase &file, I32 stat) const
Log event StateFileWriteError.
PlatformAssertArgType FwAssertArgType
The type of arguments to assert functions.
FwSizeType string_length(const CHAR *source, FwSizeType buffer_size)
get the length of the source string
FormatStatus
status of string format calls
Open file for writing and truncates file if it exists, ie same flags as creat()