17 static_assert(
DP_MAX_DIRECTORIES > 0,
"Configuration DP_MAX_DIRECTORIES must be positive");
18 static_assert(
DP_MAX_FILES > 0,
"Configuration DP_MAX_FILES must be positive");
28 m_freeListHead(nullptr),
29 m_freeListFoot(nullptr),
30 m_traverseStack(nullptr),
31 m_currentNode(nullptr),
32 m_currentXmitNode(nullptr),
36 m_stateFileData(nullptr),
37 m_stateFileEntries(0),
42 m_xmitInProgress(false),
66 this->m_stateFile = stateFile;
75 static const FwSizeType slotSize =
sizeof(DpBtreeNode) +
sizeof(DpBtreeNode**) +
sizeof(DpDstateFileEntry);
79 this->m_memPtr = allocator.
allocate(memId, this->m_memSize, notUsed);
102 (this->m_memSize >=
sizeof(DpBtreeNode)) and
103 (this->m_memPtr !=
nullptr)
106 this->m_numDpSlots = this->m_memSize / slotSize;
107 this->resetBinaryTree();
109 this->m_traverseStack =
reinterpret_cast<DpBtreeNode**
>(&this->m_freeListHead[this->m_numDpSlots]);
110 this->resetTreeStack();
112 this->m_stateFileData =
reinterpret_cast<DpDstateFileEntry*
>(&this->m_traverseStack[this->m_numDpSlots]);
117 this->m_numDpSlots = 0;
121 for (
FwSizeType dir = 0; dir < numDirs; dir++) {
122 this->m_directories[dir] = directories[dir];
124 this->m_numDirectories = numDirs;
127 this->m_allocator = &allocator;
128 this->m_allocatorId = memId;
129 this->m_initialized =
true;
132 void DpCatalog::resetBinaryTree() {
136 this->m_freeListHead =
static_cast<DpBtreeNode*
>(this->m_memPtr);
137 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
139 (void)
new(&this->m_freeListHead[slot]) DpBtreeNode();
140 this->m_freeListHead[slot].left =
nullptr;
141 this->m_freeListHead[slot].right =
nullptr;
144 this->m_freeListHead[slot-1].left = &this->m_freeListHead[slot];
148 this->m_freeListFoot = &this->m_freeListHead[this->m_numDpSlots - 1];
150 this->m_dpTree =
nullptr;
152 this->m_numDpRecords = 0;
156 void DpCatalog::resetStateFileData() {
158 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
159 this->m_stateFileData[slot].used =
false;
160 this->m_stateFileData[slot].visited =
false;
161 (void)
new(&this->m_stateFileData[slot].entry.record) DpRecord();
163 this->m_stateFileEntries = 0;
171 if (this->m_stateFile.
length() == 0) {
190 this->m_stateFileEntries = 0;
193 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
197 stat = stateFile.
read(buffer, size);
211 if (size !=
sizeof(buffer)) {
217 Fw::SerializeStatus serStat = entryBuffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(size));
220 entryBuffer.resetDeser();
226 Fw::SerializeStatus status = entryBuffer.deserialize(this->m_stateFileData[entry].entry.dir);
228 status = entryBuffer.deserialize(this->m_stateFileData[entry].entry.record);
230 this->m_stateFileData[entry].used =
true;
231 this->m_stateFileData[entry].visited =
false;
235 this->m_stateFileEntries++;
241 void DpCatalog::getFileState(DpStateEntry& entry) {
244 for (
FwSizeType line = 0; line < this->m_stateFileEntries; line++) {
247 (this->m_stateFileData[line].entry.dir == entry.dir) and
248 (this->m_stateFileData[line].entry.record.getid() == entry.record.getid()) and
249 (this->m_stateFileData[line].entry.record.gettSec() == entry.record.gettSec()) and
250 (this->m_stateFileData[line].entry.record.gettSub() == entry.record.gettSub()) and
251 (this->m_stateFileData[line].entry.record.getpriority() == entry.record.getpriority())
254 entry.record.setstate(this->m_stateFileData[line].entry.record.getstate());
255 entry.record.setblocks(this->m_stateFileData[line].entry.record.getblocks());
257 this->m_stateFileData[line].visited =
true;
263 void DpCatalog::pruneAndWriteStateFile() {
276 this->m_stateFile.
toChar(),
290 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
293 (this->m_stateFileData[entry].used) and
294 (this->m_stateFileData[entry].visited)
297 entryBuffer.resetSer();
299 Fw::SerializeStatus serStat = entryBuffer.serialize(this->m_stateFileData[entry].entry.dir);
302 serStat = entryBuffer.serialize(this->m_stateFileData[entry].entry.record);
306 FwSizeType size = entryBuffer.getBuffLength();
308 stat = stateFile.
write(buffer, size);
320 void DpCatalog::appendFileState(
const DpStateEntry& entry) {
322 FW_ASSERT(entry.dir < static_cast<FwIndexType>(this->m_numDirectories),
323 static_cast<FwAssertArgType>(entry.dir),
324 static_cast<FwAssertArgType>(this->m_numDirectories)
341 BYTE buffer[
sizeof(entry.dir)+
sizeof(entry.record)];
344 entryBuffer.resetSer();
349 serStat = entryBuffer.serialize(entry.record);
353 FwSizeType size = entryBuffer.getBuffLength();
354 stat = stateFile.
write(buffer, size);
368 if (not this->checkInit()) {
374 if (0 == this->m_numDpSlots) {
380 if (this->m_xmitInProgress) {
386 this->resetStateFileData();
392 this->resetBinaryTree();
395 response = this->fillBinaryTree();
398 this->resetBinaryTree();
399 this->resetStateFileData();
404 this->pruneAndWriteStateFile();
424 for (
FwSizeType dir = 0; dir < this->m_numDirectories; dir++) {
428 U32 pendingFiles = 0;
429 U64 pendingDpBytes = 0;
430 U32 filesProcessed = 0;
436 this->m_directories[dir],
441 status =
dpDir.readDirectory(this->m_fileList, (this->m_numDpSlots - totalFiles), filesRead);
445 this->m_directories[dir],
453 filesRead <= this->m_numDpSlots - totalFiles,
454 static_cast<FwAssertArgType>(filesRead),
455 static_cast<FwAssertArgType>(this->m_numDpSlots - totalFiles));
463 this->m_fileList[
file].toChar(),
464 this->m_fileList[
file].length(),
475 this->m_directories[dir].toChar(),
476 this->m_fileList[
file].toChar()
499 stat = dpFile.
read(dpBuff, size);
528 entry.record.setid(container.
getId());
530 entry.record.setstate(container.
getState());
533 entry.record.setsize(static_cast<U64>(fileSize));
536 this->getFileState(entry);
539 bool insertedOk = this->insertEntry(entry);
540 if (not insertedOk) {
543 this->resetBinaryTree();
544 this->resetStateFileData();
550 pendingDpBytes += entry.record.getsize();
554 if (this->m_numDpRecords > this->m_numDpSlots) {
563 totalFiles += filesProcessed;
566 this->m_directories[dir],
567 static_cast<U32>(totalFiles),
574 if (totalFiles == this->m_numDpSlots) {
585 bool DpCatalog::insertEntry(DpStateEntry& entry) {
595 if (this->m_dpTree ==
nullptr) {
596 bool goodInsert = this->allocateNode(this->m_dpTree,entry);
597 if (not goodInsert) {
603 DpBtreeNode* node = this->m_dpTree;
604 for (
FwSizeType record = 0; record < this->m_numDpSlots; record++) {
605 CheckStat stat = CheckStat::CHECK_CONT;
607 if (entry.record.getpriority() == node->entry.record.getpriority()) {
609 if (entry.record.gettSec() == node->entry.record.gettSec()) {
611 stat = this->checkLeftRight(
612 entry.record.getid() < node->entry.record.getid(),
617 stat = this->checkLeftRight(
618 entry.record.gettSec() < node->entry.record.gettSec(),
624 stat = this->checkLeftRight(
625 entry.record.getpriority() < node->entry.record.getpriority(),
632 if (stat == CheckStat::CHECK_ERROR) {
634 }
else if (stat == CheckStat::CHECK_OK) {
642 this->m_numDpRecords++;
648 DpCatalog::CheckStat DpCatalog::checkLeftRight(
bool condition, DpBtreeNode* &node,
const DpStateEntry& newEntry) {
650 if (node->left ==
nullptr) {
651 bool allocated = this->allocateNode(node->left,newEntry);
653 return CheckStat::CHECK_ERROR;
655 return CheckStat::CHECK_OK;
658 return CheckStat::CHECK_CONT;
661 if (node->right ==
nullptr) {
662 bool allocated = this->allocateNode(node->right,newEntry);
664 return CheckStat::CHECK_ERROR;
666 return CheckStat::CHECK_OK;
669 return CheckStat::CHECK_CONT;
675 bool DpCatalog::allocateNode(DpBtreeNode* &newNode,
676 const DpStateEntry& newEntry) {
680 if (this->m_freeListHead ==
nullptr) {
685 newNode = this->m_freeListHead;
687 this->m_freeListHead = this->m_freeListHead->left;
690 newNode->left =
nullptr;
691 newNode->right =
nullptr;
692 newNode->entry = newEntry;
700 void DpCatalog::deleteEntry(DpStateEntry& entry) {
704 void DpCatalog::sendNextEntry() {
712 this->m_currentXmitNode = this->findNextTreeNode();
714 if (this->m_currentXmitNode ==
nullptr) {
716 this->m_xmitInProgress =
false;
718 if (this->m_xmitCmdWait) {
725 this->m_directories[this->m_currentXmitNode->entry.dir].toChar(),
726 this->m_currentXmitNode->entry.record.getid(),
727 this->m_currentXmitNode->entry.record.gettSec(),
728 this->m_currentXmitNode->entry.record.gettSub()
731 this->m_currXmitFileName,
732 static_cast<U32>(this->m_currentXmitNode->entry.record.getsize()),
733 this->m_currentXmitNode->entry.record.getpriority()
746 DpCatalog::DpBtreeNode* DpCatalog::findNextTreeNode() {
753 DpBtreeNode* found =
nullptr;
757 for (
FwSizeType record = 0; record < this->m_numDpRecords; record++) {
761 if (this->m_currentNode ==
nullptr) {
763 if (this->m_currStackEntry < 0) {
768 this->m_currentNode = this->m_traverseStack[this->m_currStackEntry--];
770 found = this->m_currentNode;
772 this->m_currentNode = this->m_currentNode->right;
773 if (found !=
nullptr) {
779 if (this->m_currentNode->left !=
nullptr) {
781 this->m_traverseStack[++this->m_currStackEntry] = this->m_currentNode;
782 this->m_currentNode = this->m_currentNode->left;
787 found = this->m_currentNode;
790 this->m_currentNode = this->m_currentNode->right;
792 if (found !=
nullptr) {
802 bool DpCatalog::checkInit() {
803 if (not this->m_initialized) {
807 else if (0 == this->m_numDpSlots) {
819 if ((this->m_allocator !=
nullptr) and (this->m_memPtr !=
nullptr)) {
820 this->m_allocator->
deallocate(this->m_allocatorId, this->m_memPtr);
843 this->m_xmitInProgress =
false;
852 this->appendFileState(this->m_currentXmitNode->entry);
854 this->m_xmitBytes += this->m_currentXmitNode->entry.record.getsize();
856 this->sendNextEntry();
874 BUILD_CATALOG_cmdHandler(
885 START_XMIT_CATALOG_cmdHandler(
899 this->m_xmitCmdWait =
false;
900 this->m_xmitOpCode = 0;
901 this->m_xmitCmdSeq = 0;
904 this->m_xmitCmdWait =
true;
905 this->m_xmitOpCode = opCode;
906 this->m_xmitCmdSeq =
cmdSeq;
915 if (not this->checkInit()) {
921 if (0 == this->m_numDpSlots) {
927 if (this->m_xmitInProgress) {
933 this->m_xmitBytes = 0;
942 this->resetTreeStack();
943 this->m_xmitInProgress =
true;
945 this->sendNextEntry();
950 void DpCatalog::resetTreeStack() {
953 this->m_currStackEntry = -1;
955 this->m_currentNode = this->m_dpTree;
959 STOP_XMIT_CATALOG_cmdHandler(
964 if (not this->m_xmitInProgress) {
974 CLEAR_CATALOG_cmdHandler(
void log_WARNING_HI_DpCatalogFull(Svc::DpRecord dp)
Serialization/Deserialization operation was successful.
A data product Container.
FwDpPriorityType getPriority() const
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
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.
virtual void * allocate(const FwEnumStoreType identifier, FwSizeType &size, bool &recoverable)=0
Allocate memory.
void log_WARNING_HI_NotInitialized() const
Log event NotInitialized.
static constexpr FwSizeType MIN_PACKET_SIZE
static const FwIndexType DP_MAX_DIRECTORIES
const char * toChar() const
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.
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Enum representing a command response.
void log_WARNING_HI_DpFileSendError(const Fw::StringBase &file, Svc::SendFileStatus stat)
Log event DpFileSendError.
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_FileOpenError(const Fw::StringBase &loc, I32 stat)
void log_WARNING_HI_NoDpMemory() const
Log event NoDpMemory.
void log_WARNING_HI_FileSizeError(const Fw::StringBase &file, I32 stat)
Svc::SendFileStatus::T getstatus() const
Get member status.
void log_WARNING_HI_FileReadError(const Fw::StringBase &file, I32 stat)
const char * toChar() 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
Svc::SendFileResponse fileOut_out(FwIndexType portNum, const Fw::StringBase &sourceFileName, const Fw::StringBase &destFileName, U32 offset, U32 length)
Invoke output port fileOut.
SizeType length() const
Get length of string.
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.
void log_ACTIVITY_HI_CatalogXmitCompleted(U64 bytes) const
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
Command successfully executed.
uint8_t U8
8-bit unsigned integer
DpCatalog(const char *const compName)
DpCatalog constructor.
~DpCatalog()
DpCatalog destructor.
static Status getFileSize(const char *path, FwSizeType &size)
Get the size of the file (in bytes) at the specified path.
Status read(U8 *buffer, FwSizeType &size)
read data from this file into supplied buffer bounded by size
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 pingOut_out(FwIndexType portNum, U32 key)
Invoke output port pingOut.
void log_WARNING_HI_CatalogFull(const Fw::StringBase &dir)
The size of the serial representation.
Operation was successful.
void log_ACTIVITY_LO_ProductComplete(const Fw::StringBase &file) const
PlatformIndexType FwIndexType
void log_WARNING_HI_FileHdrDesError(const Fw::StringBase &file, I32 stat)
Operation was successful.
Send file response struct.
RateGroupDivider component implementation.
Fw::SerializeStatus deserializeHeader()
Operation was successful.
virtual void deallocate(const FwEnumStoreType identifier, void *ptr)=0
Deallocate memory.
Don't wait for something.
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()