1 2 #ifndef _FILEITEM_H 3 #define _FILEITEM_H 4 5 #include <string> 6 7 #include "config.h" 8 #include "lockable.h" 9 #include "header.h" 10 #include <unordered_map> 11 12 namespace acng 13 { 14 15 class fileitem; 16 typedef std::shared_ptr<fileitem> tFileItemPtr; 17 typedef std::unordered_multimap<mstring, tFileItemPtr> tFiGlobMap; 18 19 //! Base class containing all required data and methods for communication with the download sources 20 class fileitem : public base_with_condition 21 { 22 public: 23 24 // Life cycle (process states) of a file description item 25 enum FiStatus : char 26 { 27 28 FIST_FRESH, FIST_INITED, FIST_DLPENDING, FIST_DLGOTHEAD, FIST_DLRECEIVING, 29 FIST_COMPLETE, 30 // error cases: downloader reports its error or last user told downloader to stop 31 FIST_DLERROR, 32 FIST_DLSTOP // assumed to not have any users left 33 }; 34 35 virtual ~fileitem(); 36 37 // initialize file item, return the status 38 virtual FiStatus Setup(bool bDynType); 39 40 virtual int GetFileFd(); 41 uint64_t GetTransferCount(); 42 // send helper like wrapper for sendfile. Just declare virtual here to make it better customizable later. 43 virtual ssize_t SendData(int confd, int filefd, off_t &nSendPos, size_t nMax2SendNow)=0; 44 45 // downloader instruments 46 //typedef extended_bool<bool, false> SuccessWithTransErrorFlag; 47 virtual bool DownloadStartedStoreHeader(const header & h, size_t hDataLen, 48 const char *pNextData, 49 bool bForcedRestart, bool &bDoCleanRestart) =0; 50 void IncDlRefCount(); 51 void DecDlRefCount(const mstring & sReasonStatusLine); 52 //virtual void SetFailureMode(const mstring & message, FiStatus fist=FIST_ERROR, 53 // bool bOnlyIfNoDlRunnuning=false); 54 55 /*! 56 * \return true IFF ok and caller might continue. False -> caller should abort. 57 */ 58 virtual bool StoreFileData(const char *data, unsigned int size)=0; 59 header const & GetHeaderUnlocked(); GetHeader()60 inline header GetHeader() { setLockGuard; return m_head; } 61 mstring GetHttpMsg(); 62 GetStatus()63 FiStatus GetStatus() { setLockGuard; return m_status; } GetStatusUnlocked(off_t & nGoodDataSize)64 FiStatus GetStatusUnlocked(off_t &nGoodDataSize) { nGoodDataSize = m_nSizeChecked; return m_status; } 65 void ResetCacheState(); 66 67 //! returns true if complete or DL not started yet but partial file is present and contains requested range and file contents is static 68 bool CheckUsableRange_unlocked(off_t nRangeLastByte); 69 70 // returns when the state changes to complete or error 71 FiStatus WaitForFinish(int *httpCode=nullptr); 72 73 bool SetupClean(bool bForce=false); 74 75 /// mark the item as complete as-is, assuming that sizeseen is correct 76 void SetupComplete(); 77 78 void UpdateHeadTimestamp(); 79 80 uint64_t m_nIncommingCount; 81 off_t m_nSizeSeen; 82 off_t m_nRangeLimit; 83 84 bool m_bCheckFreshness; 85 // those is only good for very special purposes [tm] 86 bool m_bHeadOnly; 87 88 protected: 89 bool m_bAllowStoreData; 90 fileitem(); 91 off_t m_nSizeChecked; 92 header m_head; 93 int m_filefd; 94 int m_nDlRefsCount; 95 int usercount; 96 FiStatus m_status; 97 mstring m_sPathRel; 98 time_t m_nTimeDlStarted, m_nTimeDlDone; Truncate2checkedSize()99 virtual int Truncate2checkedSize() {return 0;}; 100 101 private: 102 // helper data for global registration control. Access is synchronized by the global lock, 103 // not the internal lock here 104 tFiGlobMap::iterator m_globRef; 105 friend class fileItemMgmt; 106 }; 107 108 // dl item implementation with storage on disk 109 class fileitem_with_storage : public fileitem 110 { 111 public: fileitem_with_storage(cmstring & s)112 inline fileitem_with_storage(cmstring &s) {m_sPathRel=s;}; fileitem_with_storage(cmstring & s,int nUsers)113 inline fileitem_with_storage(cmstring &s, int nUsers) {m_sPathRel=s; usercount=nUsers; }; 114 virtual ~fileitem_with_storage(); 115 int Truncate2checkedSize() override; 116 // send helper like wrapper for sendfile. Just declare virtual here to make it better customizable later. 117 virtual ssize_t SendData(int confd, int filefd, off_t &nSendPos, size_t nMax2SendNow) override; 118 virtual bool DownloadStartedStoreHeader(const header & h, size_t hDataLen, 119 const char *pNextData, 120 bool bForcedRestart, bool&) override; 121 virtual bool StoreFileData(const char *data, unsigned int size) override; 122 NormalizePath(cmstring & sPathRaw)123 inline static mstring NormalizePath(cmstring &sPathRaw) 124 { 125 return cfg::stupidfs ? DosEscape(sPathRaw) : sPathRaw; 126 } 127 protected: 128 int MoveRelease2Sidestore(); 129 }; 130 131 #ifndef MINIBUILD 132 133 // auto_ptr like object that "owns" a fileitem while it's registered in the global 134 // access table. Might cause item's deletion when destroyed 135 class fileItemMgmt 136 { 137 public: 138 139 // public constructor wrapper, get a unique object from the map or a new one 140 bool PrepareRegisteredFileItemWithStorage(cmstring &sPathUnescaped, bool bConsiderAltStore); 141 142 // related to GetRegisteredFileItem but used for registration of custom file item 143 // implementations created elsewhere (which still need to obey regular work flow) 144 bool RegisterFileItem(tFileItemPtr spCustomFileItem); 145 146 // deletes global registration and replaces m_ptr with another copy 147 void RegisterFileitemLocalOnly(fileitem* replacement); 148 149 //! @return: true iff there is still something in the pool for later cleaning 150 static time_t BackgroundCleanup(); 151 152 static void dump_status(); 153 154 // when copied around, invalidates the original reference 155 ~fileItemMgmt(); fileItemMgmt()156 inline fileItemMgmt() {} getFiPtr()157 inline tFileItemPtr getFiPtr() {return m_ptr;} 158 inline operator bool() const {return (bool) m_ptr;} 159 160 tFileItemPtr m_ptr; 161 162 private: 163 void Unreg(); 164 165 fileItemMgmt(const fileItemMgmt &src); 166 fileItemMgmt& operator=(const fileItemMgmt &src); 167 168 inline fileitem* operator->() const {return m_ptr.get();} 169 170 }; 171 #else 172 #define fileItemMgmt void 173 #endif // not MINIBUILD 174 175 } 176 #endif 177