From 80e3841ec4d832ce9d5c4560b2ca8e909a68e53b Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 19 Sep 2019 03:07:44 +0300 Subject: [PATCH] Add get_channel_full_force. GitOrigin-RevId: cc2d1de9fa7859b1cead9562ce1be1ff9113788a --- td/telegram/ContactsManager.cpp | 87 ++++++++++++++++++++++++++------- td/telegram/ContactsManager.h | 3 ++ 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index bc1b5793..10ca03b1 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -6748,6 +6748,58 @@ string ContactsManager::get_channel_full_database_value(const ChannelFull *chann return log_event_store(*channel_full).as_slice().str(); } +void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, string value) { + LOG(INFO) << "Successfully loaded full " << channel_id << " of size " << value.size() << " from database"; + // G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto()); + // return; + + if (get_channel_full(channel_id) != nullptr || value.empty()) { + return; + } + + ChannelFull *channel_full = &channels_full_[channel_id]; + auto status = log_event_parse(*channel_full, value); + if (status.is_error()) { + // can't happen unless database is broken + LOG(ERROR) << "Repair broken full " << channel_id << ' ' << format::as_hex_dump<4>(Slice(value)); + + // just clean all known data about the channel and pretend that there was nothing in the database + channels_full_.erase(channel_id); + G()->td_db()->get_sqlite_pmc()->erase(get_channel_full_database_key(channel_id), Auto()); + return; + } + + Dependencies dependencies; + dependencies.channel_ids.insert(channel_id); + td_->messages_manager_->add_dialog_dependencies(dependencies, DialogId(channel_full->linked_channel_id)); + dependencies.chat_ids.insert(channel_full->migrated_from_chat_id); + td_->messages_manager_->resolve_dependencies_force(dependencies); + + update_channel_full(channel_full, channel_id, true); +} + +ContactsManager::ChannelFull *ContactsManager::get_channel_full_force(ChannelId channel_id) { + if (!channel_id.is_valid()) { + return nullptr; + } + + ChannelFull *c = get_channel_full(channel_id); + if (c != nullptr) { + return c; + } + if (!G()->parameters().use_chat_info_db) { + return nullptr; + } + if (!unavailable_channel_fulls_.insert(channel_id).second) { + return nullptr; + } + + LOG(INFO) << "Trying to load full " << channel_id << " from database"; + on_load_channel_full_from_database( + channel_id, G()->td_db()->get_sqlite_sync_pmc()->get(get_channel_full_database_key(channel_id))); + return get_channel_full(channel_id); +} + void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, bool from_database) { CHECK(u != nullptr); if (u->is_name_changed || u->is_username_changed || u->is_outbound_link_changed) { @@ -7089,6 +7141,7 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId channel_id, bool from_database) { CHECK(channel_full != nullptr); + unavailable_channel_fulls_.erase(channel_id); // don't needed anymore if (channel_full->is_changed) { if (channel_full->linked_channel_id.is_valid()) { td_->messages_manager_->force_create_dialog(DialogId(channel_full->linked_channel_id), "update_channel_full"); @@ -8334,7 +8387,7 @@ void ContactsManager::on_get_channel_participants_success( } if (participant_count != -1 || administrator_count != -1) { - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full != nullptr) { if (participant_count != -1 && channel_full->participant_count != participant_count) { channel_full->participant_count = participant_count; @@ -8448,13 +8501,13 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, return; } - auto c = get_channel(channel_id); + auto c = get_channel_force(channel_id); if (c != nullptr && c->participant_count != 0 && speculative_add_count(c->participant_count, new_participant_count)) { c->need_send_update = true; update_channel(c, channel_id); } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { return; } @@ -8467,7 +8520,7 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id, void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId user_id, DialogParticipantStatus new_status, DialogParticipantStatus old_status) { - auto c = get_channel(channel_id); + auto c = get_channel_force(channel_id); if (c != nullptr && c->participant_count != 0 && speculative_add_count(c->participant_count, new_status.is_member() - old_status.is_member())) { c->need_send_update = true; @@ -8515,7 +8568,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId } } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { return; } @@ -8535,7 +8588,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_invite_link) { LOG(INFO) << "Invalidate channel full for " << channel_id; // drop channel full cache - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full != nullptr) { channel_full->expires_at = 0.0; if (drop_invite_link) { @@ -8583,7 +8636,7 @@ void ContactsManager::on_get_channel_invite_link(ChannelId channel_id, return; } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { update_invite_link(channel_invite_links_[channel_id], std::move(invite_link_ptr)); return; @@ -8612,7 +8665,7 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan update_channel(linked_channel, channel_full->linked_channel_id); reload_channel(channel_full->linked_channel_id, Auto()); } - auto linked_channel_full = get_channel_full(channel_full->linked_channel_id); + auto linked_channel_full = get_channel_full_force(channel_full->linked_channel_id); if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id == channel_id) { linked_channel_full->linked_channel_id = ChannelId(); linked_channel_full->is_changed = true; @@ -8632,7 +8685,7 @@ void ContactsManager::on_update_channel_full_linked_channel_id(ChannelFull *chan update_channel(linked_channel, channel_full->linked_channel_id); reload_channel(channel_full->linked_channel_id, Auto()); } - auto linked_channel_full = get_channel_full(channel_full->linked_channel_id); + auto linked_channel_full = get_channel_full_force(channel_full->linked_channel_id); if (linked_channel_full != nullptr && linked_channel_full->linked_channel_id != channel_id) { linked_channel_full->linked_channel_id = channel_id; linked_channel_full->is_changed = true; @@ -9367,7 +9420,7 @@ void ContactsManager::on_update_channel_description(ChannelId channel_id, string return; } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { return; } @@ -9384,7 +9437,7 @@ void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, Sticke return; } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { return; } @@ -9397,14 +9450,14 @@ void ContactsManager::on_update_channel_sticker_set(ChannelId channel_id, Sticke void ContactsManager::on_update_channel_linked_channel_id(ChannelId channel_id, ChannelId group_channel_id) { if (channel_id.is_valid()) { - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); on_update_channel_full_linked_channel_id(channel_full, channel_id, group_channel_id); if (channel_full != nullptr) { update_channel_full(channel_full, channel_id); } } if (group_channel_id.is_valid()) { - auto channel_full = get_channel_full(group_channel_id); + auto channel_full = get_channel_full_force(group_channel_id); on_update_channel_full_linked_channel_id(channel_full, group_channel_id, channel_id); if (channel_full != nullptr) { update_channel_full(channel_full, group_channel_id); @@ -9418,7 +9471,7 @@ void ContactsManager::on_update_channel_is_all_history_available(ChannelId chann return; } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { return; } @@ -10202,7 +10255,7 @@ ContactsManager::ChannelFull *ContactsManager::get_channel_full(ChannelId channe } bool ContactsManager::get_channel_full(ChannelId channel_id, Promise &&promise) { - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr) { auto input_channel = get_input_channel(channel_id); if (input_channel == nullptr) { @@ -10220,7 +10273,7 @@ bool ContactsManager::get_channel_full(ChannelId channel_id, Promise &&pro send_get_channel_full_query(channel_id, std::move(input_channel), std::move(promise), "get expired channel_full"); return false; } else { - // request has already been sent in get_channel_full + // request has already been sent in get_channel_full_force // send_get_channel_full_query(channel_id, std::move(input_channel), Auto(), "get expired channel_full"); } } @@ -10534,7 +10587,7 @@ std::pair> ContactsManager::get_channel_partici return result; } - auto channel_full = get_channel_full(channel_id); + auto channel_full = get_channel_full_force(channel_id); if (channel_full == nullptr || (!force && channel_full->is_expired())) { if (force) { LOG(ERROR) << "Can't find cached ChannelFull"; diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index d8d36b1a..00c98dcd 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -913,6 +913,7 @@ class ContactsManager : public Actor { const ChannelFull *get_channel_full(ChannelId channel_id) const; ChannelFull *get_channel_full(ChannelId channel_id); + ChannelFull *get_channel_full_force(ChannelId channel_id); void send_get_channel_full_query(ChannelId channel_id, tl_object_ptr &&input_channel, Promise &&promise, const char *source); @@ -1057,6 +1058,7 @@ class ContactsManager : public Actor { void save_channel_full(ChannelFull *channel_full, ChannelId channel_id); static string get_channel_full_database_key(ChannelId channel_id); static string get_channel_full_database_value(const ChannelFull *channel_full); + void on_load_channel_full_from_database(ChannelId channel_id, string value); void update_user(User *u, UserId user_id, bool from_binlog = false, bool from_database = false); void update_chat(Chat *c, ChatId chat_id, bool from_binlog = false, bool from_database = false); @@ -1225,6 +1227,7 @@ class ContactsManager : public Actor { std::unordered_map>, ChannelIdHash> load_channel_from_database_queries_; std::unordered_set loaded_from_database_channels_; + std::unordered_set unavailable_channel_fulls_; std::unordered_map>, SecretChatIdHash> load_secret_chat_from_database_queries_; std::unordered_set loaded_from_database_secret_chats_;