mirror of https://github.com/procxx/kepka.git
Use StorageFileLocation in streaming loader.
This commit is contained in:
parent
3f49796c43
commit
95023ca770
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue