/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "storage/streamed_file_downloader.h" #include "media/streaming/media_streaming_loader.h" #include "media/streaming/media_streaming_reader.h" namespace Storage { namespace { using namespace Media::Streaming; constexpr auto kPartSize = Loader::kPartSize; } // namespace StreamedFileDownloader::StreamedFileDownloader( uint64 objectId, MTP::DcId dcId, Data::FileOrigin origin, Cache::Key cacheKey, MediaKey fileLocationKey, std::shared_ptr reader, // For FileLoader const QString &toFile, int32 size, LocationType locationType, LoadToCacheSetting toCache, LoadFromCloudSetting fromCloud, bool autoLoading, uint8 cacheTag) : FileLoader( toFile, size, locationType, toCache, fromCloud, autoLoading, cacheTag) , _objectId(objectId) , _origin(origin) , _cacheKey(cacheKey) , _fileLocationKey(fileLocationKey) , _reader(std::move(reader)) { _partIsSaved.resize((size + kPartSize - 1) / kPartSize, false); _reader->partsForDownloader( ) | rpl::start_with_next([=](const LoadedPart &part) { if (part.offset == LoadedPart::kFailedOffset) { cancel(true); } else { savePart(std::move(part)); } }, _lifetime); _queue = _downloader->queueForDc(dcId); } StreamedFileDownloader::~StreamedFileDownloader() { stop(); } uint64 StreamedFileDownloader::objId() const { return _objectId; } Data::FileOrigin StreamedFileDownloader::fileOrigin() const { return _origin; } void StreamedFileDownloader::stop() { cancelRequests(); } Storage::Cache::Key StreamedFileDownloader::cacheKey() const { return _cacheKey; } std::optional StreamedFileDownloader::fileLocationKey() const { return _fileLocationKey; } void StreamedFileDownloader::cancelRequests() { const auto requests = std::count( begin(_partIsSaved), begin(_partIsSaved) + _nextPartIndex, false); _queue->queriesCount -= requests; _nextPartIndex = 0; _reader->cancelForDownloader(); } bool StreamedFileDownloader::loadPart() { if (_finished || _nextPartIndex >= size(_partIsSaved)) { return false; } const auto index = std::find( begin(_partIsSaved) + _nextPartIndex, end(_partIsSaved), false ) - begin(_partIsSaved); if (index == size(_partIsSaved)) { _nextPartIndex = index; return false; } _nextPartIndex = index + 1; _reader->loadForDownloader(index * kPartSize); AssertIsDebug(); //_downloader->requestedAmountIncrement( // requestData.dcId, // requestData.dcIndex, // kPartSize); ++_queue->queriesCount; return true; } void StreamedFileDownloader::savePart(const LoadedPart &part) { Expects(part.offset >= 0 && part.offset < _reader->size()); Expects(part.offset % kPartSize == 0); if (_finished || _cancelled) { return; } const auto offset = part.offset; const auto index = offset / kPartSize; Assert(index >= 0 && index < _partIsSaved.size()); if (_partIsSaved[index]) { return; } _partIsSaved[index] = true; if (index < _nextPartIndex) { AssertIsDebug(); //_downloader->requestedAmountIncrement( // requestData.dcId, // requestData.dcIndex, // -kPartSize); --_queue->queriesCount; } if (!writeResultPart(offset, bytes::make_span(part.bytes))) { return; } if (ranges::find(_partIsSaved, false) == end(_partIsSaved)) { if (!finalizeResult()) { return; } } _reader->doneForDownloader(offset); notifyAboutProgress(); } } // namespace Storage