/* */ #ifndef D_FILE_ENTRY_H #define D_FILE_ENTRY_H #include "common.h" #include #include #include #include #include #include "SharedHandle.h" #include "File.h" #include "Request.h" #include "URIResult.h" #include "error_code.h" #include "A2STR.h" #include "TimerA2.h" #include "util.h" #include "a2functional.h" namespace aria2 { class URISelector; class ServerStatMan; class FileEntry { public: typedef std::set, RefLess > InFlightRequestSet; private: std::string path_; std::deque uris_; std::deque spentUris_; int64_t length_; int64_t offset_; bool requested_; class RequestFaster { public: bool operator()(const SharedHandle& lhs, const SharedHandle& rhs) const; }; typedef std::set, RequestFaster> RequestPool; RequestPool requestPool_; InFlightRequestSet inFlightRequests_; std::string contentType_; // URIResult is stored in the ascending order of the time when its result is // available. std::deque uriResults_; bool uniqueProtocol_; int maxConnectionPerServer_; std::string originalName_; Timer lastFasterReplace_; void storePool(const SharedHandle& request); public: FileEntry(); FileEntry(const std::string& path, int64_t length, int64_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); int64_t getLength() const { return length_; } void setLength(int64_t length) { length_ = length; } int64_t getOffset() const { return offset_; } void setOffset(int64_t offset) { offset_ = offset; } int64_t getLastOffset() { return offset_+length_; } bool isRequested() const { return requested_; } void setRequested(bool flag) { requested_ = flag; } 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); const std::string& getContentType() const { return contentType_; } // 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, const std::vector >& usedHosts, 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); // Finds faster server using ServerStatMan. SharedHandle findFasterRequest (const SharedHandle& base, const std::vector >& usedHosts, const SharedHandle& serverStatMan); void poolRequest(const SharedHandle& request); bool removeRequest(const SharedHandle& request); size_t countInFlightRequest() const; size_t countPooledRequest() const; const InFlightRequestSet& getInFlightRequests() const { return inFlightRequests_; } bool operator<(const FileEntry& fileEntry) const; bool exists() const; // Translate global offset goff to file local offset. int64_t gtoloff(int64_t goff) const; void removeURIWhoseHostnameIs(const std::string& hostname); void removeIdenticalURI(const std::string& uri); void addURIResult(std::string uri, error_code::Value 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, error_code::Value r); void setMaxConnectionPerServer(int n) { maxConnectionPerServer_ = n; } int 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(); // Push URIs in pooled or in-flight requests to the front of uris_. void putBackRequest(); void setOriginalName(const std::string& originalName); const std::string& getOriginalName() const { return originalName_; } bool removeUri(const std::string& uri); bool emptyRequestUri() const; 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 filename to given o. If memory is true, the output is // "[MEMORY]" plus the basename of the filename. If there is no // FileEntry, writes "n/a" to o. void writeFilePath (std::ostream& o, const SharedHandle& entry, bool memory); // 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) { o << "n/a"; } else { writeFilePath(o, e, memory); if(!e->getPath().empty()) { size_t count = countRequestedFileEntry(first, last); if(count > 1) { o << " (" << count-1 << "more)"; } } } } } // namespace aria2 #endif // D_FILE_ENTRY_H