예제 #1
0
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()));
	}
}
예제 #2
0
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);
}