23 DpCatalog(
const char*
const compName) :
27 m_freeListHead(nullptr),
28 m_freeListFoot(nullptr),
29 m_traverseStack(nullptr),
30 m_currentNode(nullptr),
31 m_currentXmitNode(nullptr),
35 m_stateFileData(nullptr),
36 m_stateFileEntries(0),
41 m_xmitInProgress(false),
64 this->m_stateFile = stateFile;
73 static const FwSizeType slotSize =
sizeof(DpBtreeNode) +
sizeof(DpBtreeNode**) +
sizeof(DpDstateFileEntry);
77 this->m_memPtr = allocator.
allocate(memId, this->m_memSize, notUsed);
100 (this->m_memSize >=
sizeof(DpBtreeNode)) and
101 (this->m_memPtr !=
nullptr)
104 this->m_numDpSlots = this->m_memSize / slotSize;
105 this->resetBinaryTree();
107 this->m_traverseStack =
reinterpret_cast<DpBtreeNode**
>(&this->m_freeListHead[this->m_numDpSlots]);
108 this->resetTreeStack();
110 this->m_stateFileData =
reinterpret_cast<DpDstateFileEntry*
>(&this->m_traverseStack[this->m_numDpSlots]);
115 this->m_numDpSlots = 0;
119 for (
FwSizeType dir = 0; dir < numDirs; dir++) {
120 this->m_directories[dir] = directories[dir];
122 this->m_numDirectories = numDirs;
125 this->m_allocator = &allocator;
126 this->m_allocatorId = memId;
127 this->m_initialized =
true;
130 void DpCatalog::resetBinaryTree() {
133 this->m_freeListHead =
static_cast<DpBtreeNode*
>(this->m_memPtr);
134 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
136 (void)
new(&this->m_freeListHead[slot]) DpBtreeNode();
137 this->m_freeListHead[slot].left =
nullptr;
138 this->m_freeListHead[slot].right =
nullptr;
141 this->m_freeListHead[slot-1].left = &this->m_freeListHead[slot];
145 this->m_freeListFoot = &this->m_freeListHead[this->m_numDpSlots - 1];
147 this->m_dpTree =
nullptr;
149 this->m_numDpRecords = 0;
152 void DpCatalog::resetStateFileData() {
154 for (
FwSizeType slot = 0; slot < this->m_numDpSlots; slot++) {
155 this->m_stateFileData[slot].used =
false;
156 this->m_stateFileData[slot].visited =
false;
157 (void)
new(&this->m_stateFileData[slot].entry.record) DpRecord();
159 this->m_stateFileEntries = 0;
167 if (this->m_stateFile.
length() == 0) {
186 this->m_stateFileEntries = 0;
189 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
193 stat = stateFile.
read(buffer, size);
207 if (size !=
sizeof(buffer)) {
214 entryBuffer.resetDeser();
220 Fw::SerializeStatus status = entryBuffer.deserialize(this->m_stateFileData[entry].entry.dir);
222 status = entryBuffer.deserialize(this->m_stateFileData[entry].entry.record);
224 this->m_stateFileData[entry].used =
true;
225 this->m_stateFileData[entry].visited =
false;
229 this->m_stateFileEntries++;
235 void DpCatalog::getFileState(DpStateEntry& entry) {
238 for (
FwSizeType line = 0; line < this->m_stateFileEntries; line++) {
241 (this->m_stateFileData[line].entry.dir == entry.dir) and
242 (this->m_stateFileData[line].entry.record.getid() == entry.record.getid()) and
243 (this->m_stateFileData[line].entry.record.gettSec() == entry.record.gettSec()) and
244 (this->m_stateFileData[line].entry.record.gettSub() == entry.record.gettSub()) and
245 (this->m_stateFileData[line].entry.record.getpriority() == entry.record.getpriority())
248 entry.record.setstate(this->m_stateFileData[line].entry.record.getstate());
249 entry.record.setblocks(this->m_stateFileData[line].entry.record.getblocks());
251 this->m_stateFileData[line].visited =
true;
257 void DpCatalog::pruneAndWriteStateFile() {
270 this->m_stateFile.
toChar(),
284 for (
FwSizeType entry = 0; entry < this->m_numDpSlots; entry++) {
287 (this->m_stateFileData[entry].used) and
288 (this->m_stateFileData[entry].visited)
291 entryBuffer.resetSer();
293 entryBuffer.serialize(this->m_stateFileData[entry].entry.dir);
294 entryBuffer.serialize(this->m_stateFileData[entry].entry.record);
297 stat = stateFile.
write(buffer, size);
309 void DpCatalog::appendFileState(
const DpStateEntry& entry) {
329 entryBuffer.resetSer();
331 entryBuffer.serialize(entry.dir);
332 entryBuffer.serialize(entry.record);
335 stat = stateFile.
write(buffer, size);
349 if (not this->checkInit()) {
355 if (0 == this->m_numDpSlots) {
361 if (this->m_xmitInProgress) {
367 this->resetStateFileData();
373 this->resetBinaryTree();
376 response = this->fillBinaryTree();
382 this->pruneAndWriteStateFile();
402 for (
FwSizeType dir = 0; dir < this->m_numDirectories; dir++) {
406 U32 pendingFiles = 0;
407 U64 pendingDpBytes = 0;
408 U32 filesProcessed = 0;
414 this->m_directories[dir],
419 status = dpDir.
readDirectory(this->m_fileList, (this->m_numDpSlots - totalFiles), filesRead);
423 this->m_directories[dir],
431 filesRead <= this->m_numDpSlots - totalFiles,
441 this->m_fileList[file].toChar(),
442 this->m_fileList[file].length(),
453 this->m_directories[dir].toChar(),
454 this->m_fileList[file].toChar()
477 stat = dpFile.
read(dpBuff, size);
506 entry.record.setid(container.
getId());
508 entry.record.setstate(container.
getState());
511 entry.record.setsize(
static_cast<U64>(fileSize));
514 this->getFileState(entry);
517 if (not this->insertEntry(entry)) {
524 pendingDpBytes += entry.record.getsize();
528 if (this->m_numDpRecords > this->m_numDpSlots) {
537 totalFiles += filesProcessed;
540 this->m_directories[dir],
541 static_cast<U32
>(totalFiles),
548 if (totalFiles == this->m_numDpSlots) {
559 bool DpCatalog::insertEntry(DpStateEntry& entry) {
569 if (this->m_dpTree ==
nullptr) {
570 this->allocateNode(this->m_dpTree,entry);
574 DpBtreeNode* node = this->m_dpTree;
575 for (
FwSizeType record = 0; record < this->m_numDpSlots; record++) {
576 CheckStat stat = CheckStat::CHECK_CONT;
578 if (entry.record.getpriority() == node->entry.record.getpriority()) {
580 if (entry.record.gettSec() == node->entry.record.gettSec()) {
582 stat = this->checkLeftRight(
583 entry.record.getid() < node->entry.record.getid(),
588 stat = this->checkLeftRight(
589 entry.record.gettSec() < node->entry.record.gettSec(),
595 stat = this->checkLeftRight(
596 entry.record.getpriority() < node->entry.record.getpriority(),
603 if (stat == CheckStat::CHECK_ERROR) {
605 }
else if (stat == CheckStat::CHECK_OK) {
613 this->m_numDpRecords++;
619 DpCatalog::CheckStat DpCatalog::checkLeftRight(
bool condition, DpBtreeNode* &node,
const DpStateEntry& newEntry) {
621 if (node->left ==
nullptr) {
622 if (!this->allocateNode(node->left,newEntry)) {
623 return CheckStat::CHECK_ERROR;
625 return CheckStat::CHECK_OK;
628 return CheckStat::CHECK_CONT;
631 if (node->right ==
nullptr) {
632 if (!this->allocateNode(node->right,newEntry)) {
633 return CheckStat::CHECK_ERROR;
635 return CheckStat::CHECK_OK;
638 return CheckStat::CHECK_CONT;
644 bool DpCatalog::allocateNode(DpBtreeNode* &newNode,
645 const DpStateEntry& newEntry) {
649 if (this->m_freeListHead ==
nullptr) {
654 newNode = this->m_freeListHead;
656 this->m_freeListHead = this->m_freeListHead->left;
659 newNode->left =
nullptr;
660 newNode->right =
nullptr;
661 newNode->entry = newEntry;
669 void DpCatalog::deleteEntry(DpStateEntry& entry) {
673 void DpCatalog::sendNextEntry() {
681 this->m_currentXmitNode = this->findNextTreeNode();
683 if (this->m_currentXmitNode ==
nullptr) {
685 this->m_xmitInProgress =
false;
687 if (this->m_xmitCmdWait) {
694 this->m_directories[this->m_currentXmitNode->entry.dir].toChar(),
695 this->m_currentXmitNode->entry.record.getid(),
696 this->m_currentXmitNode->entry.record.gettSec(),
697 this->m_currentXmitNode->entry.record.gettSub()
700 this->m_currXmitFileName,
701 static_cast<U32
>(this->m_currentXmitNode->entry.record.getsize()),
702 this->m_currentXmitNode->entry.record.getpriority()
704 this->
fileOut_out(0, this->m_currXmitFileName, this->m_currXmitFileName, 0, 0);
709 DpCatalog::DpBtreeNode* DpCatalog::findNextTreeNode() {
716 DpBtreeNode* found =
nullptr;
720 for (
FwSizeType record = 0; record < this->m_numDpRecords; record++) {
724 if (this->m_currentNode ==
nullptr) {
726 if (this->m_currStackEntry < 0) {
731 this->m_currentNode = this->m_traverseStack[this->m_currStackEntry--];
733 found = this->m_currentNode;
735 this->m_currentNode = this->m_currentNode->right;
736 if (found !=
nullptr) {
742 if (this->m_currentNode->left !=
nullptr) {
744 this->m_traverseStack[++this->m_currStackEntry] = this->m_currentNode;
745 this->m_currentNode = this->m_currentNode->left;
750 found = this->m_currentNode;
753 this->m_currentNode = this->m_currentNode->right;
755 if (found !=
nullptr) {
765 bool DpCatalog::checkInit() {
766 if (not this->m_initialized) {
770 else if (0 == this->m_numDpSlots) {
782 if ((this->m_allocator !=
nullptr) and (this->m_memPtr !=
nullptr)) {
783 this->m_allocator->
deallocate(this->m_allocatorId, this->m_memPtr);
805 this->log_WARNING_HI_StateFileXmitError(this->m_currXmitFileName,resp.
getstatus());
806 this->m_xmitInProgress =
false;
810 this->log_ACTIVITY_LO_ProductComplete(this->m_currXmitFileName);
815 this->appendFileState(this->m_currentXmitNode->entry);
817 this->m_xmitBytes += this->m_currentXmitNode->entry.record.getsize();
819 this->sendNextEntry();
829 this->pingOut_out(0, key);
837 BUILD_CATALOG_cmdHandler(
843 this->cmdResponse_out(opCode, cmdSeq,this->doCatalogBuild());
848 START_XMIT_CATALOG_cmdHandler(
858 this->cmdResponse_out(opCode, cmdSeq, resp);
861 this->cmdResponse_out(opCode, cmdSeq, resp);
862 this->m_xmitCmdWait =
false;
863 this->m_xmitOpCode = 0;
864 this->m_xmitCmdSeq = 0;
867 this->m_xmitCmdWait =
true;
868 this->m_xmitOpCode = opCode;
869 this->m_xmitCmdSeq = cmdSeq;
878 if (not this->checkInit()) {
884 if (0 == this->m_numDpSlots) {
890 if (this->m_xmitInProgress) {
896 this->m_xmitBytes = 0;
905 this->resetTreeStack();
906 this->m_xmitInProgress =
true;
908 this->sendNextEntry();
913 void DpCatalog::resetTreeStack() {
916 this->m_currStackEntry = -1;
918 this->m_currentNode = this->m_dpTree;
922 STOP_XMIT_CATALOG_cmdHandler(
927 if (not this->m_xmitInProgress) {
928 this->log_WARNING_LO_XmitNotActive();
937 CLEAR_CATALOG_cmdHandler(
PlatformIntType NATIVE_INT_TYPE
uint8_t U8
8-bit unsigned integer
PlatformUIntType NATIVE_UINT_TYPE
constexpr const char * DP_FILENAME_FORMAT
PlatformAssertArgType FwAssertArgType
PlatformUIntType FwNativeUIntType
PlatformSignedSizeType FwSignedSizeType
PlatformSizeType FwSizeType
PlatformIndexType FwIndexType
C++-compatible configuration header for fprime configuration.
Enum representing a command response.
@ EXECUTION_ERROR
Command had execution error.
@ OK
Command successfully executed.
A data product Container.
Fw::Time getTimeTag() const
static constexpr FwSizeType MIN_PACKET_SIZE
FwDpPriorityType getPriority() const
Fw::DpState getState() const
Get the product state.
Fw::SerializeStatus deserializeHeader()
void setBuffer(const Buffer &buffer)
Set the packet buffer.
@ UNTRANSMITTED
The untransmitted state.
@ TRANSMITTED
The transmitted state.
External serialize buffer with no copy semantics.
const char * toChar() const
virtual void * allocate(const NATIVE_UINT_TYPE identifier, NATIVE_UINT_TYPE &size, bool &recoverable)=0
Allocate memory.
virtual void deallocate(const NATIVE_UINT_TYPE identifier, void *ptr)=0
Deallocate memory.
NATIVE_UINT_TYPE SizeType
void format(const CHAR *formatString,...)
write formatted string to buffer
SizeType length() const
Get length of string.
const char * toChar() const
Wait or don't wait for something.
Status open(const char *path, OpenMode mode) override
Open or create a directory.
Status readDirectory(Fw::String filenameArray[], const FwSizeType arraySize, FwSizeType &filenameCount)
Read the contents of the directory and store filenames in filenameArray of size arraySize.
@ READ
Error if directory doesn't exist.
@ OP_OK
Operation was successful.
Status read(U8 *buffer, FwSignedSizeType &size)
read data from this file into supplied buffer bounded by size
void close() override
close the file, if not opened then do nothing
Os::FileInterface::Status open(const char *path, Mode mode)
open file with supplied path and mode
Status write(const U8 *buffer, FwSignedSizeType &size)
write data to this file from the supplied buffer bounded by size
@ OVERWRITE
Overwrite file when it exists and creation was requested.
@ BAD_SIZE
Invalid size parameter.
@ OP_OK
Operation was successful.
@ OPEN_CREATE
Open file for writing and truncates file if it exists, ie same flags as creat()
@ OPEN_READ
Open file for reading.
@ OPEN_APPEND
Open file for appending.
static Status getFileSize(const char *path, FwSignedSizeType &size)
Get the size of the file (in bytes) at the specified path.
@ OP_OK
Operation was successful.
Auto-generated base for DpCatalog component.
Svc::SendFileResponse fileOut_out(FwIndexType portNum, const Fw::StringBase &sourceFileName, const Fw::StringBase &destFileName, U32 offset, U32 length)
Invoke output port fileOut.
void log_WARNING_LO_DpXmitInProgress()
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
void log_ACTIVITY_HI_CatalogXmitCompleted(U64 bytes) const
void log_WARNING_HI_FileOpenError(const Fw::StringBase &loc, I32 stat)
void log_WARNING_HI_DpInsertError(Svc::DpRecord dp)
void log_WARNING_HI_StateFileWriteError(const Fw::StringBase &file, I32 stat) const
Log event StateFileWriteError.
void log_WARNING_HI_DirectoryOpenError(const Fw::StringBase &loc, I32 stat) const
void log_WARNING_HI_ComponentNotInitialized()
void log_WARNING_HI_FileReadError(const Fw::StringBase &file, I32 stat)
void log_WARNING_HI_ComponentNoMemory()
void log_WARNING_HI_StateFileTruncated(const Fw::StringBase &file, I32 offset, I32 size) const
Log event StateFileTruncated.
void log_WARNING_HI_FileSizeError(const Fw::StringBase &file, I32 stat)
void log_WARNING_HI_CatalogFull(const Fw::StringBase &dir)
void log_WARNING_HI_StateFileOpenError(const Fw::StringBase &file, I32 stat) const
Log event StateFileOpenError.
void log_WARNING_HI_DpCatalogFull(Svc::DpRecord dp)
void log_ACTIVITY_LO_SendingProduct(const Fw::StringBase &file, U32 bytes, U32 prio) const
void log_ACTIVITY_LO_ProcessingDirectory(const Fw::StringBase &directory) const
void log_WARNING_HI_FileHdrDesError(const Fw::StringBase &file, I32 stat)
void log_ACTIVITY_HI_ProcessingDirectoryComplete(const Fw::StringBase &loc, U32 total, U32 pending, U64 pending_bytes) const
void log_WARNING_HI_NotInitialized() const
Log event NotInitialized.
void log_WARNING_LO_NoStateFileSpecified() const
Log event NoStateFileSpecified.
void log_WARNING_HI_StateFileReadError(const Fw::StringBase &file, I32 stat, I32 offset) const
Log event StateFileReadError.
void log_ACTIVITY_LO_ProcessingFile(const Fw::StringBase &file) const
void log_WARNING_HI_NoDpMemory() const
Log event NoDpMemory.
void log_ACTIVITY_HI_CatalogBuildComplete() const
void configure(Fw::FileNameString directories[DP_MAX_DIRECTORIES], FwSizeType numDirs, Fw::FileNameString &stateFile, NATIVE_UINT_TYPE memId, Fw::MemAllocator &allocator)
Configure the DpCatalog.
@ SERIALIZED_SIZE
The size of the serial representation.
Send file response struct.
Svc::SendFileStatus::T getstatus() const
Get member status.
FwSizeType string_length(const CHAR *source, FwSizeType buffer_size)
get the length of the source string
FwSignedSizeType substring_find(const CHAR *source_string, FwSizeType source_size, const CHAR *sub_string, FwSizeType sub_size)
find the first occurrence of a substring
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
static const FwSizeType DP_MAX_FILES
static const FwSizeType DP_MAX_DIRECTORIES