1 /* 2 * Copyright (C) 2001-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 */ 18 19 #pragma once 20 21 #include "User.h" 22 #include "FastAlloc.h" 23 #include "MerkleTree.h" 24 #include "Flags.h" 25 #include "forward.h" 26 #include "Segment.h" 27 28 namespace dcpp { 29 30 class QueueManager; 31 32 class QueueItem : public Flags, public FastAlloc<QueueItem> { 33 public: 34 typedef QueueItem* Ptr; 35 typedef deque<Ptr> List; 36 typedef List::iterator Iter; 37 typedef unordered_map<string*, Ptr, CaseStringHash, CaseStringEq> StringMap; 38 typedef StringMap::iterator StringIter; 39 typedef unordered_map<UserPtr, Ptr, User::Hash> UserMap; 40 typedef UserMap::iterator UserIter; 41 typedef unordered_map<UserPtr, List, User::Hash> UserListMap; 42 typedef UserListMap::iterator UserListIter; 43 44 enum Priority { 45 DEFAULT = -1, 46 PAUSED = 0, 47 LOWEST, 48 LOW, 49 NORMAL, 50 HIGH, 51 HIGHEST, 52 LAST 53 }; 54 55 enum FileFlags { 56 /** Normal download, no flags set */ 57 FLAG_NORMAL = 0x00, 58 /** This is a user file listing download */ 59 FLAG_USER_LIST = 0x02, 60 /** The file list is downloaded to use for directory download (used with USER_LIST) */ 61 FLAG_DIRECTORY_DOWNLOAD = 0x04, 62 /** The file is downloaded to be viewed in the gui */ 63 FLAG_CLIENT_VIEW = 0x08, 64 /** Flag to indicate that file should be viewed as a text file */ 65 FLAG_TEXT = 0x20, 66 /** Match the queue against this list */ 67 FLAG_MATCH_QUEUE = 0x80, 68 /** The file list downloaded was actually an .xml.bz2 list */ 69 FLAG_XML_BZLIST = 0x100, 70 /** Only download a part of the file list */ 71 FLAG_PARTIAL_LIST = 0x200 72 }; 73 74 /** 75 * Source parts info 76 * Meaningful only when Source::FLAG_PARTIAL is set 77 */ 78 class PartialSource : public FastAlloc<PartialSource>, public intrusive_ptr_base<PartialSource> { 79 public: PartialSource(const string & aMyNick,const string & aHubIpPort,const string & aIp,uint16_t udp)80 PartialSource(const string& aMyNick, const string& aHubIpPort, const string& aIp, uint16_t udp) : 81 myNick(aMyNick), hubIpPort(aHubIpPort), ip(aIp), udpPort(udp), nextQueryTime(0), pendingQueryCount(0) { } 82 ~PartialSource()83 ~PartialSource() { } 84 85 typedef boost::intrusive_ptr<PartialSource> Ptr; 86 87 GETSET(PartsInfo, partialInfo, PartialInfo); 88 GETSET(string, myNick, MyNick); // for NMDC support only 89 GETSET(string, hubIpPort, HubIpPort); 90 GETSET(string, ip, Ip); 91 GETSET(uint16_t, udpPort, UdpPort); 92 GETSET(uint64_t, nextQueryTime, NextQueryTime); 93 GETSET(uint8_t, pendingQueryCount, PendingQueryCount); 94 }; 95 96 97 class Source : public Flags { 98 public: 99 enum { 100 FLAG_NONE = 0x00, 101 FLAG_FILE_NOT_AVAILABLE = 0x01, 102 FLAG_PASSIVE = 0x02, 103 FLAG_REMOVED = 0x04, 104 FLAG_CRC_FAILED = 0x08, 105 FLAG_CRC_WARN = 0x10, 106 FLAG_NO_TTHF = 0x20, 107 FLAG_BAD_TREE = 0x40, 108 FLAG_NO_TREE = 0x80, 109 FLAG_SLOW_SOURCE = 0x100, 110 FLAG_PARTIAL = 0x200, 111 FLAG_NO_NEED_PARTS = 0x250, 112 FLAG_TTH_INCONSISTENCY = 0x300, 113 FLAG_UNTRUSTED = 0x400, 114 FLAG_UNENCRYPTED = 0x450, 115 FLAG_MASK = FLAG_FILE_NOT_AVAILABLE 116 | FLAG_PASSIVE | FLAG_REMOVED | FLAG_CRC_FAILED | FLAG_CRC_WARN 117 | FLAG_BAD_TREE | FLAG_NO_TREE | FLAG_SLOW_SOURCE | FLAG_TTH_INCONSISTENCY | FLAG_UNTRUSTED | FLAG_UNENCRYPTED 118 }; 119 Source(const HintedUser & aUser)120 Source(const HintedUser& aUser) : user(aUser), partialSource(NULL) { } Source(const Source & aSource)121 Source(const Source& aSource) : Flags(aSource), user(aSource.user), partialSource(aSource.partialSource) { } 122 123 bool operator==(const UserPtr& aUser) const { return user == aUser; } getPartialSource()124 PartialSource::Ptr& getPartialSource() { return partialSource; } 125 126 GETSET(HintedUser, user, User); 127 GETSET(PartialSource::Ptr, partialSource, PartialSource); 128 }; 129 130 typedef std::vector<Source> SourceList; 131 typedef SourceList::iterator SourceIter; 132 typedef SourceList::const_iterator SourceConstIter; 133 134 typedef set<Segment> SegmentSet; 135 typedef SegmentSet::iterator SegmentIter; 136 typedef SegmentSet::const_iterator SegmentConstIter; 137 QueueItem(const string & aTarget,int64_t aSize,Priority aPriority,int aFlag,time_t aAdded,const TTHValue & tth)138 QueueItem(const string& aTarget, int64_t aSize, Priority aPriority, int aFlag, 139 time_t aAdded, const TTHValue& tth) : 140 Flags(aFlag), target(aTarget), size(aSize), 141 priority(aPriority), added(aAdded), tthRoot(tth), nextPublishingTime(0) 142 { } 143 QueueItem(const QueueItem & rhs)144 QueueItem(const QueueItem& rhs) : 145 Flags(rhs), done(rhs.done), downloads(rhs.downloads), target(rhs.target), 146 size(rhs.size), priority(rhs.priority), added(rhs.added), tthRoot(rhs.tthRoot), 147 nextPublishingTime(rhs.nextPublishingTime), sources(rhs.sources), badSources(rhs.badSources), 148 tempTarget(rhs.tempTarget) 149 150 { } 151 ~QueueItem()152 virtual ~QueueItem() { } 153 154 int countOnlineUsers() const; hasOnlineUsers()155 bool hasOnlineUsers() const { return countOnlineUsers() > 0; } 156 void getOnlineUsers(HintedUserList& l) const; 157 getSources()158 SourceList& getSources() { return sources; } getSources()159 const SourceList& getSources() const { return sources; } getBadSources()160 SourceList& getBadSources() { return badSources; } getBadSources()161 const SourceList& getBadSources() const { return badSources; } 162 getTargetFileName()163 string getTargetFileName() const { return Util::getFileName(getTarget()); } 164 getSource(const UserPtr & aUser)165 SourceIter getSource(const UserPtr& aUser) { return find(sources.begin(), sources.end(), aUser); } getBadSource(const UserPtr & aUser)166 SourceIter getBadSource(const UserPtr& aUser) { return find(badSources.begin(), badSources.end(), aUser); } getSource(const UserPtr & aUser)167 SourceConstIter getSource(const UserPtr& aUser) const { return find(sources.begin(), sources.end(), aUser); } getBadSource(const UserPtr & aUser)168 SourceConstIter getBadSource(const UserPtr& aUser) const { return find(badSources.begin(), badSources.end(), aUser); } 169 isSource(const UserPtr & aUser)170 bool isSource(const UserPtr& aUser) const { return getSource(aUser) != sources.end(); } isBadSource(const UserPtr & aUser)171 bool isBadSource(const UserPtr& aUser) const { return getBadSource(aUser) != badSources.end(); } isBadSourceExcept(const UserPtr & aUser,Flags::MaskType exceptions)172 bool isBadSourceExcept(const UserPtr& aUser, Flags::MaskType exceptions) const { 173 SourceConstIter i = getBadSource(aUser); 174 if(i != badSources.end()) 175 return i->isAnySet(exceptions^Source::FLAG_MASK); 176 return false; 177 } 178 179 int64_t getDownloadedBytes() const; getDownloadedFraction()180 double getDownloadedFraction() const { return static_cast<double>(getDownloadedBytes()) / getSize(); } 181 getDownloads()182 DownloadList& getDownloads() { return downloads; } 183 isChunkDownloaded(int64_t startPos,int64_t & len)184 bool isChunkDownloaded(int64_t startPos, int64_t& len) const { 185 if(len <= 0) return false; 186 187 for(SegmentSet::const_iterator i = done.begin(); i != done.end(); ++i) { 188 int64_t first = (*i).getStart(); 189 int64_t second = (*i).getEnd(); 190 191 if(first <= startPos && startPos < second){ 192 len = min(len, second - startPos); 193 return true; 194 } 195 } 196 197 return false; 198 } 199 200 /** Next segment that is not done and not being downloaded, zero-sized segment returned if there is none is found */ 201 Segment getNextSegment(int64_t blockSize, int64_t wantedSize, int64_t lastSpeed, const PartialSource::Ptr partialSource) const; 202 /** 203 * Is specified parts needed by this download? 204 */ 205 bool isNeededPart(const PartsInfo& partsInfo, int64_t blockSize); 206 /** 207 * Get shared parts info, max 255 parts range pairs 208 */ 209 void getPartialInfo(PartsInfo& partialInfo, int64_t blockSize) const; 210 211 212 void addSegment(const Segment& segment); resetDownloaded()213 void resetDownloaded() { done.clear(); } 214 isFinished()215 bool isFinished() const { 216 return done.size() == 1 && *done.begin() == Segment(0, getSize()); 217 } 218 isRunning()219 bool isRunning() const { 220 return !isWaiting(); 221 } isWaiting()222 bool isWaiting() const { 223 return downloads.empty(); 224 } 225 getListName()226 string getListName() const { 227 dcassert(isSet(QueueItem::FLAG_USER_LIST)); 228 if(isSet(QueueItem::FLAG_XML_BZLIST)) { 229 return getTarget() + ".xml.bz2"; 230 } else { 231 return getTarget() + ".xml"; 232 } 233 } 234 235 const string& getTempTarget(); setTempTarget(const string & aTempTarget)236 void setTempTarget(const string& aTempTarget) { tempTarget = aTempTarget; } 237 238 GETSET(SegmentSet, done, Done); 239 GETSET(DownloadList, downloads, Downloads); 240 GETSET(string, target, Target); 241 GETSET(int64_t, size, Size); 242 GETSET(Priority, priority, Priority); 243 GETSET(time_t, added, Added); 244 GETSET(TTHValue, tthRoot, TTH); 245 GETSET(uint64_t, nextPublishingTime, NextPublishingTime); 246 private: 247 QueueItem& operator=(const QueueItem&); 248 249 friend class QueueManager; 250 SourceList sources; 251 SourceList badSources; 252 string tempTarget; 253 254 void addSource(const HintedUser& aUser); 255 void removeSource(const UserPtr& aUser, int reason); 256 }; 257 258 } // namespace dcpp 259