void Download::open(int64_t bytes, bool z, bool hasDownloadedBytes) { if(getType() == Transfer::TYPE_FILE) { auto target = getDownloadTarget(); auto fullSize = tt.getFileSize(); if(getOverlapped() && bundle) { setOverlapped(false); bool found = false; // ok, we got a fast slot, so it's possible to disconnect original user now for(auto d: bundle->getDownloads()) { if(d != this && compare(d->getPath(), getPath()) == 0 && d->getSegment().contains(getSegment())) { // overlapping has no sense if segment is going to finish if(d->getSecondsLeft() < 10) break; found = true; // disconnect slow chunk d->getUserConnection().disconnect(); break; } } if(!found) { // slow chunk already finished ??? throw Exception(STRING(DOWNLOAD_FINISHED_IDLE)); } } if(hasDownloadedBytes) { if(File::getSize(target) != fullSize) { // When trying the download the next time, the resume pos will be reset throw Exception(CSTRING(TARGET_FILE_MISSING)); } } else { File::ensureDirectory(target); } int flags = File::OPEN | File::CREATE | File::SHARED_WRITE; if (getSegment().getEnd() != fullSize) { //segmented download, let Windows decide the buffering flags |= File::BUFFER_AUTO; } unique_ptr<SharedFileStream> f(new SharedFileStream(target, File::WRITE, flags)); if(f->getSize() != fullSize) { f->setSize(fullSize); } f->setPos(getSegment().getStart()); output = move(f); tempTarget = target; } else if(getType() == Transfer::TYPE_FULL_LIST) { auto target = getPath(); File::ensureDirectory(target); if(isSet(Download::FLAG_XML_BZ_LIST)) { target += ".xml.bz2"; } else { target += ".xml"; } output.reset(new File(target, File::WRITE, File::OPEN | File::TRUNCATE | File::CREATE)); tempTarget = target; } else if(getType() == Transfer::TYPE_PARTIAL_LIST) { output.reset(new StringOutputStream(pfs)); } else if(getType() == Transfer::TYPE_TREE) { output.reset(new MerkleTreeOutputStream<TigerTree>(tt)); } if((getType() == Transfer::TYPE_FILE || getType() == Transfer::TYPE_FULL_LIST) && SETTING(BUFFER_SIZE) > 0 ) { output.reset(new BufferedOutputStream<true>(output.release())); } if(getType() == Transfer::TYPE_FILE && !SettingsManager::lanMode) { typedef MerkleCheckOutputStream<TigerTree, true> MerkleStream; output.reset(new MerkleStream(tt, output.release(), getStartPos())); setFlag(Download::FLAG_TTH_CHECK); } // Check that we don't get too many bytes output.reset(new LimitedOutputStream<true>(output.release(), bytes)); if(z) { setFlag(Download::FLAG_ZDOWNLOAD); output.reset(new FilteredOutputStream<UnZFilter, true>(output.release())); } }
Range getOverlapped(const Range& a, const Range& b){ if(a.first > b.first) return getOverlapped(b, a); if(b.first > a.second) return NULL_RANGE; return Range(b.first, (a.second > b.second)? b.second : a.second); }