1 /*
2  * Copyright (C) 2001-2009 Jacek Sieka, arnetheduck on gmail point com
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #ifndef DCPLUSPLUS_DCPP_QUEUE_ITEM_H
20 #define DCPLUSPLUS_DCPP_QUEUE_ITEM_H
21 
22 #include "User.h"
23 #include "FastAlloc.h"
24 #include "MerkleTree.h"
25 #include "Flags.h"
26 #include "forward.h"
27 #include "Segment.h"
28 
29 namespace dcpp {
30 
31 class QueueManager;
32 
33 class QueueItem : public Flags, public FastAlloc<QueueItem> {
34 public:
35 	typedef QueueItem* Ptr;
36 	typedef std::list<Ptr> List;
37 	typedef List::iterator Iter;
38 	typedef unordered_map<string*, Ptr, noCaseStringHash, noCaseStringEq> StringMap;
39 	typedef StringMap::iterator StringIter;
40 	typedef unordered_map<UserPtr, Ptr, User::Hash> UserMap;
41 	typedef UserMap::iterator UserIter;
42 	typedef unordered_map<UserPtr, List, User::Hash> UserListMap;
43 	typedef UserListMap::iterator UserListIter;
44 
45 	enum Priority {
46 		DEFAULT = -1,
47 		PAUSED = 0,
48 		LOWEST,
49 		LOW,
50 		NORMAL,
51 		HIGH,
52 		HIGHEST,
53 		LAST
54 	};
55 
56 	enum FileFlags {
57 		/** Normal download, no flags set */
58 		FLAG_NORMAL = 0x00,
59 		/** This is a user file listing download */
60 		FLAG_USER_LIST = 0x02,
61 		/** The file list is downloaded to use for directory download (used with USER_LIST) */
62 		FLAG_DIRECTORY_DOWNLOAD = 0x04,
63 		/** The file is downloaded to be viewed in the gui */
64 		FLAG_CLIENT_VIEW = 0x08,
65 		/** Flag to indicate that file should be viewed as a text file */
66 		FLAG_TEXT = 0x20,
67 		/** Match the queue against this list */
68 		FLAG_MATCH_QUEUE = 0x80,
69 		/** The file list downloaded was actually an .xml.bz2 list */
70 		FLAG_XML_BZLIST = 0x100,
71 		/** Only download a part of the file list */
72 		FLAG_PARTIAL_LIST = 0x200
73 	};
74 
75 	class Source : public Flags {
76 	public:
77 		enum {
78 			FLAG_NONE = 0x00,
79 			FLAG_FILE_NOT_AVAILABLE = 0x01,
80 			FLAG_PASSIVE = 0x02,
81 			FLAG_REMOVED = 0x04,
82 			FLAG_CRC_FAILED = 0x08,
83 			FLAG_CRC_WARN = 0x10,
84 			FLAG_NO_TTHF = 0x20,
85 			FLAG_BAD_TREE = 0x40,
86 			FLAG_NO_TREE = 0x80,
87 			FLAG_SLOW_SOURCE = 0x100,
88 			FLAG_UNTRUSTED = 0x200,
89 			FLAG_MASK = FLAG_FILE_NOT_AVAILABLE
90 				| FLAG_PASSIVE | FLAG_REMOVED | FLAG_CRC_FAILED | FLAG_CRC_WARN
91 				| FLAG_BAD_TREE | FLAG_NO_TREE | FLAG_SLOW_SOURCE | FLAG_UNTRUSTED
92 		};
93 
Source(const UserPtr & aUser)94 		Source(const UserPtr& aUser) : user(aUser) { }
Source(const Source & aSource)95 		Source(const Source& aSource) : Flags(aSource), user(aSource.user) { }
96 
97 		bool operator==(const UserPtr& aUser) const { return user == aUser; }
getUser()98 		UserPtr& getUser() { return user; }
99 		GETSET(UserPtr, user, User);
100 	};
101 
102 	typedef std::vector<Source> SourceList;
103 	typedef SourceList::iterator SourceIter;
104 	typedef SourceList::const_iterator SourceConstIter;
105 
106 	typedef set<Segment> SegmentSet;
107 	typedef SegmentSet::iterator SegmentIter;
108 	typedef SegmentSet::const_iterator SegmentConstIter;
109 
QueueItem(const string & aTarget,int64_t aSize,Priority aPriority,int aFlag,time_t aAdded,const TTHValue & tth)110 	QueueItem(const string& aTarget, int64_t aSize, Priority aPriority, int aFlag,
111 		time_t aAdded, const TTHValue& tth) :
112 		Flags(aFlag), target(aTarget), size(aSize),
113 		priority(aPriority), added(aAdded),	tthRoot(tth)
114 	{ }
115 
QueueItem(const QueueItem & rhs)116 	QueueItem(const QueueItem& rhs) :
117 		Flags(rhs), done(rhs.done), downloads(rhs.downloads), target(rhs.target),
118 		size(rhs.size), priority(rhs.priority), added(rhs.added), tthRoot(rhs.tthRoot),
119 		sources(rhs.sources), badSources(rhs.badSources), tempTarget(rhs.tempTarget)
120 	{ }
121 
~QueueItem()122 	virtual ~QueueItem() { }
123 
124 	int countOnlineUsers() const;
hasOnlineUsers()125 	bool hasOnlineUsers() const { return countOnlineUsers() > 0; }
126 
getSources()127 	SourceList& getSources() { return sources; }
getSources()128 	const SourceList& getSources() const { return sources; }
getBadSources()129 	SourceList& getBadSources() { return badSources; }
getBadSources()130 	const SourceList& getBadSources() const { return badSources; }
131 
getOnlineUsers(UserList & l)132 	void getOnlineUsers(UserList& l) const {
133 		for(SourceConstIter i = sources.begin(); i != sources.end(); ++i)
134 			if(i->getUser()->isOnline())
135 				l.push_back(i->getUser());
136 	}
137 
getTargetFileName()138 	string getTargetFileName() const { return Util::getFileName(getTarget()); }
139 
getSource(const UserPtr & aUser)140 	SourceIter getSource(const UserPtr& aUser) { return find(sources.begin(), sources.end(), aUser); }
getBadSource(const UserPtr & aUser)141 	SourceIter getBadSource(const UserPtr& aUser) { return find(badSources.begin(), badSources.end(), aUser); }
getSource(const UserPtr & aUser)142 	SourceConstIter getSource(const UserPtr& aUser) const { return find(sources.begin(), sources.end(), aUser); }
getBadSource(const UserPtr & aUser)143 	SourceConstIter getBadSource(const UserPtr& aUser) const { return find(badSources.begin(), badSources.end(), aUser); }
144 
isSource(const UserPtr & aUser)145 	bool isSource(const UserPtr& aUser) const { return getSource(aUser) != sources.end(); }
isBadSource(const UserPtr & aUser)146 	bool isBadSource(const UserPtr& aUser) const { return getBadSource(aUser) != badSources.end(); }
isBadSourceExcept(const UserPtr & aUser,Flags::MaskType exceptions)147 	bool isBadSourceExcept(const UserPtr& aUser, Flags::MaskType exceptions) const {
148 		SourceConstIter i = getBadSource(aUser);
149 		if(i != badSources.end())
150 			return i->isAnySet(exceptions^Source::FLAG_MASK);
151 		return false;
152 	}
153 
154 	int64_t getDownloadedBytes() const;
getDownloadedFraction()155 	double getDownloadedFraction() const { return static_cast<double>(getDownloadedBytes()) / getSize(); }
156 
getDownloads()157 	DownloadList& getDownloads() { return downloads; }
158 
159 	/** Next segment that is not done and not being downloaded, zero-sized segment returned if there is none is found */
160 	Segment getNextSegment(int64_t blockSize, int64_t wantedSize) const;
161 
162 	void addSegment(const Segment& segment);
resetDownloaded()163 	void resetDownloaded() { done.clear(); }
164 
isFinished()165 	bool isFinished() const {
166 		return done.size() == 1 && *done.begin() == Segment(0, getSize());
167 	}
168 
isRunning()169 	bool isRunning() const {
170 		return !isWaiting();
171 	}
isWaiting()172 	bool isWaiting() const {
173 		return downloads.empty();
174 	}
175 
getListName()176 	string getListName() const {
177 		dcassert(isSet(QueueItem::FLAG_USER_LIST));
178 		if(isSet(QueueItem::FLAG_XML_BZLIST)) {
179 			return getTarget() + ".xml.bz2";
180 		} else {
181 			return getTarget() + ".xml";
182 		}
183 	}
184 
185 	const string& getTempTarget();
setTempTarget(const string & aTempTarget)186 	void setTempTarget(const string& aTempTarget) { tempTarget = aTempTarget; }
187 
188 	GETSET(SegmentSet, done, Done);
189 	GETSET(DownloadList, downloads, Downloads);
190 	GETSET(string, target, Target);
191 	GETSET(int64_t, size, Size);
192 	GETSET(Priority, priority, Priority);
193 	GETSET(time_t, added, Added);
194 	GETSET(TTHValue, tthRoot, TTH);
195 private:
196 	QueueItem& operator=(const QueueItem&);
197 
198 	friend class QueueManager;
199 	SourceList sources;
200 	SourceList badSources;
201 	string tempTarget;
202 
203 	void addSource(const UserPtr& aUser);
204 	void removeSource(const UserPtr& aUser, int reason);
205 };
206 
207 } // namespace dcpp
208 
209 #endif // !defined(QUEUE_ITEM_H)
210