/* <!-- copyright */ /* * aria2 - The high speed download utility * * Copyright (C) 2006 Tatsuhiro Tsujikawa * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. */ /* copyright --> */ #ifndef _D_REQUEST_GROUP_H_ #define _D_REQUEST_GROUP_H_ #include "common.h" #include <string> #include <algorithm> #include <vector> #include "SharedHandle.h" #include "TransferStat.h" #include "TimeA2.h" #include "Request.h" #include "DownloadResultCode.h" #include "MetadataInfo.h" namespace aria2 { class DownloadEngine; class SegmentMan; 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 URISelector; class URIResult; class RequestGroupMan; #ifdef ENABLE_BITTORRENT class BtRuntime; class PeerStorage; #endif // ENABLE_BITTORRENT typedef int64_t gid_t; class RequestGroup { public: enum HaltReason { NONE, SHUTDOWN_SIGNAL, USER_REQUEST }; private: static gid_t _gidCounter; gid_t _gid; SharedHandle<Option> _option; size_t _numConcurrentCommand; /** * This is the number of connections used in streaming protocol(http/ftp) */ unsigned int _numStreamConnection; unsigned int _numCommand; SharedHandle<SegmentMan> _segmentMan; SharedHandle<DownloadContext> _downloadContext; SharedHandle<PieceStorage> _pieceStorage; bool _saveControlFile; SharedHandle<BtProgressInfoFile> _progressInfoFile; SharedHandle<DiskWriterFactory> _diskWriterFactory; SharedHandle<Dependency> _dependency; bool _fileAllocationEnabled; bool _preLocalFileCheckEnabled; bool _haltRequested; bool _forceHaltRequested; HaltReason _haltReason; bool _pauseRequested; std::vector<SharedHandle<PreDownloadHandler> > _preDownloadHandlers; std::vector<SharedHandle<PostDownloadHandler> > _postDownloadHandlers; std::vector<std::string> _acceptTypes; SharedHandle<URISelector> _uriSelector; Time _lastModifiedTime; unsigned int _fileNotFoundCount; // Timeout used for HTTP/FTP downloads. time_t _timeout; #ifdef ENABLE_BITTORRENT WeakHandle<BtRuntime> _btRuntime; WeakHandle<PeerStorage> _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; SharedHandle<URIResult> _lastUriResult; // If this download generates another downloads when completed(for // example, downloads generated by PostDownloadHandler), this field // has the GID of generated RequestGroups. empty list means there is // no such RequestGroup. std::vector<gid_t> _followedByGIDs; // If this download is a part of another download(for example, // downloading torrent file described in Metalink file), this field // has the GID of parent RequestGroup. 0 means this is a parent // RequestGroup. gid_t _belongsToGID; SharedHandle<MetadataInfo> _metadataInfo; RequestGroupMan* _requestGroupMan; int _resumeFailureCount; Logger* _logger; void validateFilename(const std::string& expectedFilename, const std::string& actualFilename) const; void initializePreDownloadHandler(); void initializePostDownloadHandler(); bool tryAutoFileRenaming(); // Returns the result code of this RequestGroup. If the download // finished, then returns downloadresultcode::FINISHED. If the // download didn't finish and error result is available in // _uriResults, then last result code is returned. Otherwise // returns downloadresultcode::UNKNOWN_ERROR. downloadresultcode::RESULT downloadResult() const; void removeDefunctControlFile (const SharedHandle<BtProgressInfoFile>& progressInfoFile); public: // The copy of option is stored in RequestGroup object. RequestGroup(const SharedHandle<Option>& option); ~RequestGroup(); const SharedHandle<SegmentMan>& getSegmentMan() const { return _segmentMan; } // 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. void createInitialCommand(std::vector<Command*>& commands, DownloadEngine* e); void createNextCommandWithAdj(std::vector<Command*>& commands, DownloadEngine* e, int numAdj); void createNextCommand(std::vector<Command*>& commands, DownloadEngine* e, unsigned int numCommand); void createNextCommand(std::vector<Command*>& commands, DownloadEngine* e); bool downloadFinished() const; bool allDownloadFinished() const; void closeFile(); std::string getFirstFilePath() const; uint64_t getTotalLength() const; uint64_t getCompletedLength() 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 expectedTotalLength, uint64_t actualTotalLength) const; void validateTotalLength(uint64_t actualTotalLength) const; void setNumConcurrentCommand(unsigned int num) { _numConcurrentCommand = num; } unsigned int getNumConcurrentCommand() const { return _numConcurrentCommand; } gid_t getGID() const { return _gid; } TransferStat calculateStat() const; const SharedHandle<DownloadContext>& getDownloadContext() const { return _downloadContext; } // This function also calls // downloadContext->setOwnerRequestGroup(this). void setDownloadContext(const SharedHandle<DownloadContext>& downloadContext); const SharedHandle<PieceStorage>& getPieceStorage() const { return _pieceStorage; } void setPieceStorage(const SharedHandle<PieceStorage>& pieceStorage); void setProgressInfoFile(const SharedHandle<BtProgressInfoFile>& progressInfoFile); void increaseStreamConnection(); void decreaseStreamConnection(); // Returns the number of connections used in HTTP(S)/FTP. unsigned int getNumStreamConnection() { return _numStreamConnection; } 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>& diskWriterFactory); const SharedHandle<DiskWriterFactory>& getDiskWriterFactory() const { return _diskWriterFactory; } 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, HaltReason = SHUTDOWN_SIGNAL); void setForceHaltRequested(bool f, HaltReason = SHUTDOWN_SIGNAL); bool isHaltRequested() const { return _haltRequested; } bool isForceHaltRequested() const { return _forceHaltRequested; } void setPauseRequested(bool f); bool isPauseRequested() const { return _pauseRequested; } void dependsOn(const SharedHandle<Dependency>& dep); bool isDependencyResolved(); void releaseRuntimeResource(DownloadEngine* e); void postDownloadProcessing(std::vector<SharedHandle<RequestGroup> >& groups); void addPostDownloadHandler(const SharedHandle<PostDownloadHandler>& handler); void clearPostDownloadHandler(); void preDownloadProcessing(); void addPreDownloadHandler(const SharedHandle<PreDownloadHandler>& handler); void clearPreDownloadHandler(); void processCheckIntegrityEntry(std::vector<Command*>& commands, const SharedHandle<CheckIntegrityEntry>& entry, DownloadEngine* e); // Initializes _pieceStorage and _segmentMan. We guarantee that // either both of _pieceStorage and _segmentMan are initialized or // they are not. void initPieceStorage(); void dropPieceStorage(); bool downloadFinishedByFileLength(); void loadAndOpenFile(const SharedHandle<BtProgressInfoFile>& progressInfoFile); void shouldCancelDownloadForSafety(); void adjustFilename(const SharedHandle<BtProgressInfoFile>& infoFile); SharedHandle<DownloadResult> createDownloadResult() const; const SharedHandle<Option>& getOption() const { return _option; } void reportDownloadFinished(); const std::vector<std::string>& getAcceptTypes() const { return _acceptTypes; } void addAcceptType(const std::string& type); template<typename InputIterator> void addAcceptType(InputIterator first, InputIterator last) { for(; first != last; ++first) { if(std::find(_acceptTypes.begin(), _acceptTypes.end(), *first) == _acceptTypes.end()) { _acceptTypes.push_back(*first); } } } void removeAcceptType(const std::string& type); void setURISelector(const SharedHandle<URISelector>& uriSelector); const SharedHandle<URISelector>& getURISelector() const { return _uriSelector; } void applyLastModifiedTimeToLocalFiles(); void updateLastModifiedTime(const Time& time); void increaseAndValidateFileNotFoundCount(); // Just set inMemoryDownload flag true. void markInMemoryDownload(); // Returns inMemoryDownload flag. bool inMemoryDownload() const { return _inMemoryDownload; } void setTimeout(time_t timeout); time_t getTimeout() const { return _timeout; } // 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(); unsigned int getMaxDownloadSpeedLimit() const { return _maxDownloadSpeedLimit; } void setMaxDownloadSpeedLimit(unsigned int speed) { _maxDownloadSpeedLimit = speed; } unsigned int getMaxUploadSpeedLimit() const { return _maxUploadSpeedLimit; } void setMaxUploadSpeedLimit(unsigned int speed) { _maxUploadSpeedLimit = speed; } void setLastUriResult(std::string uri, downloadresultcode::RESULT result); void saveControlFile() const; void removeControlFile() const; void enableSaveControlFile() { _saveControlFile = true; } void disableSaveControlFile() { _saveControlFile = false; } template<typename InputIterator> void followedBy(InputIterator groupFirst, InputIterator groupLast) { _followedByGIDs.clear(); for(; groupFirst != groupLast; ++groupFirst) { _followedByGIDs.push_back((*groupFirst)->getGID()); } } const std::vector<gid_t>& followedBy() const { return _followedByGIDs; } void belongsTo(gid_t gid) { _belongsToGID = gid; } gid_t belongsTo() const { return _belongsToGID; } void setRequestGroupMan(RequestGroupMan* requestGroupMan) { _requestGroupMan = requestGroupMan; } int getResumeFailureCount() const { return _resumeFailureCount; } void increaseResumeFailureCount() { ++_resumeFailureCount; } bool p2pInvolved() const; void setMetadataInfo(const SharedHandle<MetadataInfo>& info) { _metadataInfo = info; } const SharedHandle<MetadataInfo>& getMetadataInfo() const { return _metadataInfo; } static void resetGIDCounter() { _gidCounter = 0; } static gid_t newGID(); }; } // namespace aria2 #endif // _D_REQUEST_GROUP_H_