/* */ #ifndef _D_REQUEST_GROUP_H_ #define _D_REQUEST_GROUP_H_ #include "common.h" #include #include #include "SharedHandle.h" #include "TransferStat.h" #include "TimeA2.h" #include "Request.h" #include "DownloadResult.h" #include "URIResult.h" namespace aria2 { class DownloadEngine; class SegmentMan; class SegmentManFactory; class Command; class DownloadCommand; class DownloadContext; class PieceStorage; class BtProgressInfoFile; class Dependency; class PreDownloadHandler; class PostDownloadHandler; class DiskWriterFactory; class Option; class Logger; class RequestGroup; class CheckIntegrityEntry; class DownloadResult; class ServerHost; class URISelector; #ifdef ENABLE_BITTORRENT class BtRuntime; class PeerStorage; #endif // ENABLE_BITTORRENT class RequestGroup { private: static int32_t _gidCounter; int32_t _gid; std::deque _uris; std::deque _spentUris; unsigned int _numConcurrentCommand; /** * This is the number of connections used in streaming protocol(http/ftp) */ unsigned int _numStreamConnection; unsigned int _numCommand; SharedHandle _segmentMan; SharedHandle _segmentManFactory; SharedHandle _downloadContext; SharedHandle _pieceStorage; SharedHandle _progressInfoFile; SharedHandle _diskWriterFactory; SharedHandle _dependency; std::deque > _serverHosts; bool _fileAllocationEnabled; bool _preLocalFileCheckEnabled; bool _haltRequested; bool _forceHaltRequested; // URIResult is stored in the ascending order of the time when its result is // available. std::deque _uriResults; bool _singleHostMultiConnectionEnabled; std::deque > _preDownloadHandlers; std::deque > _postDownloadHandlers; std::deque _acceptFeatures; std::deque _acceptTypes; SharedHandle _uriSelector; Time _lastModifiedTime; unsigned int _fileNotFoundCount; // Timeout used for HTTP/FTP downloads. time_t _timeout; // How many times HTTP/FTP download should retry. unsigned int _maxTries; #ifdef ENABLE_BITTORRENT WeakHandle _btRuntime; WeakHandle _peerStorage; #endif // ENABLE_BITTORRENT // This flag just indicates that the downloaded file is not saved disk but // just sits in memory. bool _inMemoryDownload; unsigned int _maxDownloadSpeedLimit; unsigned int _maxUploadSpeedLimit; const Option* _option; Logger* _logger; void validateFilename(const std::string& expectedFilename, const std::string& actualFilename) const; void validateTotalLength(uint64_t expectedTotalLength, uint64_t actualTotalLength) const; void initializePreDownloadHandler(); void initializePostDownloadHandler(); bool tryAutoFileRenaming(); // Returns the result code of this RequestGroup. // If the download finished, then returns DownloadResult::FINISHED. // If the download didn't finish and error result is available in _uriResults, // then last result code is returned. // Otherwise returns DownloadResult::UNKNOWN_ERROR. DownloadResult::RESULT downloadResult() const; public: RequestGroup(const Option* option, const std::deque& uris); ~RequestGroup(); /** * Reinitializes SegmentMan based on current property values and * returns new one. */ SharedHandle initSegmentMan(); SharedHandle getSegmentMan() const; // Returns first bootstrap commands to initiate a download. // If this is HTTP/FTP download and file size is unknown, only 1 command // (usually, HttpInitiateConnection or FtpInitiateConnection) will be created // with its Request object having Requet::METHOD_HEAD in its method. // This behavior can be changed by providing 3rd argument. // The method has effect only for using HTTP request including FTP via HTTP // proxy. void createInitialCommand(std::deque& commands, DownloadEngine* e, const std::string& method = Request::METHOD_HEAD); void createNextCommandWithAdj(std::deque& commands, DownloadEngine* e, int numAdj); void createNextCommand(std::deque& commands, DownloadEngine* e, unsigned int numCommand, const std::string& method = Request::METHOD_GET); void addURI(const std::string& uri) { _uris.push_back(uri); } bool downloadFinished() const; bool allDownloadFinished() const; void closeFile(); std::string getFilePath() const; uint64_t getTotalLength() const; uint64_t getCompletedLength() const; const std::deque& getRemainingUris() const { return _uris; } const std::deque& getSpentUris() const { return _spentUris; } void getURIs(std::deque& uris) const; /** * Compares expected filename with specified actualFilename. * The expected filename refers to FileEntry::getBasename() of the first * element of DownloadContext::getFileEntries() */ void validateFilename(const std::string& actualFilename) const; void validateTotalLength(uint64_t actualTotalLength) const; void setSegmentManFactory(const SharedHandle& segmentManFactory); void setNumConcurrentCommand(unsigned int num) { _numConcurrentCommand = num; } unsigned int getNumConcurrentCommand() const; int32_t getGID() const { return _gid; } TransferStat calculateStat(); SharedHandle getDownloadContext() const; void setDownloadContext(const SharedHandle& downloadContext); SharedHandle getPieceStorage() const; void setPieceStorage(const SharedHandle& pieceStorage); SharedHandle getProgressInfoFile() const; void setProgressInfoFile(const SharedHandle& progressInfoFile); void increaseStreamConnection(); void decreaseStreamConnection(); unsigned int getNumConnection() const; void increaseNumCommand(); void decreaseNumCommand(); unsigned int getNumCommand() const { return _numCommand; } // TODO is it better to move the following 2 methods to SingleFileDownloadContext? void setDiskWriterFactory(const SharedHandle& diskWriterFactory); SharedHandle getDiskWriterFactory() const; void setFileAllocationEnabled(bool f) { _fileAllocationEnabled = f; } bool isFileAllocationEnabled() const { return _fileAllocationEnabled; } bool needsFileAllocation() const; /** * Setting _preLocalFileCheckEnabled to false, then skip the check to see * if a file is already exists and control file exists etc. * Always open file with DiskAdaptor::initAndOpenFile() */ void setPreLocalFileCheckEnabled(bool f) { _preLocalFileCheckEnabled = f; } bool isPreLocalFileCheckEnabled() const { return _preLocalFileCheckEnabled; } void setHaltRequested(bool f); void setForceHaltRequested(bool f); bool isHaltRequested() const { return _haltRequested; } bool isForceHaltRequested() const { return _forceHaltRequested; } void addURIResult(std::string uri, DownloadResult::RESULT result); const std::deque& getURIResults() const; // Extracts URIResult whose _result is r and stores them into res. // The extracted URIResults are removed from _uriResults. void extractURIResult(std::deque& res, DownloadResult::RESULT r); void dependsOn(const SharedHandle& dep); bool isDependencyResolved(); void releaseRuntimeResource(DownloadEngine* e); void postDownloadProcessing(std::deque >& groups); void addPostDownloadHandler(const SharedHandle& handler); void clearPostDowloadHandler(); void preDownloadProcessing(); void addPreDownloadHandler(const SharedHandle& handler); void clearPreDowloadHandler(); void processCheckIntegrityEntry(std::deque& commands, const SharedHandle& entry, DownloadEngine* e); void initPieceStorage(); bool downloadFinishedByFileLength(); void loadAndOpenFile(const SharedHandle& progressInfoFile); void shouldCancelDownloadForSafety(); void adjustFilename(const SharedHandle& infoFile); SharedHandle createDownloadResult() const; const Option* getOption() const { return _option; } bool isSingleHostMultiConnectionEnabled() const { return _singleHostMultiConnectionEnabled; } void setSingleHostMultiConnectionEnabled(bool f) { _singleHostMultiConnectionEnabled = f; } /** * Registers given ServerHost. */ void registerServerHost(const SharedHandle& serverHost); /** * Returns ServerHost whose cuid is given cuid. If it is not found, returns * 0. */ SharedHandle searchServerHost(int32_t cuid) const; SharedHandle searchServerHost(const std::string& hostname) const; void removeServerHost(int32_t cuid); void removeURIWhoseHostnameIs(const std::string& hostname); void removeIdenticalURI(const std::string& uri); void reportDownloadFinished(); const std::deque& getAcceptFeatures() const; void addAcceptFeatureHeader(const std::string& feature); void removeAcceptFeatureHeader(const std::string& feature); const std::deque& getAcceptTypes() const; void addAcceptType(const std::string& type); void removeAcceptType(const std::string& type); static const std::string ACCEPT_METALINK; void setURISelector(const SharedHandle& uriSelector); void applyLastModifiedTimeToLocalFiles(); void updateLastModifiedTime(const Time& time); void increaseAndValidateFileNotFoundCount(); // Just set inMemoryDownload flag true. void markInMemoryDownload(); // Returns inMemoryDownload flag. bool inMemoryDownload() const; void tuneDownloadCommand(DownloadCommand* command); void setTimeout(time_t timeout); time_t getTimeout() const; void setMaxTries(unsigned int maxTries); unsigned int getMaxTries() const; // Returns true if current download speed exceeds // _maxDownloadSpeedLimit. Always returns false if // _maxDownloadSpeedLimit == 0. Otherwise returns false. bool doesDownloadSpeedExceed(); // Returns true if current upload speed exceeds // _maxUploadSpeedLimit. Always returns false if // _maxUploadSpeedLimit == 0. Otherwise returns false. bool doesUploadSpeedExceed(); }; typedef SharedHandle RequestGroupHandle; typedef WeakHandle RequestGroupWeakHandle; typedef std::deque RequestGroups; } // namespace aria2 #endif // _D_REQUEST_GROUP_H_