| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*
- 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;
- constexpr auto kRequestPartsCount = 32;
- } // namespace
- StreamedFileDownloader::StreamedFileDownloader(
- not_null<Main::Session*> session,
- uint64 objectId,
- MTP::DcId dcId,
- Data::FileOrigin origin,
- Cache::Key cacheKey,
- MediaKey fileLocationKey,
- std::shared_ptr<Reader> reader,
- // For FileLoader
- const QString &toFile,
- int64 size,
- LocationType locationType,
- LoadToCacheSetting toCache,
- LoadFromCloudSetting fromCloud,
- bool autoLoading,
- uint8 cacheTag)
- : FileLoader(
- session,
- toFile,
- size,
- size,
- locationType,
- toCache,
- fromCloud,
- autoLoading,
- cacheTag)
- , _objectId(objectId)
- , _origin(origin)
- , _cacheKey(cacheKey)
- , _fileLocationKey(fileLocationKey)
- , _reader(std::move(reader))
- , _partsCount((size + kPartSize - 1) / kPartSize) {
- _partIsSaved.resize(_partsCount, false);
- _reader->partsForDownloader(
- ) | rpl::start_with_next([=](const LoadedPart &part) {
- if (part.offset == LoadedPart::kFailedOffset) {
- cancel(FailureReason::OtherFailure);
- } else {
- savePart(std::move(part));
- }
- }, _lifetime);
- }
- StreamedFileDownloader::~StreamedFileDownloader() {
- if (!_finished) {
- cancel();
- } else {
- _reader->cancelForDownloader(this);
- }
- }
- uint64 StreamedFileDownloader::objId() const {
- return _objectId;
- }
- Data::FileOrigin StreamedFileDownloader::fileOrigin() const {
- return _origin;
- }
- void StreamedFileDownloader::requestParts() {
- while (!_finished
- && _nextPartIndex < _partsCount
- && _partsRequested < kRequestPartsCount) {
- requestPart();
- }
- _reader->continueDownloaderFromMainThread();
- }
- void StreamedFileDownloader::requestPart() {
- Expects(!_finished);
- const auto index = std::find(
- begin(_partIsSaved) + _nextPartIndex,
- end(_partIsSaved),
- false
- ) - begin(_partIsSaved);
- if (index == _partsCount) {
- _nextPartIndex = _partsCount;
- return;
- }
- _nextPartIndex = index + 1;
- _reader->loadForDownloader(this, index * kPartSize);
- ++_partsRequested;
- }
- QByteArray StreamedFileDownloader::readLoadedPart(int64 offset) {
- Expects(offset >= 0 && offset < _fullSize);
- Expects(!(offset % kPartSize));
- const auto index = (offset / kPartSize);
- return _partIsSaved[index]
- ? readLoadedPartBack(offset, kPartSize)
- : QByteArray();
- }
- Storage::Cache::Key StreamedFileDownloader::cacheKey() const {
- return _cacheKey;
- }
- std::optional<MediaKey> StreamedFileDownloader::fileLocationKey() const {
- return _fileLocationKey;
- }
- void StreamedFileDownloader::cancelHook() {
- _partsRequested = 0;
- _nextPartIndex = 0;
- _reader->cancelForDownloader(this);
- }
- void StreamedFileDownloader::startLoading() {
- requestParts();
- }
- 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 < _partsCount);
- if (_partIsSaved[index]) {
- return;
- }
- _partIsSaved[index] = true;
- ++_partsSaved;
- if (index < _nextPartIndex) {
- --_partsRequested;
- }
- if (!writeResultPart(offset, bytes::make_span(part.bytes))) {
- return;
- }
- _reader->doneForDownloader(offset);
- if (_partsSaved == _partsCount) {
- finalizeResult();
- } else {
- requestParts();
- notifyAboutProgress();
- }
- }
- } // namespace Storage
|