| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title DpCatalog.hpp | ||
| 3 | // \author tcanham | ||
| 4 | // \brief hpp file for DpCatalog component implementation class | ||
| 5 | // ====================================================================== | ||
| 6 | |||
| 7 | #ifndef Svc_DpCatalog_HPP | ||
| 8 | #define Svc_DpCatalog_HPP | ||
| 9 | |||
| 10 | #include "Svc/DpCatalog/DpCatalogComponentAc.hpp" | ||
| 11 | #include "Svc/DpCatalog/DpRecordSerializableAc.hpp" | ||
| 12 | |||
| 13 | #include <Fw/DataStructures/ExternalArray.hpp> | ||
| 14 | #include <Fw/DataStructures/RedBlackTreeSet.hpp> | ||
| 15 | #include <Fw/Deprecate.hpp> | ||
| 16 | #include <Fw/Types/MemAllocator.hpp> | ||
| 17 | |||
| 18 | #include <Fw/Types/FileNameString.hpp> | ||
| 19 | #include <config/DpCatalogCfg.hpp> | ||
| 20 | #include <config/DpCfg.hpp> | ||
| 21 | |||
| 22 | #define DIRECTORY_DELIMITER "/" | ||
| 23 | |||
| 24 | namespace Svc { | ||
| 25 | |||
| 26 | class DpCatalog final : public DpCatalogComponentBase { | ||
| 27 | friend class DpCatalogTester; | ||
| 28 | |||
| 29 | public: | ||
| 30 | // ---------------------------------------------------------------------- | ||
| 31 | // Component construction and destruction | ||
| 32 | // ---------------------------------------------------------------------- | ||
| 33 | |||
| 34 | /// @brief DpCatalog constructor | ||
| 35 | /// @param compName component name | ||
| 36 | DpCatalog(const char* const compName //!< The component name | ||
| 37 | ); | ||
| 38 | |||
| 39 | /// @brief DpCatalog destructor | ||
| 40 |
3/4✓ Branch 16 taken 526 times.
✗ Branch 17 not taken.
✓ Branch 23 taken 1052 times.
✓ Branch 24 taken 526 times.
|
3156 | ~DpCatalog() = default; |
| 41 | |||
| 42 | /// @brief Configure the DpCatalog | ||
| 43 | /// @param directories array of directories to scan; at most DP_MAX_DIRECTORIES entries | ||
| 44 | /// @param stateFile file to store transmit state. Provide a zero-length string if no state tracking | ||
| 45 | /// @param memId memory ID for allocator | ||
| 46 | /// @param allocator Allocator to supply memory for catalog. | ||
| 47 | /// Instance must survive for shutdown to use for reclaiming memory | ||
| 48 | void configure(const Fw::ExternalArray<Fw::FileNameString>& directories, | ||
| 49 | Fw::FileNameString& stateFile, | ||
| 50 | FwEnumStoreType memId, | ||
| 51 | Fw::MemAllocator& allocator); | ||
| 52 | |||
| 53 | /// @brief Configure the DpCatalog | ||
| 54 | /// @param directories list of directories to scan | ||
| 55 | /// @param numDirs number of supplied directories | ||
| 56 | /// @param stateFile file to store transmit state. Provide a zero-length string if no state tracking | ||
| 57 | /// @param memId memory ID for allocator | ||
| 58 | /// @param allocator Allocator to supply memory for catalog. | ||
| 59 | /// Instance must survive for shutdown to use for reclaiming memory | ||
| 60 | DEPRECATED(void configure(Fw::FileNameString directories[DP_MAX_DIRECTORIES], | ||
| 61 | FwSizeType numDirs, | ||
| 62 | Fw::FileNameString& stateFile, | ||
| 63 | FwEnumStoreType memId, | ||
| 64 | Fw::MemAllocator& allocator), | ||
| 65 | "Use configure(const Fw::ExternalArray<Fw::FileNameString>& directories, ...) instead"); | ||
| 66 | |||
| 67 | // @brief clean up component. | ||
| 68 | // Deallocates memory. | ||
| 69 | void shutdown(); | ||
| 70 | |||
| 71 | private: | ||
| 72 | // ---------------------------------------------------------------------- | ||
| 73 | // Handler implementations for user-defined typed input ports | ||
| 74 | // ---------------------------------------------------------------------- | ||
| 75 | |||
| 76 | //! Handler implementation for fileDone | ||
| 77 | //! | ||
| 78 | //! File Downlink send complete port | ||
| 79 | void fileDone_handler(FwIndexType portNum, //!< The port number | ||
| 80 | const Svc::SendFileResponse& resp) override; | ||
| 81 | |||
| 82 | //! Handler implementation for pingIn | ||
| 83 | //! | ||
| 84 | //! Ping input port | ||
| 85 | void pingIn_handler(FwIndexType portNum, //!< The port number | ||
| 86 | U32 key //!< Value to return to pinger | ||
| 87 | ) override; | ||
| 88 | |||
| 89 | //! Handler implementation for addToCat | ||
| 90 | //! | ||
| 91 | //! DP Writer Add File to Cat | ||
| 92 | void addToCat_handler(FwIndexType portNum, //!< The port number | ||
| 93 | const Fw::StringBase& fileName, //!< The file name | ||
| 94 | FwDpPriorityType priority, //!< The priority | ||
| 95 | FwSizeType size //!< The file size | ||
| 96 | ) override; | ||
| 97 | |||
| 98 | private: | ||
| 99 | // ---------------------------------------------------------------------- | ||
| 100 | // Handler implementations for commands | ||
| 101 | // ---------------------------------------------------------------------- | ||
| 102 | |||
| 103 | //! Handler implementation for command BUILD_CATALOG | ||
| 104 | //! | ||
| 105 | //! Build catalog from data product directory | ||
| 106 | void BUILD_CATALOG_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 107 | U32 cmdSeq //!< The command sequence number | ||
| 108 | ) override; | ||
| 109 | |||
| 110 | //! Handler implementation for command START_XMIT_CATALOG | ||
| 111 | //! | ||
| 112 | //! Start transmitting catalog | ||
| 113 | void START_XMIT_CATALOG_cmdHandler( | ||
| 114 | FwOpcodeType opCode, //!< The opcode | ||
| 115 | U32 cmdSeq, //!< The command sequence number | ||
| 116 | const Fw::Wait& wait, //!< have START_XMIT command wait for catalog to complete transmitting | ||
| 117 | bool remainActive //!< should the catalog resume transmission when Dps are added at runtime | ||
| 118 | ) override; | ||
| 119 | |||
| 120 | //! Handler implementation for command STOP_XMIT_CATALOG | ||
| 121 | //! | ||
| 122 | //! Stop transmitting catalog | ||
| 123 | void STOP_XMIT_CATALOG_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 124 | U32 cmdSeq //!< The command sequence number | ||
| 125 | ) override; | ||
| 126 | |||
| 127 | //! Handler implementation for command CLEAR_CATALOG | ||
| 128 | //! | ||
| 129 | //! clear existing catalog | ||
| 130 | void CLEAR_CATALOG_cmdHandler(FwOpcodeType opCode, //!< The opcode | ||
| 131 | U32 cmdSeq //!< The command sequence number | ||
| 132 | ) override; | ||
| 133 | |||
| 134 | // ---------------------------------- | ||
| 135 | // Private data structures | ||
| 136 | // ---------------------------------- | ||
| 137 | |||
| 138 | struct DpStateEntry { | ||
| 139 | friend class DpCatalogTester; | ||
| 140 | FwIndexType dir; //!< index to m_directories entry that has directory name where DP exists | ||
| 141 | DpRecord record; //!< data product metadata | ||
| 142 | |||
| 143 | /// @brief insert an entry into the sorted list; if it exists, update the metadata | ||
| 144 | /// @param left an entry to compare | ||
| 145 | /// @param right other entry to compare | ||
| 146 | /// @return -1 if left is higher priority, 0 if equal, and 1 if right is higher priority | ||
| 147 | static I8 compareEntries(const DpStateEntry& left, const DpStateEntry& right); | ||
| 148 | |||
| 149 | bool operator==(const DpStateEntry& other) const; | ||
| 150 | bool operator!=(const DpStateEntry& other) const; | ||
| 151 | bool operator>(const DpStateEntry& other) const; | ||
| 152 | bool operator<(const DpStateEntry& other) const; | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct DpDstateFileEntry { | ||
| 156 | bool used; //!< if the entry is used | ||
| 157 | bool visited; //!< used for state file state; indicates that the entry was found in the search of current data | ||
| 158 | //!< products | ||
| 159 | DpStateEntry entry; //!< state entry from file | ||
| 160 | }; | ||
| 161 | |||
| 162 | // ---------------------------------- | ||
| 163 | // Private helpers | ||
| 164 | // ---------------------------------- | ||
| 165 | |||
| 166 | //! Status of a processFile() call | ||
| 167 | enum class ProcessFileStatus { | ||
| 168 | SUCCESS, //!< file added to the catalog | ||
| 169 | FAILED, //!< file could not be processed; continue with the next file | ||
| 170 | QUIT //!< catalog is full; stop processing files | ||
| 171 | }; | ||
| 172 | |||
| 173 | /// @brief determine in which managed directory a file resides | ||
| 174 | /// @param fullFile full path to file to be processed | ||
| 175 | /// @return directory index in m_directories; DP_MAX_DIRECTORIES if not in a managed dir | ||
| 176 | FwSizeType determineDirectory(const Fw::String& fullFile); | ||
| 177 | |||
| 178 | /// @brief add entry to sorted list and state file; called on each file in it & upon addToCat | ||
| 179 | /// @param fullFile full path to file to be processed | ||
| 180 | /// @param dir directory index in m_directories | ||
| 181 | /// @return QUIT to stop processing, FAILED for failure but continue, SUCCESS for success | ||
| 182 | ProcessFileStatus processFile(const Fw::String& fullFile, FwSizeType dir); | ||
| 183 | |||
| 184 | /// @brief insert an entry into the sorted catalog; if it exists, update the metadata | ||
| 185 | /// @param entry new entry | ||
| 186 | /// @return true if inserted successfully, false if catalog is full | ||
| 187 | bool insertEntry(DpStateEntry& entry); | ||
| 188 | |||
| 189 | /// @brief reset the catalog | ||
| 190 | void resetCatalog(); | ||
| 191 | |||
| 192 | /// #brief fill the binary tree from DP files | ||
| 193 | Fw::CmdResponse fillBinaryTree(); | ||
| 194 | |||
| 195 | /// @brief reset the state file data | ||
| 196 | void resetStateFileData(); | ||
| 197 | |||
| 198 | /// @brief get file state from the stored state file | ||
| 199 | /// @param entry entry to update from file state | ||
| 200 | void getFileState(DpStateEntry& entry); | ||
| 201 | |||
| 202 | /// @brief prune the state file data and write the remaining entries back | ||
| 203 | void pruneAndWriteStateFile(); | ||
| 204 | |||
| 205 | /// @brief load state data from file | ||
| 206 | Fw::CmdResponse loadStateFile(); | ||
| 207 | |||
| 208 | /// @brief get file state from the stored state file | ||
| 209 | /// @param entry entry to add to state file | ||
| 210 | void appendFileState(const DpStateEntry& entry); | ||
| 211 | |||
| 212 | /// @brief send the next entry to file downlink | ||
| 213 | void sendNextEntry(); | ||
| 214 | |||
| 215 | /// @brief find the next entry in the catalog using iterator | ||
| 216 | /// @param entry entry to return | ||
| 217 | /// @return true if an entry was found, false if no more entries | ||
| 218 | bool findNextEntry(DpStateEntry& entry); | ||
| 219 | |||
| 220 | /// @brief check to see if component successfully initialized | ||
| 221 | /// @return bool if it was initialized | ||
| 222 | bool checkInit(); | ||
| 223 | |||
| 224 | /// @brief build catalog. Shared between command and port | ||
| 225 | /// @return command response for pass/fail | ||
| 226 | Fw::CmdResponse doCatalogBuild(); | ||
| 227 | |||
| 228 | /// @brief start transmitting catalog. Shared between command and port | ||
| 229 | /// @return command response for pass/fail | ||
| 230 | Fw::CmdResponse doCatalogXmit(); | ||
| 231 | |||
| 232 | /// @brief send a cmdResponse to the start xmit cmd if user waited | ||
| 233 | /// @param response the command response for pass/fail | ||
| 234 | void dispatchWaitedResponse(Fw::CmdResponse response); | ||
| 235 | |||
| 236 | // ---------------------------------- | ||
| 237 | // Private data | ||
| 238 | // ---------------------------------- | ||
| 239 | bool m_initialized = false; //!< set when the component has been initialized | ||
| 240 | |||
| 241 | Fw::RedBlackTreeSet<DpStateEntry, DP_MAX_FILES> m_dpCatalog; //!< The sorted catalog of DPs | ||
| 242 | DpStateEntry m_currentXmitEntry; //!< Entry currently being transmitted | ||
| 243 | bool m_hasCurrentXmit = false; //!< Whether m_currentXmitEntry is valid | ||
| 244 | |||
| 245 | FwSizeType m_numDpSlots = 0; //!< Stores the available number of record slots. | ||
| 246 | |||
| 247 | Fw::FileNameString m_directories[DP_MAX_DIRECTORIES]; //!< List of supplied DP directories | ||
| 248 | FwSizeType m_numDirectories = 0; //!< number of supplied directories | ||
| 249 | |||
| 250 | Fw::FileNameString m_stateFile; //!< file to store transmit state | ||
| 251 | DpDstateFileEntry* m_stateFileData = nullptr; //!< DP state loaded from file | ||
| 252 | FwSizeType m_stateFileEntries = 0; //!< size of state file data | ||
| 253 | |||
| 254 | FwSizeType m_memSize = 0; //!< size of allocated buffer | ||
| 255 | void* m_memPtr = nullptr; //!< stored for shutdown | ||
| 256 | FwEnumStoreType m_allocatorId = 0; //!< stored for shutdown | ||
| 257 | Fw::MemAllocator* m_allocator = nullptr; //!< stored for shutdown | ||
| 258 | |||
| 259 | bool m_catalogBuilt = false; //!< catalog build is complete (can add DPs at runtime) | ||
| 260 | bool m_xmitInProgress = false; //!< set if DP files are in the process of being sent | ||
| 261 | Fw::FileNameString m_currXmitFileName; //!< current file being transmitted | ||
| 262 | bool m_xmitCmdWait = false; //!< true if waiting for transmission complete to complete xmit command | ||
| 263 | U64 m_xmitBytes = 0; //!< bytes transmitted for downlink session | ||
| 264 | FwOpcodeType m_xmitOpCode = 0; //!< stored xmit command opcode | ||
| 265 | U32 m_xmitCmdSeq = 0; //!< stored command sequence id | ||
| 266 | |||
| 267 | U32 m_pendingFiles = 0; //!< Pending Files to Transmit | ||
| 268 | U64 m_pendingDpBytes = 0; //!< Pending Bytes to Transmit | ||
| 269 | |||
| 270 | bool m_remainActive = false; //!< Does the DpCat resume transmission when | ||
| 271 | //!< a runtime Dp is received after | ||
| 272 | //!< the full catalog is sent | ||
| 273 | }; | ||
| 274 | |||
| 275 | } // namespace Svc | ||
| 276 | |||
| 277 | #endif | ||
| 278 |