1 /* <!-- copyright */ 2 /* 3 * aria2 - The high speed download utility 4 * 5 * Copyright (C) 2006 Tatsuhiro Tsujikawa 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 * In addition, as a special exception, the copyright holders give 22 * permission to link the code of portions of this program with the 23 * OpenSSL library under certain conditions as described in each 24 * individual source file, and distribute linked combinations 25 * including the two. 26 * You must obey the GNU General Public License in all respects 27 * for all of the code used other than OpenSSL. If you modify 28 * file(s) with this exception, you may extend this exception to your 29 * version of the file(s), but you are not obligated to do so. If you 30 * do not wish to do so, delete this exception statement from your 31 * version. If you delete this exception statement from all source 32 * files in the program, then also delete it here. 33 */ 34 /* copyright --> */ 35 #ifndef D_REQUEST_GROUP_H 36 #define D_REQUEST_GROUP_H 37 38 #include "common.h" 39 40 #include <string> 41 #include <algorithm> 42 #include <vector> 43 #include <memory> 44 #include <utility> 45 46 #include "TransferStat.h" 47 #include "TimeA2.h" 48 #include "Request.h" 49 #include "error_code.h" 50 #include "MetadataInfo.h" 51 #include "GroupId.h" 52 53 namespace aria2 { 54 55 class DownloadEngine; 56 class SegmentMan; 57 class Command; 58 class DownloadCommand; 59 class DownloadContext; 60 class PieceStorage; 61 class BtProgressInfoFile; 62 class Dependency; 63 class PreDownloadHandler; 64 class PostDownloadHandler; 65 class DiskWriterFactory; 66 class Option; 67 class RequestGroup; 68 class CheckIntegrityEntry; 69 struct DownloadResult; 70 class URISelector; 71 class URIResult; 72 class RequestGroupMan; 73 #ifdef ENABLE_BITTORRENT 74 class BtRuntime; 75 class PeerStorage; 76 #endif // ENABLE_BITTORRENT 77 78 class RequestGroup { 79 public: 80 enum HaltReason { NONE, SHUTDOWN_SIGNAL, USER_REQUEST }; 81 enum State { 82 // Waiting in the reserved queue 83 STATE_WAITING, 84 // Download has begun 85 STATE_ACTIVE 86 }; 87 88 private: 89 // If this download is a part of another download(for example, 90 // downloading torrent file described in Metalink file), this field 91 // has the GID of parent RequestGroup. 0 means this is a parent 92 // RequestGroup. 93 a2_gid_t belongsToGID_; 94 95 std::shared_ptr<GroupId> gid_; 96 97 std::shared_ptr<Option> option_; 98 99 // options applied on restart 100 std::shared_ptr<Option> pendingOption_; 101 102 std::shared_ptr<SegmentMan> segmentMan_; 103 104 std::shared_ptr<DownloadContext> downloadContext_; 105 106 std::shared_ptr<PieceStorage> pieceStorage_; 107 108 std::shared_ptr<BtProgressInfoFile> progressInfoFile_; 109 110 std::shared_ptr<DiskWriterFactory> diskWriterFactory_; 111 112 std::shared_ptr<Dependency> dependency_; 113 114 std::unique_ptr<URISelector> uriSelector_; 115 116 std::shared_ptr<MetadataInfo> metadataInfo_; 117 118 RequestGroupMan* requestGroupMan_; 119 120 #ifdef ENABLE_BITTORRENT 121 BtRuntime* btRuntime_; 122 123 PeerStorage* peerStorage_; 124 #endif // ENABLE_BITTORRENT 125 126 // If this download generates another downloads when completed(for 127 // example, downloads generated by PostDownloadHandler), this field 128 // has the GID of generated RequestGroups. empty list means there is 129 // no such RequestGroup. 130 std::vector<a2_gid_t> followedByGIDs_; 131 // This is a reverse link against followedByGIDs_. For example, a 132 // download included in followedByGIDs_ has this download's GID in 133 // followingGID_. 134 a2_gid_t followingGID_; 135 136 std::vector<const PreDownloadHandler*> preDownloadHandlers_; 137 138 std::vector<const PostDownloadHandler*> postDownloadHandlers_; 139 140 Time lastModifiedTime_; 141 142 // Timeout used for HTTP/FTP downloads. 143 std::chrono::seconds timeout_; 144 145 int state_; 146 147 int numConcurrentCommand_; 148 149 /** 150 * This is the number of connections used in streaming protocol(http/ftp) 151 */ 152 int numStreamConnection_; 153 154 int numStreamCommand_; 155 156 int numCommand_; 157 158 int fileNotFoundCount_; 159 160 int maxDownloadSpeedLimit_; 161 162 int maxUploadSpeedLimit_; 163 164 int resumeFailureCount_; 165 166 HaltReason haltReason_; 167 168 error_code::Value lastErrorCode_; 169 170 std::string lastErrorMessage_; 171 172 bool saveControlFile_; 173 174 bool fileAllocationEnabled_; 175 176 bool preLocalFileCheckEnabled_; 177 178 bool haltRequested_; 179 180 bool forceHaltRequested_; 181 182 bool pauseRequested_; 183 184 // restartRequested_ indicates that this download should be 185 // restarted. Usually, it is used with pauseRequested_ to stop 186 // download first. 187 bool restartRequested_; 188 189 // This flag just indicates that the downloaded file is not saved disk but 190 // just sits in memory. 191 bool inMemoryDownload_; 192 193 bool seedOnly_; 194 195 void validateFilename(const std::string& expectedFilename, 196 const std::string& actualFilename) const; 197 198 void initializePreDownloadHandler(); 199 200 void initializePostDownloadHandler(); 201 202 // Returns the result code of this RequestGroup. If the download 203 // finished, then returns error_code::FINISHED. If the 204 // download didn't finish and error result is available in 205 // _uriResults, then last result code is returned. Otherwise 206 // returns error_code::UNKNOWN_ERROR. 207 std::pair<error_code::Value, std::string> downloadResult() const; 208 209 void removeDefunctControlFile( 210 const std::shared_ptr<BtProgressInfoFile>& progressInfoFile); 211 212 public: 213 RequestGroup(const std::shared_ptr<GroupId>& gid, 214 const std::shared_ptr<Option>& option); 215 216 ~RequestGroup(); 217 218 bool isCheckIntegrityReady(); 219 220 void tryAutoFileRenaming(); 221 getSegmentMan()222 const std::shared_ptr<SegmentMan>& getSegmentMan() const 223 { 224 return segmentMan_; 225 } 226 227 std::unique_ptr<CheckIntegrityEntry> createCheckIntegrityEntry(); 228 229 // Returns first bootstrap commands to initiate a download. 230 // If this is HTTP/FTP download and file size is unknown, only 1 command 231 // (usually, HttpInitiateConnection or FtpInitiateConnection) will be created. 232 void createInitialCommand(std::vector<std::unique_ptr<Command>>& commands, 233 DownloadEngine* e); 234 235 void createNextCommandWithAdj(std::vector<std::unique_ptr<Command>>& commands, 236 DownloadEngine* e, int numAdj); 237 238 void createNextCommand(std::vector<std::unique_ptr<Command>>& commands, 239 DownloadEngine* e, int numCommand); 240 241 void createNextCommand(std::vector<std::unique_ptr<Command>>& commands, 242 DownloadEngine* e); 243 244 bool downloadFinished() const; 245 246 bool allDownloadFinished() const; 247 248 void closeFile(); 249 250 std::string getFirstFilePath() const; 251 252 int64_t getTotalLength() const; 253 254 int64_t getCompletedLength() const; 255 getPendingLength()256 inline int64_t getPendingLength() const 257 { 258 return getTotalLength() - getCompletedLength(); 259 } 260 261 /** 262 * Compares expected filename with specified actualFilename. 263 * The expected filename refers to FileEntry::getBasename() of the first 264 * element of DownloadContext::getFileEntries() 265 */ 266 void validateFilename(const std::string& actualFilename) const; 267 268 void validateTotalLength(int64_t expectedTotalLength, 269 int64_t actualTotalLength) const; 270 271 void validateTotalLength(int64_t actualTotalLength) const; 272 setNumConcurrentCommand(int num)273 void setNumConcurrentCommand(int num) { numConcurrentCommand_ = num; } 274 getNumConcurrentCommand()275 int getNumConcurrentCommand() const { return numConcurrentCommand_; } 276 getGID()277 a2_gid_t getGID() const { return gid_->getNumericId(); } 278 getGroupId()279 const std::shared_ptr<GroupId>& getGroupId() const { return gid_; } 280 281 TransferStat calculateStat() const; 282 getDownloadContext()283 const std::shared_ptr<DownloadContext>& getDownloadContext() const 284 { 285 return downloadContext_; 286 } 287 288 // This function also calls 289 // downloadContext->setOwnerRequestGroup(this). 290 void 291 setDownloadContext(const std::shared_ptr<DownloadContext>& downloadContext); 292 getPieceStorage()293 const std::shared_ptr<PieceStorage>& getPieceStorage() const 294 { 295 return pieceStorage_; 296 } 297 298 void setPieceStorage(const std::shared_ptr<PieceStorage>& pieceStorage); 299 300 void setProgressInfoFile( 301 const std::shared_ptr<BtProgressInfoFile>& progressInfoFile); 302 303 void increaseStreamCommand(); 304 305 void decreaseStreamCommand(); 306 307 void increaseStreamConnection(); 308 309 void decreaseStreamConnection(); 310 311 int getNumConnection() const; 312 313 void increaseNumCommand(); 314 315 void decreaseNumCommand(); 316 getNumCommand()317 int getNumCommand() const { return numCommand_; } 318 319 // TODO is it better to move the following 2 methods to 320 // SingleFileDownloadContext? 321 void setDiskWriterFactory( 322 const std::shared_ptr<DiskWriterFactory>& diskWriterFactory); 323 getDiskWriterFactory()324 const std::shared_ptr<DiskWriterFactory>& getDiskWriterFactory() const 325 { 326 return diskWriterFactory_; 327 } 328 setFileAllocationEnabled(bool f)329 void setFileAllocationEnabled(bool f) { fileAllocationEnabled_ = f; } 330 isFileAllocationEnabled()331 bool isFileAllocationEnabled() const { return fileAllocationEnabled_; } 332 333 bool needsFileAllocation() const; 334 335 /** 336 * Setting preLocalFileCheckEnabled_ to false, then skip the check to see 337 * if a file is already exists and control file exists etc. 338 * Always open file with DiskAdaptor::initAndOpenFile() 339 */ setPreLocalFileCheckEnabled(bool f)340 void setPreLocalFileCheckEnabled(bool f) { preLocalFileCheckEnabled_ = f; } 341 isPreLocalFileCheckEnabled()342 bool isPreLocalFileCheckEnabled() const { return preLocalFileCheckEnabled_; } 343 344 void setHaltRequested(bool f, HaltReason = SHUTDOWN_SIGNAL); 345 346 void setForceHaltRequested(bool f, HaltReason = SHUTDOWN_SIGNAL); 347 isHaltRequested()348 bool isHaltRequested() const { return haltRequested_; } 349 isForceHaltRequested()350 bool isForceHaltRequested() const { return forceHaltRequested_; } 351 352 void setPauseRequested(bool f); 353 isPauseRequested()354 bool isPauseRequested() const { return pauseRequested_; } 355 356 void setRestartRequested(bool f); 357 isRestartRequested()358 bool isRestartRequested() const { return restartRequested_; } 359 360 void dependsOn(const std::shared_ptr<Dependency>& dep); 361 362 bool isDependencyResolved(); 363 364 void releaseRuntimeResource(DownloadEngine* e); 365 366 void 367 postDownloadProcessing(std::vector<std::shared_ptr<RequestGroup>>& groups); 368 369 void addPostDownloadHandler(const PostDownloadHandler* handler); 370 371 void clearPostDownloadHandler(); 372 373 void preDownloadProcessing(); 374 375 void addPreDownloadHandler(const PreDownloadHandler* handler); 376 377 void clearPreDownloadHandler(); 378 379 void 380 processCheckIntegrityEntry(std::vector<std::unique_ptr<Command>>& commands, 381 std::unique_ptr<CheckIntegrityEntry> entry, 382 DownloadEngine* e); 383 384 // Initializes pieceStorage_ and segmentMan_. We guarantee that 385 // either both of pieceStorage_ and segmentMan_ are initialized or 386 // they are not. 387 void initPieceStorage(); 388 389 void dropPieceStorage(); 390 391 bool downloadFinishedByFileLength(); 392 393 void 394 loadAndOpenFile(const std::shared_ptr<BtProgressInfoFile>& progressInfoFile); 395 396 void shouldCancelDownloadForSafety(); 397 398 void adjustFilename(const std::shared_ptr<BtProgressInfoFile>& infoFile); 399 400 std::shared_ptr<DownloadResult> createDownloadResult() const; 401 getOption()402 const std::shared_ptr<Option>& getOption() const { return option_; } 403 404 void reportDownloadFinished(); 405 406 void setURISelector(std::unique_ptr<URISelector> uriSelector); 407 getURISelector()408 const std::unique_ptr<URISelector>& getURISelector() const 409 { 410 return uriSelector_; 411 } 412 413 void applyLastModifiedTimeToLocalFiles(); 414 415 void updateLastModifiedTime(const Time& time); 416 417 void increaseAndValidateFileNotFoundCount(); 418 419 // Just set inMemoryDownload flag true. 420 void markInMemoryDownload(); 421 422 // Returns inMemoryDownload flag. inMemoryDownload()423 bool inMemoryDownload() const { return inMemoryDownload_; } 424 425 void setTimeout(std::chrono::seconds timeout); 426 getTimeout()427 const std::chrono::seconds& getTimeout() const { return timeout_; } 428 429 // Returns true if current download speed exceeds 430 // maxDownloadSpeedLimit_. Always returns false if 431 // maxDownloadSpeedLimit_ == 0. Otherwise returns false. 432 bool doesDownloadSpeedExceed(); 433 434 // Returns true if current upload speed exceeds 435 // maxUploadSpeedLimit_. Always returns false if 436 // maxUploadSpeedLimit_ == 0. Otherwise returns false. 437 bool doesUploadSpeedExceed(); 438 getMaxDownloadSpeedLimit()439 int getMaxDownloadSpeedLimit() const { return maxDownloadSpeedLimit_; } 440 setMaxDownloadSpeedLimit(int speed)441 void setMaxDownloadSpeedLimit(int speed) { maxDownloadSpeedLimit_ = speed; } 442 getMaxUploadSpeedLimit()443 int getMaxUploadSpeedLimit() const { return maxUploadSpeedLimit_; } 444 setMaxUploadSpeedLimit(int speed)445 void setMaxUploadSpeedLimit(int speed) { maxUploadSpeedLimit_ = speed; } 446 447 void setLastErrorCode(error_code::Value code, const char* message = "") 448 { 449 lastErrorCode_ = code; 450 lastErrorMessage_ = message; 451 } 452 getLastErrorCode()453 error_code::Value getLastErrorCode() const { return lastErrorCode_; } 454 455 void saveControlFile() const; 456 457 void removeControlFile() const; 458 enableSaveControlFile()459 void enableSaveControlFile() { saveControlFile_ = true; } 460 disableSaveControlFile()461 void disableSaveControlFile() { saveControlFile_ = false; } 462 463 template <typename InputIterator> followedBy(InputIterator groupFirst,InputIterator groupLast)464 void followedBy(InputIterator groupFirst, InputIterator groupLast) 465 { 466 followedByGIDs_.clear(); 467 for (; groupFirst != groupLast; ++groupFirst) { 468 followedByGIDs_.push_back((*groupFirst)->getGID()); 469 } 470 } 471 followedBy()472 const std::vector<a2_gid_t>& followedBy() const { return followedByGIDs_; } 473 following(a2_gid_t gid)474 void following(a2_gid_t gid) { followingGID_ = gid; } 475 following()476 a2_gid_t following() const { return followingGID_; } 477 belongsTo(a2_gid_t gid)478 void belongsTo(a2_gid_t gid) { belongsToGID_ = gid; } 479 belongsTo()480 a2_gid_t belongsTo() const { return belongsToGID_; } 481 setRequestGroupMan(RequestGroupMan * requestGroupMan)482 void setRequestGroupMan(RequestGroupMan* requestGroupMan) 483 { 484 requestGroupMan_ = requestGroupMan; 485 } 486 getRequestGroupMan()487 RequestGroupMan* getRequestGroupMan() { return requestGroupMan_; } 488 getResumeFailureCount()489 int getResumeFailureCount() const { return resumeFailureCount_; } 490 increaseResumeFailureCount()491 void increaseResumeFailureCount() { ++resumeFailureCount_; } 492 493 bool p2pInvolved() const; 494 setMetadataInfo(const std::shared_ptr<MetadataInfo> & info)495 void setMetadataInfo(const std::shared_ptr<MetadataInfo>& info) 496 { 497 metadataInfo_ = info; 498 } 499 getMetadataInfo()500 const std::shared_ptr<MetadataInfo>& getMetadataInfo() const 501 { 502 return metadataInfo_; 503 } 504 getState()505 int getState() const { return state_; } 506 setState(int state)507 void setState(int state) { state_ = state; } 508 isSeedOnlyEnabled()509 bool isSeedOnlyEnabled() { return seedOnly_; } 510 511 void enableSeedOnly(); 512 513 // Returns true if this download is now seeding. 514 bool isSeeder() const; 515 516 void setPendingOption(std::shared_ptr<Option> option); getPendingOption()517 const std::shared_ptr<Option>& getPendingOption() const 518 { 519 return pendingOption_; 520 } 521 }; 522 523 } // namespace aria2 524 525 #endif // D_REQUEST_GROUP_H 526