/* */ #include "DownloadContext.h" #include #include "FileEntry.h" #include "fmt.h" #include "util.h" #include "wallclock.h" #include "DlAbortEx.h" #include "a2functional.h" #include "Signature.h" #include "ContextAttribute.h" namespace aria2 { DownloadContext::DownloadContext(): pieceLength_(0), checksumVerified_(false), knowsTotalLength_(true), ownerRequestGroup_(0), downloadStartTime_(0), downloadStopTime_(downloadStartTime_), metalinkServerContacted_(false) {} DownloadContext::DownloadContext(size_t pieceLength, uint64_t totalLength, const std::string& path): pieceLength_(pieceLength), checksumVerified_(false), knowsTotalLength_(true), ownerRequestGroup_(0), downloadStartTime_(0), downloadStopTime_(0), metalinkServerContacted_(false) { SharedHandle fileEntry(new FileEntry(path, totalLength, 0)); fileEntries_.push_back(fileEntry); } DownloadContext::~DownloadContext() {} void DownloadContext::resetDownloadStartTime() { downloadStartTime_ = global::wallclock(); downloadStopTime_.reset(0); } void DownloadContext::resetDownloadStopTime() { downloadStopTime_ = global::wallclock(); } int64_t DownloadContext::calculateSessionTime() const { if(downloadStopTime_ > downloadStartTime_) { return downloadStartTime_.differenceInMillis(downloadStopTime_); } else { return 0; } } SharedHandle DownloadContext::findFileEntryByOffset(off_t offset) const { if(fileEntries_.empty() || (offset > 0 && fileEntries_.back()->getOffset()+fileEntries_.back()->getLength() <= static_cast(offset))){ return SharedHandle(); } SharedHandle obj(new FileEntry()); obj->setOffset(offset); std::vector >::const_iterator i = std::upper_bound(fileEntries_.begin(), fileEntries_.end(), obj, DerefLess >()); if(i != fileEntries_.end() && (*i)->getOffset() == offset) { return *i; } else { return *(--i); } } void DownloadContext::setFilePathWithIndex (size_t index, const std::string& path) { if(0 < index && index <= fileEntries_.size()) { // We don't escape path because path may come from users. fileEntries_[index-1]->setPath(path); } else { throw DL_ABORT_EX(fmt("No such file with index=%u", static_cast(index))); } } void DownloadContext::setFileFilter(IntSequence seq) { std::vector fileIndexes = seq.flush(); std::sort(fileIndexes.begin(), fileIndexes.end()); fileIndexes.erase(std::unique(fileIndexes.begin(), fileIndexes.end()), fileIndexes.end()); bool selectAll = fileIndexes.empty() || fileEntries_.size() == 1; int32_t index = 1; for(std::vector >::const_iterator i = fileEntries_.begin(), eoi = fileEntries_.end(); i != eoi; ++i, ++index) { (*i)->setRequested (selectAll || std::binary_search(fileIndexes.begin(), fileIndexes.end(), index)); } } void DownloadContext::setAttribute (const std::string& key, const SharedHandle& value) { std::map >::value_type p = std::make_pair(key, value); std::pair >::iterator, bool> r = attrs_.insert(p); if(!r.second) { (*r.first).second = value; } } const SharedHandle& DownloadContext::getAttribute (const std::string& key) { std::map >::const_iterator itr = attrs_.find(key); if(itr == attrs_.end()) { throw DL_ABORT_EX(fmt("No attribute named %s", key.c_str())); } else { return (*itr).second; } } bool DownloadContext::hasAttribute(const std::string& key) const { return attrs_.count(key) == 1; } void DownloadContext::releaseRuntimeResource() { for(std::vector >::const_iterator i = fileEntries_.begin(), eoi = fileEntries_.end(); i != eoi; ++i) { (*i)->releaseRuntimeResource(); } } size_t DownloadContext::getNumPieces() const { if(pieceLength_ == 0) { return 0; } else { assert(!fileEntries_.empty()); return (fileEntries_.back()->getLastOffset()+pieceLength_-1)/pieceLength_; } } uint64_t DownloadContext::getTotalLength() const { if(fileEntries_.empty()) { return 0; } else { return fileEntries_.back()->getLastOffset(); } } const std::string& DownloadContext::getBasePath() const { if(basePath_.empty()) { assert(!fileEntries_.empty()); return getFirstFileEntry()->getPath(); } else { return basePath_; } } SharedHandle DownloadContext::getFirstRequestedFileEntry() const { for(std::vector >::const_iterator i = fileEntries_.begin(), eoi = fileEntries_.end(); i != eoi; ++i) { if((*i)->isRequested()) { return *i; } } return SharedHandle(); } size_t DownloadContext::countRequestedFileEntry() const { size_t numFiles = 0; for(std::vector >::const_iterator i = fileEntries_.begin(), eoi = fileEntries_.end(); i != eoi; ++i) { if((*i)->isRequested()) { ++numFiles; } } return numFiles; } bool DownloadContext::isChecksumVerificationNeeded() const { return pieceHashType_.empty() && !digest_.empty() && !hashType_.empty() && !checksumVerified_; } bool DownloadContext::isChecksumVerificationAvailable() const { return !digest_.empty() && !hashType_.empty(); } bool DownloadContext::isPieceHashVerificationAvailable() const { return !pieceHashType_.empty() && pieceHashes_.size() > 0 && pieceHashes_.size() == getNumPieces(); } const std::string& DownloadContext::getPieceHash(size_t index) const { if(index < pieceHashes_.size()) { return pieceHashes_[index]; } else { return A2STR::NIL; } } void DownloadContext::setDigest (const std::string& hashType, const std::string& digest) { hashType_ = hashType; digest_ = digest; } void DownloadContext::setBasePath(const std::string& basePath) { basePath_ = basePath; } void DownloadContext::setSignature(const SharedHandle& signature) { signature_ = signature; } } // namespace aria2