/* */ #include "DownloadContext.h" #include #include "FileEntry.h" #include "StringFormat.h" #include "util.h" #include "wallclock.h" #include "DlAbortEx.h" namespace aria2 { DownloadContext::DownloadContext(): _dir(A2STR::DOT_C), _pieceLength(0), _knowsTotalLength(true), _ownerRequestGroup(0), _downloadStartTime(0), _downloadStopTime(_downloadStartTime) {} DownloadContext::DownloadContext(size_t pieceLength, uint64_t totalLength, const std::string& path): _dir(A2STR::DOT_C), _pieceLength(pieceLength), _knowsTotalLength(true), _ownerRequestGroup(0), _downloadStartTime(0), _downloadStopTime(0) { SharedHandle fileEntry(new FileEntry(path, totalLength, 0)); _fileEntries.push_back(fileEntry); } 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); 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(StringFormat("No such file with index=%u", static_cast(index)).str()); } } 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(StringFormat("No attribute named %s", key.c_str()).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; } } } // namespace aria2