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)) {
51 this->m_numDpSlots = this->m_memSize / slotSize;
55 this->m_stateFileData =
static_cast<DpDstateFileEntry*
>(this->m_memPtr);
59 this->m_numDpSlots = 0;
63 for (
FwSizeType dir = 0; dir < numDirs; dir++) {
64 this->m_directories[dir] = directories[dir];
66 this->m_numDirectories = numDirs;
69 this->m_allocator = &allocator;
70 this->m_allocatorId = memId;
71 this->m_initialized =
true;
74 void DpCatalog::resetCatalog() {
76 this->m_dpCatalog.
clear();
78 this->m_hasCurrentXmit =
false;
80 this->m_pendingFiles = 0;
81 this->m_pendingDpBytes = 0;
83 this->m_catalogBuilt =
false;
86 void DpCatalog::resetStateFileData() {
88 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
89 this->m_stateFileData[slot].used =
false;
90 this->m_stateFileData[slot].visited =
false;
91 (void)
new (&this->m_stateFileData[slot].entry.record) DpRecord();
93 this->m_stateFileEntries = 0;
100 if (this->m_stateFile.
length() == 0) {
119 this->m_stateFileEntries = 0;
122 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
125 stat = stateFile.
read(buffer, size);
140 if (size !=
sizeof(buffer)) {
142 static_cast<I32>(size));
148 Fw::SerializeStatus serStat = entryBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(size));
151 entryBuffer.resetDeser();
158 Fw::SerializeStatus status = entryBuffer.deserializeTo(this->m_stateFileData[entry].entry.dir);
164 status = entryBuffer.deserializeTo(this->m_stateFileData[entry].entry.record);
170 this->m_stateFileData[entry].used =
true;
171 this->m_stateFileData[entry].visited =
false;
175 this->m_stateFileEntries++;
181 void DpCatalog::getFileState(DpStateEntry& entry) {
184 for (
FwSizeType line = 0; line < this->m_stateFileEntries; line++) {
186 if (this->m_stateFileData[line].entry.dir == entry.dir && this->m_stateFileData[line].entry == entry) {
188 entry.record.set_state(this->m_stateFileData[line].entry.record.get_state());
189 entry.record.set_blocks(this->m_stateFileData[line].entry.record.get_blocks());
191 this->m_stateFileData[line].visited =
true;
197 void DpCatalog::pruneAndWriteStateFile() {
222 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
224 if ((this->m_stateFileData[entry].used) and (this->m_stateFileData[entry].visited)) {
226 entryBuffer.resetSer();
228 Fw::SerializeStatus serStat = entryBuffer.serializeFrom(this->m_stateFileData[entry].entry.dir);
231 serStat = entryBuffer.serializeFrom(this->m_stateFileData[entry].entry.record);
237 stat = stateFile.
write(buffer, size);
250 void DpCatalog::appendFileState(
const DpStateEntry& entry) {
252 FW_ASSERT(entry.dir < static_cast<FwIndexType>(this->m_numDirectories), static_cast<FwAssertArgType>(entry.dir),
253 static_cast<FwAssertArgType>(this->m_numDirectories));
269 BYTE buffer[
sizeof(entry.dir) +
sizeof(entry.record)];
272 entryBuffer.resetSer();
277 serStat = entryBuffer.serializeFrom(entry.record);
282 stat = stateFile.
write(buffer, size);
295 if (not this->checkInit()) {
300 if (0 == this->m_numDpSlots) {
306 if (this->m_xmitInProgress) {
312 this->resetStateFileData();
318 this->resetCatalog();
321 response = this->fillBinaryTree();
324 this->resetCatalog();
325 this->resetStateFileData();
330 this->pruneAndWriteStateFile();
335 this->m_catalogBuilt =
true;
350 U32 filesProcessed = 0;
358 status = dpDir.
readDirectory(this->m_fileList, (this->m_numDpSlots - totalFiles), filesRead);
366 FW_ASSERT(filesRead <= this->m_numDpSlots - totalFiles, static_cast<FwAssertArgType>(filesRead),
367 static_cast<FwAssertArgType>(this->m_numDpSlots - totalFiles));
370 for (
FwSizeType file = 0; file < filesRead; file++) {
376 fileNameLength,
DP_EXT, dpExtLength);
379 if ((-1 == loc) || (static_cast<FwSizeType>(loc) + dpExtLength != fileNameLength)) {
384 fullFile.
format(
"%s/%s", this->m_directories[dir].toChar(), this->m_fileList[file].toChar());
386 int ret = processFile(fullFile, dir);
391 filesProcessed +=
static_cast<U32
>(ret);
395 totalFiles += filesProcessed;
398 this->m_pendingFiles, this->m_pendingDpBytes);
402 if (totalFiles == this->m_numDpSlots) {
427 for (
FwSizeType dir = 0; dir < this->m_numDirectories; dir++) {
478 stat = dpFile.
read(dpBuff, size);
517 if (dataSize != expectedDataSize) {
525 if (canonicalFileName != fullFile) {
539 entry.record.set_id(container.
getId());
540 entry.record.set_priority(container.
getPriority());
541 entry.record.set_state(container.
getState());
544 entry.record.set_size(static_cast<U64>(fileSize));
547 this->getFileState(entry);
550 bool inserted = this->insertEntry(entry);
558 this->m_pendingFiles++;
559 this->m_pendingDpBytes += entry.record.get_size();
562 if (this->m_pendingFiles > this->m_numDpSlots) {
578 int DpCatalog::DpStateEntry::compareEntries(
const DpStateEntry& left,
const DpStateEntry& right) {
580 if (left.record.get_priority() < right.record.get_priority()) {
582 }
else if (left.record.get_priority() > right.record.get_priority()) {
587 else if (left.record.get_tSec() < right.record.get_tSec()) {
589 }
else if (left.record.get_tSec() > right.record.get_tSec()) {
594 else if (left.record.get_tSub() < right.record.get_tSub()) {
596 }
else if (left.record.get_tSub() > right.record.get_tSub()) {
601 else if (left.record.get_id() < right.record.get_id()) {
603 }
else if (left.record.get_id() > right.record.get_id()) {
613 bool DpCatalog::DpStateEntry::operator==(
const DpStateEntry& other)
const {
614 return compareEntries(*
this, other) == 0;
616 bool DpCatalog::DpStateEntry::operator!=(
const DpStateEntry& other)
const {
617 return compareEntries(*
this, other) != 0;
620 bool DpCatalog::DpStateEntry::operator>(
const DpStateEntry& other)
const {
621 return compareEntries(*
this, other) > 0;
623 bool DpCatalog::DpStateEntry::operator<(
const DpStateEntry& other)
const {
624 return compareEntries(*
this, other) < 0;
627 bool DpCatalog::insertEntry(DpStateEntry& entry) {
634 void DpCatalog::sendNextEntry() {
636 if (this->m_xmitInProgress !=
true) {
642 if (!this->findNextEntry(entry)) {
644 this->m_xmitInProgress =
false;
651 this->m_currentXmitEntry = entry;
652 this->m_hasCurrentXmit =
true;
656 entry.record.get_tSec(), entry.record.get_tSub());
658 entry.record.get_priority());
667 bool DpCatalog::findNextEntry(DpStateEntry& entry) {
669 if (this->m_dpCatalog.
getSize() == 0) {
678 if (iter == this->m_dpCatalog.
end()) {
688 bool DpCatalog::checkInit() {
689 if (not this->m_initialized) {
692 }
else if (0 == this->m_numDpSlots) {
704 if ((this->m_allocator !=
nullptr) and (this->m_memPtr !=
nullptr)) {
705 this->m_allocator->
deallocate(this->m_allocatorId, this->m_memPtr);
717 this->m_xmitInProgress =
false;
723 if (!this->m_catalogBuilt) {
731 this->m_pendingDpBytes -= this->m_currentXmitEntry.record.get_size();
732 this->m_pendingFiles--;
739 this->appendFileState(this->m_currentXmitEntry);
741 this->m_xmitBytes += this->m_currentXmitEntry.record.get_size();
747 this->m_hasCurrentXmit =
false;
750 this->sendNextEntry();
753 void DpCatalog ::pingIn_handler(
FwIndexType portNum, U32 key) {
758 void DpCatalog ::addToCat_handler(
FwIndexType portNum,
763 if (not this->checkInit()) {
768 if (0 == this->m_numDpSlots) {
774 if (not this->m_catalogBuilt) {
785 FwSizeType dir = this->determineDirectory(fileName);
794 int ret = processFile(fileName, dir);
798 if (!this->m_xmitInProgress && this->m_remainActive) {
799 this->m_xmitInProgress =
true;
800 this->sendNextEntry();
806 this->pruneAndWriteStateFile();
814 void DpCatalog ::BUILD_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
819 void DpCatalog ::START_XMIT_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq,
Fw::Wait wait,
bool remainActive) {
821 this->m_remainActive = remainActive;
828 this->m_xmitCmdWait =
false;
829 this->m_xmitOpCode = 0;
830 this->m_xmitCmdSeq = 0;
832 this->m_xmitCmdWait =
true;
833 this->m_xmitOpCode = opCode;
834 this->m_xmitCmdSeq = cmdSeq;
841 if (not this->checkInit()) {
846 if (0 == this->m_numDpSlots) {
852 if (this->m_xmitInProgress) {
858 if (not this->m_catalogBuilt) {
864 this->m_xmitBytes = 0;
866 this->m_xmitInProgress =
true;
868 this->sendNextEntry();
872 void DpCatalog ::STOP_XMIT_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
873 if (not this->m_xmitInProgress) {
880 this->m_xmitInProgress =
false;
890 void DpCatalog ::CLEAR_CATALOG_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
891 this->resetCatalog();
892 this->resetStateFileData();
898 if (this->m_xmitCmdWait) {
899 this->
cmdResponse_out(this->m_xmitOpCode, this->m_xmitCmdSeq, response);
902 this->m_xmitCmdWait =
false;
903 this->m_xmitOpCode = 0;
904 this->m_xmitCmdSeq = 0;
void log_WARNING_HI_DpCatalogFull(Svc::DpRecord dp)
void log_WARNING_HI_FileHdrError(const Fw::StringBase &file, Svc::DpHdrField field, U32 exp, U32 act)
Serialization/Deserialization operation was successful.
A data product Container.
Status readDirectory(Fw::String filenameArray[], const FwSizeType arraySize, FwSizeType &filenameCount)
Read the contents of the directory and store filenames in filenameArray of size arraySize.
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
void log_WARNING_HI_DpFileXmitError(const Fw::StringBase &file, Svc::SendFileStatus stat)
Log event DpFileXmitError.
PlatformSizeType FwSizeType
U32 FwDpPriorityType
The type of a data product priority.
void log_ACTIVITY_HI_NotLoaded(const Fw::StringBase &file) const
Log event NotLoaded.
void log_WARNING_HI_DpInsertError(Svc::DpRecord dp)
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
Wait or don't wait for something.
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.
ConstIterator begin() const override
Svc::SendFileStatus::T get_status() const
Get member status.
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.
void log_WARNING_HI_DpFileSendError(const Fw::StringBase &file, Svc::SendFileStatus stat)
Log event DpFileSendError.
#define DIRECTORY_DELIMITER
void log_ACTIVITY_HI_DpFileAdded(const Fw::StringBase &file) const
void setBuffer(const Buffer &buffer)
Set the packet buffer.
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 configure(Fw::FileNameString directories[DP_MAX_DIRECTORIES], FwSizeType numDirs, Fw::FileNameString &stateFile, FwEnumStoreType memId, Fw::MemAllocator &allocator)
Configure the DpCatalog.
void log_ACTIVITY_LO_ProcessingDirectory(const Fw::StringBase &directory) const
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_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_ACTIVITY_LO_ProcessingFile(const Fw::StringBase &file) const
static const FwIndexType DP_MAX_FILES
The size of the serial representation.
FormatStatus format(const CHAR *formatString,...)
write formatted string to buffer
Command successfully executed.
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.
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.
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_StateFileWriteError(const Fw::StringBase &file, I32 stat) const
Log event StateFileWriteError.
FwSizeType string_length(const CHAR *source, FwSizeType buffer_size)
get the length of the source string
Open file for writing and truncates file if it exists, ie same flags as creat()