Use StorageFileLocation in streaming loader.

This commit is contained in:
John Preston 2019-03-25 13:17:47 +04:00
parent 3f49796c43
commit 95023ca770
6 changed files with 86 additions and 89 deletions

View File

@ -3125,8 +3125,9 @@ void ApiWrap::toggleFavedSticker(
return;
}
auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
auto performRequest = [=] {
const auto usedFileReference = document->fileReference();
request(MTPmessages_FaveSticker(
document->mtpInput(),
MTP_bool(!faved)
@ -3134,16 +3135,15 @@ void ApiWrap::toggleFavedSticker(
if (mtpIsTrue(result)) {
Stickers::SetFaved(document, faved);
}
}).fail(
base::duplicate(*failHandler)
).send();
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
}).send();
};
*failHandler = [=](const RPCError &error) {
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
if (error.code() == 400
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
const auto current = document->fileReference();
auto refreshed = [=](const UpdatedFileReferences &data) {
if (document->fileReference() != current) {
if (document->fileReference() != usedFileReference) {
performRequest();
}
};
@ -3161,8 +3161,9 @@ void ApiWrap::toggleSavedGif(
return;
}
auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
auto performRequest = [=] {
const auto usedFileReference = document->fileReference();
request(MTPmessages_SaveGif(
document->mtpInput(),
MTP_bool(!saved)
@ -3172,16 +3173,15 @@ void ApiWrap::toggleSavedGif(
App::addSavedGif(document);
}
}
}).fail(
base::duplicate(*failHandler)
).send();
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
}).send();
};
*failHandler = [=](const RPCError &error) {
*failHandler = [=](const RPCError & error, QByteArray usedFileReference) {
if (error.code() == 400
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
const auto current = document->fileReference();
auto refreshed = [=](const UpdatedFileReferences &data) {
if (document->fileReference() != current) {
if (document->fileReference() != usedFileReference) {
performRequest();
}
};
@ -4902,8 +4902,9 @@ void ApiWrap::sendExistingDocument(
caption,
MTPReplyMarkup());
auto failHandler = std::make_shared<Fn<void(const RPCError&)>>();
auto failHandler = std::make_shared<Fn<void(const RPCError&, QByteArray)>>();
auto performRequest = [=] {
const auto usedFileReference = document->fileReference();
history->sendRequestId = request(MTPmessages_SendMedia(
MTP_flags(sendFlags),
peer->input,
@ -4918,17 +4919,16 @@ void ApiWrap::sendExistingDocument(
sentEntities
)).done([=](const MTPUpdates &result) {
applyUpdates(result, randomId);
}).fail(
base::duplicate(*failHandler)
).afterRequest(history->sendRequestId
}).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference);
}).afterRequest(history->sendRequestId
).send();
};
*failHandler = [=](const RPCError &error) {
*failHandler = [=](const RPCError &error, QByteArray usedFileReference) {
if (error.code() == 400
&& error.type().startsWith(qstr("FILE_REFERENCE_"))) {
const auto current = document->fileReference();
auto refreshed = [=](const UpdatedFileReferences &data) {
if (document->fileReference() != current) {
if (document->fileReference() != usedFileReference) {
performRequest();
} else {
sendMessageFail(error);

View File

@ -1195,12 +1195,14 @@ auto DocumentData::createStreamingLoader(Data::FileOrigin origin) const
return hasRemoteLocation()
? std::make_unique<Media::Streaming::LoaderMtproto>(
&session().api(),
_dc,
MTP_inputDocumentFileLocation(
MTP_long(id),
MTP_long(_access),
MTP_bytes(_fileReference),
MTP_string(QString())),
StorageFileLocation(
_dc,
session().userId(),
MTP_inputDocumentFileLocation(
MTP_long(id),
MTP_long(_access),
MTP_bytes(_fileReference),
MTP_string(QString()))),
size,
origin)
: nullptr;

View File

@ -8,44 +8,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/streaming/media_streaming_loader_mtproto.h"
#include "apiwrap.h"
#include "auth_session.h"
#include "storage/cache/storage_cache_types.h"
namespace Media {
namespace Streaming {
namespace {
constexpr auto kMaxConcurrentRequests = 2;
constexpr auto kDocumentBaseCacheTag = 0x0000000000010000ULL;
constexpr auto kDocumentBaseCacheMask = 0x000000000000FF00ULL;
constexpr auto kMaxConcurrentRequests = 4;
} // namespace
LoaderMtproto::LoaderMtproto(
not_null<ApiWrap*> api,
MTP::DcId dcId,
const MTPInputFileLocation &location,
const StorageFileLocation &location,
int size,
Data::FileOrigin origin)
: _api(api)
, _dcId(dcId)
, _location(location)
, _size(size)
, _origin(origin) {
}
std::optional<Storage::Cache::Key> LoaderMtproto::baseCacheKey() const {
return _location.match([&](const MTPDinputDocumentFileLocation &data) {
const auto id = data.vid.v;
const auto high = kDocumentBaseCacheTag
| ((uint64(_dcId) << 16) & kDocumentBaseCacheMask)
| (id >> 48);
const auto low = (id << 16);
Ensures((low & 0xFFULL) == 0);
return Storage::Cache::Key{ high, low };
}, [](auto &&) -> Storage::Cache::Key {
Unexpected("Not implemented file location type.");
});
return _location.bigFileBaseCacheKey();
}
int LoaderMtproto::size() const {
@ -99,18 +85,19 @@ void LoaderMtproto::sendNext() {
}
static auto DcIndex = 0;
const auto reference = locationFileReference();
const auto usedFileReference = _location.fileReference();
const auto id = _sender.request(MTPupload_GetFile(
_location,
_location.tl(Auth().userId()),
MTP_int(offset),
MTP_int(kPartSize)
)).done([=](const MTPupload_File &result) {
requestDone(offset, result);
}).fail([=](const RPCError &error) {
requestFailed(offset, error, reference);
}).toDC(
MTP::downloadDcId(_dcId, (++DcIndex) % MTP::kDownloadSessionsCount)
).send();
requestFailed(offset, error, usedFileReference);
}).toDC(MTP::downloadDcId(
_location.dcId(),
(++DcIndex) % MTP::kDownloadSessionsCount
)).send();
_requests.emplace(offset, id);
sendNext();
@ -155,43 +142,20 @@ void LoaderMtproto::requestFailed(
return fail();
}
const auto callback = [=](const Data::UpdatedFileReferences &updated) {
_location.match([&](const MTPDinputDocumentFileLocation &location) {
const auto i = updated.data.find(
Data::DocumentFileLocationId{ location.vid.v });
if (i == end(updated.data)) {
return fail();
}
const auto reference = i->second;
if (reference == usedFileReference) {
return fail();
} else if (reference != location.vfile_reference.v) {
_location = MTP_inputDocumentFileLocation(
MTP_long(location.vid.v),
MTP_long(location.vaccess_hash.v),
MTP_bytes(reference),
MTP_string(QString()));
}
if (!_requests.take(offset)) {
// Request with such offset was already cancelled.
return;
}
_location.refreshFileReference(updated);
if (_location.fileReference() == usedFileReference) {
fail();
} else if (!_requests.take(offset)) {
// Request with such offset was already cancelled.
return;
} else {
_requested.add(offset);
sendNext();
}, [](auto &&) {
Unexpected("Not implemented file location type.");
});
}
};
_api->refreshFileReference(_origin, crl::guard(this, callback));
}
QByteArray LoaderMtproto::locationFileReference() const {
return _location.match([&](const MTPDinputDocumentFileLocation &data) {
return data.vfile_reference.v;
}, [](auto &&) -> QByteArray {
Unexpected("Not implemented file location type.");
});
}
rpl::producer<LoadedPart> LoaderMtproto::parts() const {
return _parts.events();
}

View File

@ -20,8 +20,7 @@ class LoaderMtproto : public Loader, public base::has_weak_ptr {
public:
LoaderMtproto(
not_null<ApiWrap*> api,
MTP::DcId dcId,
const MTPInputFileLocation &location,
const StorageFileLocation &location,
int size,
Data::FileOrigin origin);
@ -44,8 +43,8 @@ private:
void requestDone(int offset, const MTPupload_File &result);
void requestFailed(
int offset,
const RPCError &error,
int offset,
const RPCError &error,
const QByteArray &usedFileReference);
void changeCdnParams(
int offset,
@ -55,13 +54,11 @@ private:
const QByteArray &encryptionIV,
const QVector<MTPFileHash> &hashes);
[[nodiscard]] QByteArray locationFileReference() const;
const not_null<ApiWrap*> _api;
const MTP::DcId _dcId = 0;
// _location can be changed with an updated file_reference.
MTPInputFileLocation _location;
StorageFileLocation _location;
const int _size = 0;
const Data::FileOrigin _origin;

View File

@ -16,6 +16,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace {
constexpr auto kDocumentBaseCacheTag = 0x0000000000010000ULL;
constexpr auto kDocumentBaseCacheMask = 0x000000000000FF00ULL;
MTPInputPeer GenerateInputPeer(uint64 id, uint64 accessHash, int32 self) {
const auto bareId = [&] {
return peerToBareMTPInt(id);
@ -335,6 +338,36 @@ Storage::Cache::Key StorageFileLocation::cacheKey() const {
return Key();
}
Storage::Cache::Key StorageFileLocation::bigFileBaseCacheKey() const {
using Key = Storage::Cache::Key;
// Skip '1' and '2' for legacy document cache keys.
const auto shifted = ((uint64(_type) + 3) << 8);
const auto sliced = uint64(_dcId) & 0xFFULL;
switch (_type) {
case Type::Document: {
const auto high = kDocumentBaseCacheTag
| ((uint64(_dcId) << 16) & kDocumentBaseCacheMask)
| (_id >> 48);
const auto low = (_id << 16);
Ensures((low & 0xFFULL) == 0);
return Storage::Cache::Key{ high, low };
}
case Type::Legacy:
case Type::PeerPhoto:
case Type::StickerSetThumb:
case Type::Encrypted:
case Type::Secure:
case Type::Photo:
case Type::Takeout:
Unexpected("Not implemented file location type.");
};
Unexpected("Invalid file location type.");
}
QByteArray StorageFileLocation::fileReference() const {
return _fileReference;
}

View File

@ -83,6 +83,7 @@ public:
[[nodiscard]] Type type() const;
[[nodiscard]] bool valid() const;
[[nodiscard]] Storage::Cache::Key cacheKey() const;
[[nodiscard]] Storage::Cache::Key bigFileBaseCacheKey() const;
[[nodiscard]] QByteArray fileReference() const;
bool refreshFileReference(const Data::UpdatedFileReferences &updates);