Repair file_reference in SaveGifQuery.

GitOrigin-RevId: ae9fcc543795a659c51699af8ea0048a0b5f8fb5
This commit is contained in:
levlam 2019-01-23 22:20:48 +03:00
parent 6633b87d51
commit 0ac8c2d389
8 changed files with 87 additions and 34 deletions

View File

@ -64,13 +64,22 @@ class GetSavedGifsQuery : public Td::ResultHandler {
};
class SaveGifQuery : public Td::ResultHandler {
FileId file_id_;
string file_reference_;
bool unsave_ = false;
Promise<Unit> promise_;
public:
explicit SaveGifQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
void send(FileId file_id, tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
CHECK(input_document != nullptr);
CHECK(file_id.is_valid());
file_id_ = file_id;
file_reference_ = input_document->file_reference_.as_slice().str();
unsave_ = unsave;
send_query(G()->net_query_creator().create(
create_storer(telegram_api::messages_saveGif(std::move(input_document), unsave))));
}
@ -82,7 +91,7 @@ class SaveGifQuery : public Td::ResultHandler {
}
bool result = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for save gif: " << result;
LOG(INFO) << "Receive result for save GIF: " << result;
if (!result) {
td->animations_manager_->reload_saved_animations(true);
}
@ -91,7 +100,22 @@ class SaveGifQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
LOG(ERROR) << "Receive error for save gif: " << status;
if (FileReferenceManager::is_file_reference_error(status)) {
td->file_manager_->delete_file_reference(file_id_, file_reference_);
td->file_reference_manager_->repair_file_reference(
file_id_, PromiseCreator::lambda([animation_id = file_id_, unsave = unsave_,
promise = std::move(promise_)](Result<Unit> result) mutable {
if (result.is_error()) {
return promise.set_error(Status::Error(400, "Failed to find the animation"));
}
send_closure(G()->animations_manager(), &AnimationsManager::send_save_gif_query, animation_id, unsave,
std::move(promise));
}));
return;
}
LOG(ERROR) << "Receive error for save GIF: " << status;
td->animations_manager_->reload_saved_animations(true);
promise_.set_error(std::move(status));
}
@ -310,6 +334,7 @@ tl_object_ptr<telegram_api::InputMedia> AnimationsManager::get_input_media(
return nullptr;
}
SecretInputMedia AnimationsManager::get_secret_input_media(FileId animation_file_id,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail,
@ -511,7 +536,7 @@ void AnimationsManager::on_get_saved_animations(
for (auto &document_ptr : saved_animations->gifs_) {
int32 document_constructor_id = document_ptr->get_id();
if (document_constructor_id == telegram_api::documentEmpty::ID) {
LOG(ERROR) << "Empty gif document received";
LOG(ERROR) << "Empty saved animation document received";
continue;
}
CHECK(document_constructor_id == telegram_api::document::ID);
@ -588,11 +613,19 @@ void AnimationsManager::add_saved_animation(const tl_object_ptr<td_api::InputFil
add_saved_animation_inner(r_file_id.ok(), std::move(promise));
}
void AnimationsManager::send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise) {
// TODO invokeAfter and log event
auto file_view = td_->file_manager_->get_file_view(animation_id);
CHECK(file_view.has_remote_location());
CHECK(file_view.remote_location().is_document()) << file_view.remote_location();
CHECK(!file_view.remote_location().is_web());
td_->create_handler<SaveGifQuery>(std::move(promise))
->send(animation_id, file_view.remote_location().as_input_document(), unsave);
}
void AnimationsManager::add_saved_animation_inner(FileId animation_id, Promise<Unit> &&promise) {
if (add_saved_animation_impl(animation_id, promise)) {
// TODO invokeAfter and log event
auto file_view = td_->file_manager_->get_file_view(animation_id);
td_->create_handler<SaveGifQuery>(std::move(promise))->send(file_view.remote_location().as_input_document(), false);
send_save_gif_query(animation_id, false, std::move(promise));
}
}
@ -697,12 +730,7 @@ void AnimationsManager::remove_saved_animation(const tl_object_ptr<td_api::Input
return promise.set_error(Status::Error(7, "Animation not found"));
}
// TODO invokeAfter
auto file_view = td_->file_manager_->get_file_view(file_id);
CHECK(file_view.has_remote_location());
CHECK(file_view.remote_location().is_document()) << file_view.remote_location();
CHECK(!file_view.remote_location().is_web());
td_->create_handler<SaveGifQuery>(std::move(promise))->send(file_view.remote_location().as_input_document(), true);
send_save_gif_query(file_id, true, std::move(promise));
saved_animation_ids_.erase(it);
@ -716,19 +744,22 @@ td_api::object_ptr<td_api::updateSavedAnimations> AnimationsManager::get_update_
void AnimationsManager::send_update_saved_animations(bool from_database) {
if (are_saved_animations_loaded_) {
if (!saved_animations_file_source_id_.is_valid() && !saved_animation_ids_.empty()) {
saved_animations_file_source_id_ = td_->file_reference_manager_->create_saved_animations_file_source();
}
vector<FileId> new_saved_animation_file_ids = saved_animation_ids_;
for (auto &animation_id : saved_animation_ids_) {
td_->file_manager_->add_file_source(animation_id, saved_animations_file_source_id_);
auto thumbnail_file_id = get_animation_thumbnail_file_id(animation_id);
if (thumbnail_file_id.is_valid()) {
td_->file_manager_->add_file_source(thumbnail_file_id, saved_animations_file_source_id_);
new_saved_animation_file_ids.push_back(thumbnail_file_id);
}
}
// there is no much reason to delete source from deleted saved animations,
// it will be automatically deleted after unsuccessfull try of file reference repairing
// moreover one thumbnail can belong to different animations, so removal should be careful
std::sort(new_saved_animation_file_ids.begin(), new_saved_animation_file_ids.end());
if (new_saved_animation_file_ids != saved_animation_file_ids_) {
if (!saved_animations_file_source_id_.is_valid()) {
saved_animations_file_source_id_ = td_->file_reference_manager_->create_saved_animations_file_source();
}
td_->file_manager_->change_files_source(saved_animations_file_source_id_, saved_animation_file_ids_,
new_saved_animation_file_ids);
saved_animation_file_ids_ = std::move(new_saved_animation_file_ids);
}
send_closure(G()->td(), &Td::send_update, get_update_saved_animations_object());

View File

@ -68,6 +68,8 @@ class AnimationsManager : public Actor {
vector<FileId> get_saved_animations(Promise<Unit> &&promise);
void send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise);
void add_saved_animation(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
void add_saved_animation_by_id(FileId animation_id);
@ -133,6 +135,7 @@ class AnimationsManager : public Actor {
int32 saved_animations_limit_ = 200;
vector<FileId> saved_animation_ids_;
vector<FileId> saved_animation_file_ids_;
double next_saved_animations_load_time_ = 0;
bool are_saved_animations_loaded_ = false;
vector<Promise<Unit>> load_saved_animations_queries_;

View File

@ -128,14 +128,19 @@ void FileReferenceManager::run_node(NodeId node_id) {
if (node.query->active_queries != 0) {
return;
}
VLOG(file_references) << "Run file references repair for file " << node_id;
VLOG(file_references) << "Trying to repair file reference for file " << node_id;
if (node.query->promises.empty()) {
node.query = {};
return;
}
if (!node.file_source_ids.has_next()) {
VLOG(file_references) << "Have no more file sources to repair file reference for file " << node_id;
for (auto &p : node.query->promises) {
p.set_value(Unit());
if (node.file_source_ids.empty()) {
p.set_error(Status::Error(400, "File not found"));
} else {
p.set_error(Status::Error(429, "Too Many Requests: retry after 1"));
}
}
node.query = {};
return;
@ -253,7 +258,7 @@ void FileReferenceManager::repair_file_reference(NodeId node_id, Promise<> promi
node.query = make_unique<Query>();
node.query->generation = ++query_generation_;
node.file_source_ids.reset_position();
VLOG(file_references) << "new query " << query_generation_;
VLOG(file_references) << "Create new file reference repair query with " << query_generation_;
}
node.query->promises.push_back(std::move(promise));
run_node(node_id);

View File

@ -42,8 +42,11 @@ class FileReferenceManager : public Actor {
using NodeId = FileId;
void repair_file_reference(NodeId node_id, Promise<> promise);
void add_file_source(NodeId node_id, FileSourceId file_source_id);
void remove_file_source(NodeId node_id, FileSourceId file_source_id);
void merge(NodeId to_node_id, NodeId from_node_id);
private:

View File

@ -77,6 +77,10 @@ class FastSetWithPosition {
return checked_.size() + not_checked_.size();
}
bool empty() const {
return size() == 0;
}
private:
std::set<T> checked_;
std::set<T> not_checked_;
@ -168,6 +172,13 @@ class SetWithPosition {
return static_cast<size_t>(has_value_);
}
bool empty() const {
if (fast_) {
return false;
}
return !has_value_;
}
private:
T value_{};
bool has_value_{false};

View File

@ -241,7 +241,7 @@ class SaveRecentStickerQuery : public Td::ResultHandler {
explicit SaveRecentStickerQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(bool is_attached, tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
void send(bool is_attached, tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
is_attached_ = is_attached;
int32 flags = 0;
@ -347,7 +347,7 @@ class FaveStickerQuery : public Td::ResultHandler {
explicit FaveStickerQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, bool unsave) {
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document, bool unsave) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::messages_faveSticker(std::move(input_document), unsave))));
}
@ -666,7 +666,7 @@ class SetStickerPositionQuery : public Td::ResultHandler {
explicit SetStickerPositionQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document, int32 position) {
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document, int32 position) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::stickers_changeStickerPosition(std::move(input_document), position))));
}
@ -695,7 +695,7 @@ class DeleteStickerFromSetQuery : public Td::ResultHandler {
explicit DeleteStickerFromSetQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(tl_object_ptr<telegram_api::InputDocument> &&input_document) {
void send(tl_object_ptr<telegram_api::inputDocument> &&input_document) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::stickers_removeStickerFromSet(std::move(input_document)))));
}

View File

@ -480,7 +480,7 @@ class FullRemoteFileLocation {
}
#define as_input_document() as_input_document_impl(__FILE__, __LINE__)
tl_object_ptr<telegram_api::InputDocument> as_input_document_impl(const char *file, int line) const {
tl_object_ptr<telegram_api::inputDocument> as_input_document_impl(const char *file, int line) const {
CHECK(is_common()) << file << ' ' << line;
CHECK(is_document()) << file << ' ' << line;
return make_tl_object<telegram_api::inputDocument>(common().id_, common().access_hash_,
@ -488,18 +488,18 @@ class FullRemoteFileLocation {
}
#define as_input_photo() as_input_photo_impl(__FILE__, __LINE__)
tl_object_ptr<telegram_api::InputPhoto> as_input_photo_impl(const char *file, int line) const {
tl_object_ptr<telegram_api::inputPhoto> as_input_photo_impl(const char *file, int line) const {
CHECK(is_photo()) << file << ' ' << line;
return make_tl_object<telegram_api::inputPhoto>(photo().id_, photo().access_hash_, BufferSlice(file_reference_));
}
tl_object_ptr<telegram_api::InputEncryptedFile> as_input_encrypted_file() const {
tl_object_ptr<telegram_api::inputEncryptedFile> as_input_encrypted_file() const {
CHECK(is_encrypted_secret());
return make_tl_object<telegram_api::inputEncryptedFile>(common().id_, common().access_hash_);
}
#define as_input_secure_file() as_input_secure_file_impl(__FILE__, __LINE__)
tl_object_ptr<telegram_api::InputSecureFile> as_input_secure_file_impl(const char *file, int line) const {
tl_object_ptr<telegram_api::inputSecureFile> as_input_secure_file_impl(const char *file, int line) const {
CHECK(is_secure()) << file << ' ' << line;
return make_tl_object<telegram_api::inputSecureFile>(common().id_, common().access_hash_);
}

View File

@ -164,7 +164,7 @@ void FileNode::set_remote_location(const RemoteFileLocation &remote, FileLocatio
void FileNode::delete_file_reference(Slice file_reference) {
if (remote_.type() == RemoteFileLocation::Type::Full && remote_.full().delete_file_reference(file_reference)) {
VLOG(file_references) << "Delete file reference of file " << main_file_id_;
VLOG(file_references) << "Do delete file reference of main file " << main_file_id_;
upload_was_update_file_reference_ = false;
download_was_update_file_reference_ = false;
on_pmc_changed();
@ -1915,7 +1915,7 @@ bool FileManager::delete_partial_remote_location(FileId file_id) {
void FileManager::delete_file_reference(FileId file_id, string file_reference) {
VLOG(file_references) << "Delete file reference of file " << file_id << " "
<< tag("reference", base64_encode(file_reference));
<< tag("reference_base64", base64_encode(file_reference));
auto node = get_sync_file_node(file_id);
if (!node) {
LOG(ERROR) << "Wrong file id " << file_id;