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