/* */ #ifndef _D_FILE_ENTRY_H_ #define _D_FILE_ENTRY_H_ #include "common.h" #include #include #include #include #include "SharedHandle.h" #include "File.h" #include "Request.h" #include "URIResult.h" #include "DownloadResultCode.h" #include "A2STR.h" #include "TimerA2.h" namespace aria2 { class URISelector; class Logger; class FileEntry { private: std::string path_; std::deque uris_; std::deque spentUris_; uint64_t length_; off_t offset_; bool requested_; std::deque > requestPool_; std::deque > inFlightRequests_; std::string contentType_; // URIResult is stored in the ascending order of the time when its result is // available. std::deque uriResults_; bool uniqueProtocol_; size_t maxConnectionPerServer_; std::string originalName_; Timer lastFasterReplace_; Logger* logger_; void storePool(const SharedHandle& request); public: FileEntry(); FileEntry(const std::string& path, uint64_t length, off_t offset, const std::vector& uris = std::vector()); ~FileEntry(); FileEntry& operator=(const FileEntry& entry); std::string getBasename() const; std::string getDirname() const; const std::string& getPath() const { return path_; } void setPath(const std::string& path) { path_ = path; } uint64_t getLength() const { return length_; } void setLength(uint64_t length) { length_ = length; } off_t getOffset() const { return offset_; } void setOffset(off_t offset) { offset_ = offset; } off_t getLastOffset() { return offset_+length_; } bool isRequested() const { return requested_; } void setRequested(bool flag) { requested_ = flag; } void setupDir(); const std::deque& getRemainingUris() const { return uris_; } std::deque& getRemainingUris() { return uris_; } const std::deque& getSpentUris() const { return spentUris_; } size_t setUris(const std::vector& uris); template size_t addUris(InputIterator first, InputIterator last) { size_t count = 0; for(; first != last; ++first) { if(addUri(*first)) { ++count; } } return count; } bool addUri(const std::string& uri); bool insertUri(const std::string& uri, size_t pos); // Inserts uris_ and spentUris_ into uris. void getUris(std::vector& uris) const; void setContentType(const std::string& contentType) { contentType_ = contentType; } const std::string& getContentType() const { return contentType_; } std::string selectUri(const SharedHandle& uriSelector); // If pooled Request object is available, one of them is removed // from the pool and returned. If pool is empty, then select URI // using selectUri(selector) and construct Request object using it // and return the Request object. If referer is given, it is set to // newly created Request. If Request object is retrieved from the // pool, referer is ignored. If method is given, it is set to newly // created Request. If Request object is retrieved from the pool, // method is ignored. If uriReuse is true and selector does not // returns Request object either because uris_ is empty or all URI // are not be usable because maxConnectionPerServer_ limit, then // reuse used URIs and do selection again. SharedHandle getRequest (const SharedHandle& selector, bool uriReuse = true, const std::string& referer = A2STR::NIL, const std::string& method = Request::METHOD_GET); // Finds pooled Request object which is faster than passed one, // comparing their PeerStat objects. If such Request is found, it is // removed from the pool and returned. SharedHandle findFasterRequest(const SharedHandle& base); void poolRequest(const SharedHandle& request); bool removeRequest(const SharedHandle& request); size_t countInFlightRequest() const { return inFlightRequests_.size(); } size_t countPooledRequest() const { return requestPool_.size(); } const std::deque >& getInFlightRequests() const { return inFlightRequests_; } bool operator<(const FileEntry& fileEntry) const; bool exists() const; // Translate global offset goff to file local offset. off_t gtoloff(off_t goff) const; void removeURIWhoseHostnameIs(const std::string& hostname); void removeIdenticalURI(const std::string& uri); void addURIResult(std::string uri, downloadresultcode::RESULT result); const std::deque& getURIResults() const { return uriResults_; } // Extracts URIResult whose _result is r and stores them into res. // The extracted URIResults are removed from uriResults_. void extractURIResult (std::deque& res, downloadresultcode::RESULT r); void setMaxConnectionPerServer(size_t n) { maxConnectionPerServer_ = n; } size_t getMaxConnectionPerServer() const { return maxConnectionPerServer_; } // Reuse URIs which have not emitted error so far and whose host // component is not included in ignore. The reusable URIs are // appended to uris_ maxConnectionPerServer_ times. void reuseUri(const std::vector& ignore); void releaseRuntimeResource(); void setOriginalName(const std::string& originalName) { originalName_ = originalName; } const std::string& getOriginalName() const { return originalName_; } bool removeUri(const std::string& uri); bool emptyRequestUri() const { return uris_.empty() && inFlightRequests_.empty() && requestPool_.empty(); } void setUniqueProtocol(bool f) { uniqueProtocol_ = f; } bool isUniqueProtocol() const { return uniqueProtocol_; } }; // Returns the first FileEntry which isRequested() method returns // true. If no such FileEntry exists, then returns // SharedHandle(). template SharedHandle getFirstRequestedFileEntry (InputIterator first, InputIterator last) { for(; first != last; ++first) { if((*first)->isRequested()) { return *first; } } return SharedHandle(); } // Counts the number of files selected in the given iterator range // [first, last). template size_t countRequestedFileEntry(InputIterator first, InputIterator last) { size_t count = 0; for(; first != last; ++first) { if((*first)->isRequested()) { ++count; } } return count; } // Returns true if at least one requested FileEntry has URIs. template bool isUriSuppliedForRequsetFileEntry(InputIterator first, InputIterator last) { for(; first != last; ++first) { if((*first)->isRequested() && !(*first)->getRemainingUris().empty()) { return true; } } return false; } // Writes first filename to given o. If memory is true, the output is // "[MEMORY]" plus the basename of the first filename. If there is no // FileEntry, writes "n/a" to o. If more than 1 FileEntry are in the // iterator range [first, last), "(Nmore)" is written at the end where // N is the number of files in iterator range [first, last) minus 1. template void writeFilePath (InputIterator first, InputIterator last, std::ostream& o, bool memory) { SharedHandle e = getFirstRequestedFileEntry(first, last); if(e.isNull()) { o << "n/a"; } else { if(e->getPath().empty()) { std::vector uris; e->getUris(uris); if(uris.empty()) { o << "n/a"; } else { o << uris.front(); } } else { if(memory) { o << "[MEMORY]" << File(e->getPath()).getBasename(); } else { o << e->getPath(); } size_t count = countRequestedFileEntry(first, last); if(count > 1) { o << " (" << count-1 << "more)"; } } } } } #endif // _D_FILE_ENTRY_H_