diff --git a/CMake/TdSetUpCompiler.cmake b/CMake/TdSetUpCompiler.cmake index d9d67da33..40c667e32 100644 --- a/CMake/TdSetUpCompiler.cmake +++ b/CMake/TdSetUpCompiler.cmake @@ -88,6 +88,9 @@ function(td_set_up_compiler) # _FILE_OFFSET_BITS is broken in Android NDK r15, r15b and r17 and doesn't work prior to Android 7.0 add_definitions(-D_FILE_OFFSET_BITS=64) + # _GNU_SOURCE might not be defined by g++ + add_definitions(-D_GNU_SOURCE) + if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl") if (ILLUMOS) diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index ca8ea5f9d..39c916093 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3399,43 +3399,16 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent } ContactsManager::~ContactsManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_full_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_photos_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_users_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), pending_user_photos_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_profile_photo_file_source_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), my_photo_file_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_full_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chat_full_file_source_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), min_channels_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channels_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channels_full_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_channels_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), invalidated_channels_full_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_full_file_source_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), secret_chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_secret_chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), secret_chats_with_user_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), invite_link_infos_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_access_by_invite_link_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_users_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_user_fulls_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_chat_fulls_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_channels_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_channel_fulls_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_secret_chats_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_administrators_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), cached_channel_participants_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), resolved_phone_numbers_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_participants_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), all_imported_contacts_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), linked_channel_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), restricted_user_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), restricted_channel_ids_); + Scheduler::instance()->destroy_on_scheduler( + G()->get_gc_scheduler_id(), users_, users_full_, user_photos_, unknown_users_, pending_user_photos_, + user_profile_photo_file_source_ids_, my_photo_file_id_, chats_, chats_full_, unknown_chats_, + chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_, + invalidated_channels_full_, channel_full_file_source_ids_, secret_chats_, unknown_secret_chats_, + secret_chats_with_user_, invite_link_infos_, dialog_access_by_invite_link_, loaded_from_database_users_, + unavailable_user_fulls_, loaded_from_database_chats_, unavailable_chat_fulls_, loaded_from_database_channels_, + unavailable_channel_fulls_, loaded_from_database_secret_chats_, dialog_administrators_, + cached_channel_participants_, resolved_phone_numbers_, channel_participants_, all_imported_contacts_, + linked_channel_ids_, restricted_user_ids_, restricted_channel_ids_); } void ContactsManager::tear_down() { @@ -8795,23 +8768,24 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, class ContactsManager::UserLogEvent { public: UserId user_id; - User u; + const User *u_in = nullptr; + unique_ptr u_out; UserLogEvent() = default; - UserLogEvent(UserId user_id, const User &u) : user_id(user_id), u(u) { + UserLogEvent(UserId user_id, const User *u) : user_id(user_id), u_in(u) { } template void store(StorerT &storer) const { td::store(user_id, storer); - td::store(u, storer); + td::store(*u_in, storer); } template void parse(ParserT &parser) { td::parse(user_id, parser); - td::parse(u, parser); + td::parse(u_out, parser); } }; @@ -8830,7 +8804,7 @@ void ContactsManager::save_user(User *u, UserId user_id, bool from_binlog) { make_tl_object(get_user_access_hash_object(user_id, u))); } if (!from_binlog) { - auto log_event = UserLogEvent(user_id, *u); + auto log_event = UserLogEvent(user_id, u); auto storer = get_log_event_storer(log_event); if (u->log_event_id == 0) { u->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Users, storer); @@ -8860,8 +8834,8 @@ void ContactsManager::on_binlog_user_event(BinlogEvent &&event) { } LOG(INFO) << "Add " << user_id << " from binlog"; - User *u = add_user(user_id, "on_binlog_user_event"); - *u = std::move(log_event.u); // users come from binlog before all other events, so just add them + User *u = users_.emplace(user_id, std::move(log_event.u_out)).first->second.get(); + CHECK(u != nullptr); u->log_event_id = event.id_; @@ -9109,23 +9083,24 @@ ContactsManager::User *ContactsManager::get_user_force_impl(UserId user_id) { class ContactsManager::ChatLogEvent { public: ChatId chat_id; - Chat c; + const Chat *c_in = nullptr; + unique_ptr c_out; ChatLogEvent() = default; - ChatLogEvent(ChatId chat_id, const Chat &c) : chat_id(chat_id), c(c) { + ChatLogEvent(ChatId chat_id, const Chat *c) : chat_id(chat_id), c_in(c) { } template void store(StorerT &storer) const { td::store(chat_id, storer); - td::store(c, storer); + td::store(*c_in, storer); } template void parse(ParserT &parser) { td::parse(chat_id, parser); - td::parse(c, parser); + td::parse(c_out, parser); } }; @@ -9136,7 +9111,7 @@ void ContactsManager::save_chat(Chat *c, ChatId chat_id, bool from_binlog) { CHECK(c != nullptr); if (!c->is_saved) { if (!from_binlog) { - auto log_event = ChatLogEvent(chat_id, *c); + auto log_event = ChatLogEvent(chat_id, c); auto storer = get_log_event_storer(log_event); if (c->log_event_id == 0) { c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Chats, storer); @@ -9167,8 +9142,8 @@ void ContactsManager::on_binlog_chat_event(BinlogEvent &&event) { } LOG(INFO) << "Add " << chat_id << " from binlog"; - Chat *c = add_chat(chat_id); - *c = std::move(log_event.c); // chats come from binlog before all other events, so just add them + Chat *c = chats_.emplace(chat_id, std::move(log_event.c_out)).first->second.get(); + CHECK(c != nullptr); c->log_event_id = event.id_; @@ -9346,23 +9321,24 @@ ContactsManager::Chat *ContactsManager::get_chat_force(ChatId chat_id) { class ContactsManager::ChannelLogEvent { public: ChannelId channel_id; - Channel c; + const Channel *c_in = nullptr; + unique_ptr c_out; ChannelLogEvent() = default; - ChannelLogEvent(ChannelId channel_id, const Channel &c) : channel_id(channel_id), c(c) { + ChannelLogEvent(ChannelId channel_id, const Channel *c) : channel_id(channel_id), c_in(c) { } template void store(StorerT &storer) const { td::store(channel_id, storer); - td::store(c, storer); + td::store(*c_in, storer); } template void parse(ParserT &parser) { td::parse(channel_id, parser); - td::parse(c, parser); + td::parse(c_out, parser); } }; @@ -9381,7 +9357,7 @@ void ContactsManager::save_channel(Channel *c, ChannelId channel_id, bool from_b make_tl_object(get_channel_access_hash_object(channel_id, c))); } if (!from_binlog) { - auto log_event = ChannelLogEvent(channel_id, *c); + auto log_event = ChannelLogEvent(channel_id, c); auto storer = get_log_event_storer(log_event); if (c->log_event_id == 0) { c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Channels, storer); @@ -9412,8 +9388,8 @@ void ContactsManager::on_binlog_channel_event(BinlogEvent &&event) { } LOG(INFO) << "Add " << channel_id << " from binlog"; - Channel *c = add_channel(channel_id, "on_binlog_channel_event"); - *c = std::move(log_event.c); // channels come from binlog before all other events, so just add them + Channel *c = channels_.emplace(channel_id, std::move(log_event.c_out)).first->second.get(); + CHECK(c != nullptr); c->log_event_id = event.id_; @@ -9607,23 +9583,24 @@ ContactsManager::Channel *ContactsManager::get_channel_force(ChannelId channel_i class ContactsManager::SecretChatLogEvent { public: SecretChatId secret_chat_id; - SecretChat c; + const SecretChat *c_in = nullptr; + unique_ptr c_out; SecretChatLogEvent() = default; - SecretChatLogEvent(SecretChatId secret_chat_id, const SecretChat &c) : secret_chat_id(secret_chat_id), c(c) { + SecretChatLogEvent(SecretChatId secret_chat_id, const SecretChat *c) : secret_chat_id(secret_chat_id), c_in(c) { } template void store(StorerT &storer) const { td::store(secret_chat_id, storer); - td::store(c, storer); + td::store(*c_in, storer); } template void parse(ParserT &parser) { td::parse(secret_chat_id, parser); - td::parse(c, parser); + td::parse(c_out, parser); } }; @@ -9634,7 +9611,7 @@ void ContactsManager::save_secret_chat(SecretChat *c, SecretChatId secret_chat_i CHECK(c != nullptr); if (!c->is_saved) { if (!from_binlog) { - auto log_event = SecretChatLogEvent(secret_chat_id, *c); + auto log_event = SecretChatLogEvent(secret_chat_id, c); auto storer = get_log_event_storer(log_event); if (c->log_event_id == 0) { c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SecretChatInfos, storer); @@ -9665,8 +9642,8 @@ void ContactsManager::on_binlog_secret_chat_event(BinlogEvent &&event) { } LOG(INFO) << "Add " << secret_chat_id << " from binlog"; - SecretChat *c = add_secret_chat(secret_chat_id); - *c = std::move(log_event.c); // secret chats come from binlog before all other events, so just add them + SecretChat *c = secret_chats_.emplace(secret_chat_id, std::move(log_event.c_out)).first->second.get(); + CHECK(c != nullptr); c->log_event_id = event.id_; diff --git a/td/telegram/DownloadManager.cpp b/td/telegram/DownloadManager.cpp index 202a0272a..ce220a1c8 100644 --- a/td/telegram/DownloadManager.cpp +++ b/td/telegram/DownloadManager.cpp @@ -6,7 +6,6 @@ // #include "td/telegram/DownloadManager.h" -#include "td/telegram/FileReferenceManager.h" #include "td/telegram/files/FileId.hpp" #include "td/telegram/files/FileSourceId.hpp" #include "td/telegram/Global.h" @@ -83,64 +82,43 @@ class DownloadManagerImpl final : public DownloadManager { load_database_files(); } - Status toggle_is_paused(FileId file_id, bool is_paused) final { - TRY_STATUS(check_is_active()); - TRY_RESULT(file_info_ptr, get_file_info(file_id)); + void toggle_is_paused(FileId file_id, bool is_paused, Promise promise) final { + TRY_STATUS_PROMISE(promise, check_is_active()); + TRY_RESULT_PROMISE(promise, file_info_ptr, get_file_info(file_id)); toggle_is_paused(*file_info_ptr, is_paused); - return Status::OK(); + promise.set_value(Unit()); } - Status toggle_all_is_paused(bool is_paused) final { - TRY_STATUS(check_is_active()); + void toggle_all_is_paused(bool is_paused, Promise promise) final { + TRY_STATUS_PROMISE(promise, check_is_active()); + vector to_toggle; for (auto &it : files_) { - toggle_is_paused(*it.second, is_paused); + FileInfo &file_info = *it.second; + if (!is_completed(file_info) && is_paused != file_info.is_paused) { + to_toggle.push_back(file_info.file_id); + } + } + for (auto file_id : to_toggle) { + auto r_file_info_ptr = get_file_info(file_id); + if (r_file_info_ptr.is_ok()) { + toggle_is_paused(*r_file_info_ptr.ok(), is_paused); + } } - return Status::OK(); + promise.set_value(Unit()); } - Status remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) final { - LOG(INFO) << "Remove from downloads file " << file_id << " from " << file_source_id; - TRY_STATUS(check_is_active()); - TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id)); - auto &file_info = *file_info_ptr; - auto download_id = file_info.download_id; - if (!is_completed(file_info) && !file_info.is_paused) { - callback_->pause_file(file_info.internal_file_id); - } - unregister_file_info(file_info); - if (delete_from_cache) { - callback_->delete_file(file_info.internal_file_id); - } - by_internal_file_id_.erase(file_info.internal_file_id); - by_file_id_.erase(file_info.file_id); - hints_.remove(download_id); - completed_download_ids_.erase(download_id); - - remove_from_database(file_info); - files_.erase(download_id); - if (is_search_inited_) { - callback_->update_file_removed(file_id, file_counters_); - } - - update_counters(); - on_file_viewed(download_id); - - return Status::OK(); + void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, Promise promise) final { + promise.set_result(remove_file_impl(file_id, file_source_id, delete_from_cache)); } - Status remove_file_if_finished(FileId file_id) { - TRY_STATUS(check_is_active()); - TRY_RESULT(file_info_ptr, get_file_info(file_id, {})); - if (!is_completed(*file_info_ptr)) { - return Status::Error("File is active"); - } - return remove_file(file_id, {}, false); + void remove_file_if_finished(FileId file_id) final { + remove_file_if_finished_impl(file_id).ignore(); } - Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) final { - TRY_STATUS(check_is_active()); + void remove_all_files(bool only_active, bool only_completed, bool delete_from_cache, Promise promise) final { + TRY_STATUS_PROMISE(promise, check_is_active()); vector to_remove; for (auto &it : files_) { FileInfo &file_info = *it.second; @@ -153,15 +131,16 @@ class DownloadManagerImpl final : public DownloadManager { to_remove.push_back(file_info.file_id); } for (auto file_id : to_remove) { - remove_file(file_id, {}, delete_from_cache); + remove_file_impl(file_id, {}, delete_from_cache); } - return Status::OK(); + promise.set_value(Unit()); } - Status add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority) final { - TRY_STATUS(check_is_active()); + void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority, + Promise> promise) final { + TRY_STATUS_PROMISE(promise, check_is_active()); - remove_file(file_id, {}, false); + remove_file_impl(file_id, {}, false); auto download_id = next_download_id(); @@ -176,19 +155,23 @@ class DownloadManagerImpl final : public DownloadManager { add_file_info(std::move(file_info), search_text); - return Status::OK(); + promise.set_value(callback_->get_file_object(file_id)); } - Status change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) final { + void change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) final { if (!is_search_inited_) { - return Status::OK(); + return; } - TRY_STATUS(check_is_active()); - TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id)); - auto &file_info = *file_info_ptr; + if (check_is_active().is_error()) { + return; + } + auto r_file_info_ptr = get_file_info(file_id, file_source_id); + if (r_file_info_ptr.is_error()) { + return; + } + auto &file_info = *r_file_info_ptr.ok(); hints_.add(file_info.download_id, search_text.empty() ? string(" ") : search_text); - return Status::OK(); } void hints_synchronized(Result) { @@ -328,7 +311,7 @@ class DownloadManagerImpl final : public DownloadManager { return; } auto &file_info = *r_file_info_ptr.ok(); - remove_file(file_info.file_id, {}, false); + remove_file_impl(file_info.file_id, {}, false); } void update_file_viewed(FileId file_id, FileSourceId file_source_id) final { @@ -376,6 +359,7 @@ class DownloadManagerImpl final : public DownloadManager { Counters sent_counters_; FileCounters file_counters_; bool is_inited_{false}; + bool is_database_being_loaded_{false}; bool is_database_loaded_{false}; bool is_search_inited_{false}; int64 max_download_id_{0}; @@ -488,6 +472,8 @@ class DownloadManagerImpl final : public DownloadManager { return; } CHECK(is_inited_); + CHECK(!is_database_being_loaded_); + is_database_being_loaded_ = true; LOG(INFO) << "Start Download Manager database loading"; @@ -503,6 +489,7 @@ class DownloadManagerImpl final : public DownloadManager { } is_database_loaded_ = true; + is_database_being_loaded_ = false; update_counters(); check_completed_downloads_size(); @@ -512,13 +499,13 @@ class DownloadManagerImpl final : public DownloadManager { void prepare_hints() { for (auto &it : files_) { const auto &file_info = *it.second; - send_closure(G()->file_reference_manager(), &FileReferenceManager::get_file_search_text, file_info.file_source_id, - callback_->get_file_view(file_info.file_id).get_unique_file_id(), - [actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(), - download_id = it.first](Result r_search_text) mutable { - send_closure(actor_id, &DownloadManagerImpl::add_download_to_hints, download_id, - std::move(r_search_text), std::move(promise)); - }); + auto promise = + PromiseCreator::lambda([actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(), + download_id = it.first](Result r_search_text) mutable { + send_closure(actor_id, &DownloadManagerImpl::add_download_to_hints, download_id, std::move(r_search_text), + std::move(promise)); + }); + callback_->get_file_search_text(file_info.file_id, file_info.file_source_id, std::move(promise)); } } @@ -530,7 +517,7 @@ class DownloadManagerImpl final : public DownloadManager { if (r_search_text.is_error()) { if (!G()->close_flag()) { - remove_file(it->second->file_id, {}, false); + remove_file_impl(it->second->file_id, {}, false); } } else { auto search_text = r_search_text.move_as_ok(); @@ -567,11 +554,8 @@ class DownloadManagerImpl final : public DownloadManager { << file_info->size << '/' << file_info->expected_size << " with downloaded_size = " << file_info->downloaded_size << " and is_paused = " << file_info->is_paused; - auto res = files_.emplace(download_id, std::move(file_info)); - auto it = res.first; + auto it = files_.emplace(download_id, std::move(file_info)).first; bool was_completed = is_completed(*it->second); - LOG_CHECK(!it->second->is_registered) - << res.second << ' ' << download_id << ' ' << max_download_id_ << ' ' << it->second->need_save_to_database; register_file_info(*it->second); // must be called before start_file, which can call update_file_download_state if (is_completed(*it->second)) { bool is_inserted = completed_download_ids_.insert(it->second->download_id).second; @@ -588,6 +572,45 @@ class DownloadManagerImpl final : public DownloadManager { } } + Status remove_file_impl(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) { + LOG(INFO) << "Remove from downloads file " << file_id << " from " << file_source_id; + TRY_STATUS(check_is_active()); + TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id)); + auto &file_info = *file_info_ptr; + auto download_id = file_info.download_id; + if (!is_completed(file_info) && !file_info.is_paused) { + callback_->pause_file(file_info.internal_file_id); + } + unregister_file_info(file_info); + if (delete_from_cache) { + callback_->delete_file(file_info.internal_file_id); + } + by_internal_file_id_.erase(file_info.internal_file_id); + by_file_id_.erase(file_info.file_id); + hints_.remove(download_id); + completed_download_ids_.erase(download_id); + + remove_from_database(file_info); + files_.erase(download_id); + if (is_search_inited_) { + callback_->update_file_removed(file_id, file_counters_); + } + + update_counters(); + on_file_viewed(download_id); + + return Status::OK(); + } + + Status remove_file_if_finished_impl(FileId file_id) { + TRY_STATUS(check_is_active()); + TRY_RESULT(file_info_ptr, get_file_info(file_id, {})); + if (!is_completed(*file_info_ptr)) { + return Status::Error("File is active"); + } + return remove_file_impl(file_id, {}, false); + } + void timeout_expired() final { clear_counters(); } @@ -756,7 +779,7 @@ class DownloadManagerImpl final : public DownloadManager { while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) { auto download_id = *completed_download_ids_.begin(); auto file_info = get_file_info(download_id).move_as_ok(); - remove_file(file_info->file_id, FileSourceId(), false); + remove_file_impl(file_info->file_id, FileSourceId(), false); } } diff --git a/td/telegram/DownloadManager.h b/td/telegram/DownloadManager.h index aa0790fd9..de2133944 100644 --- a/td/telegram/DownloadManager.h +++ b/td/telegram/DownloadManager.h @@ -73,8 +73,10 @@ class DownloadManager : public Actor { virtual void delete_file(FileId file_id) = 0; virtual FileId dup_file_id(FileId file_id) = 0; - virtual FileView get_file_view(FileId file_id) = 0; + virtual void get_file_search_text(FileId file_id, FileSourceId file_source_id, Promise &&promise) = 0; + virtual FileView get_sync_file_view(FileId file_id) = 0; + virtual td_api::object_ptr get_file_object(FileId file_id) = 0; virtual td_api::object_ptr get_file_download_object(FileId file_id, FileSourceId file_source_id, int32 add_date, int32 complete_date, @@ -86,20 +88,23 @@ class DownloadManager : public Actor { // // public interface for user // - virtual void after_get_difference() = 0; - virtual Status add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority) = 0; - virtual Status change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) = 0; - virtual Status toggle_is_paused(FileId file_id, bool is_paused) = 0; - virtual Status toggle_all_is_paused(bool is_paused) = 0; + virtual void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority, + Promise> promise) = 0; + virtual void toggle_is_paused(FileId file_id, bool is_paused, Promise promise) = 0; + virtual void toggle_all_is_paused(bool is_paused, Promise promise) = 0; virtual void search(string query, bool only_active, bool only_completed, string offset, int32 limit, Promise> promise) = 0; - virtual Status remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) = 0; - virtual Status remove_file_if_finished(FileId file_id) = 0; - virtual Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) = 0; + virtual void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, + Promise promise) = 0; + virtual void remove_all_files(bool only_active, bool only_completed, bool delete_from_cache, + Promise promise) = 0; // // private interface to handle all kinds of updates // + virtual void after_get_difference() = 0; + virtual void change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) = 0; + virtual void remove_file_if_finished(FileId file_id) = 0; virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size, int64 expected_size, bool is_paused) = 0; virtual void update_file_deleted(FileId internal_file_id) = 0; diff --git a/td/telegram/DownloadManagerCallback.cpp b/td/telegram/DownloadManagerCallback.cpp index b41f119c4..8b3622299 100644 --- a/td/telegram/DownloadManagerCallback.cpp +++ b/td/telegram/DownloadManagerCallback.cpp @@ -64,6 +64,12 @@ FileId DownloadManagerCallback::dup_file_id(FileId file_id) { return td_->file_manager_->dup_file_id(file_id); } +void DownloadManagerCallback::get_file_search_text(FileId file_id, FileSourceId file_source_id, + Promise &&promise) { + send_closure(td_->file_reference_manager_actor_, &FileReferenceManager::get_file_search_text, file_source_id, + get_file_view(file_id).get_unique_file_id(), std::move(promise)); +} + FileView DownloadManagerCallback::get_file_view(FileId file_id) { return td_->file_manager_->get_file_view(file_id); } @@ -73,6 +79,10 @@ FileView DownloadManagerCallback::get_sync_file_view(FileId file_id) { return get_file_view(file_id); } +td_api::object_ptr DownloadManagerCallback::get_file_object(FileId file_id) { + return td_->file_manager_->get_file_object(file_id); +} + td_api::object_ptr DownloadManagerCallback::get_file_download_object( FileId file_id, FileSourceId file_source_id, int32 add_date, int32 complete_date, bool is_paused) { return td_api::make_object(td_->file_manager_->get_file_view(file_id).get_main_file_id().get(), diff --git a/td/telegram/DownloadManagerCallback.h b/td/telegram/DownloadManagerCallback.h index 145ae7f92..19da9c842 100644 --- a/td/telegram/DownloadManagerCallback.h +++ b/td/telegram/DownloadManagerCallback.h @@ -45,18 +45,22 @@ class DownloadManagerCallback final : public DownloadManager::Callback { FileId dup_file_id(FileId file_id) final; - FileView get_file_view(FileId file_id) final; + void get_file_search_text(FileId file_id, FileSourceId file_source_id, Promise &&promise) final; FileView get_sync_file_view(FileId file_id) final; + td_api::object_ptr get_file_object(FileId file_id) final; + td_api::object_ptr get_file_download_object(FileId file_id, FileSourceId file_source_id, int32 add_date, int32 complete_date, - bool is_paused); + bool is_paused) final; private: Td *td_; ActorShared<> parent_; + FileView get_file_view(FileId file_id); + static std::shared_ptr make_download_file_callback( Td *td, ActorShared download_manager); }; diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp index eff592aee..28c82b793 100644 --- a/td/telegram/LinkManager.cpp +++ b/td/telegram/LinkManager.cpp @@ -1057,7 +1057,7 @@ unique_ptr LinkManager::parse_tg_link_query(Slice que nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach")); } // resolve?phone=12345 - return user_link; + return std::move(user_link); } } else if (path.size() == 1 && path[0] == "login") { // login?code=123456 @@ -1239,7 +1239,7 @@ unique_ptr LinkManager::parse_t_me_link_query(Slice q nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach")); } // /+ - return user_link; + return std::move(user_link); } else { // /+ return td::make_unique(PSTRING() << "tg:join?invite=" diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index d5532ffc4..3d5fc7f8d 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -51,6 +51,7 @@ #include "td/telegram/NotificationSettingsManager.h" #include "td/telegram/NotificationSound.h" #include "td/telegram/NotificationType.h" +#include "td/telegram/PollId.h" #include "td/telegram/PublicDialogType.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.hpp" @@ -5810,34 +5811,16 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent) } MessagesManager::~MessagesManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_nodes_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_heap_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), being_sent_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_message_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_scheduled_message_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_id_to_dialog_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), last_clear_history_message_id_to_dialog_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialogs_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), postponed_chat_read_inbox_updates_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_public_dialogs_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_on_server_dialogs_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_common_dialogs_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_embedding_codes_[0]); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_embedding_codes_[1]); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), replied_by_media_timestamp_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), notification_group_id_to_dialog_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), active_get_channel_differencies_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), get_channel_difference_to_log_event_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_get_difference_retry_timeouts_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), is_channel_difference_finished_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), resolved_usernames_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), inaccessible_resolved_usernames_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_bot_command_message_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), full_message_id_to_file_source_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), last_outgoing_forwarded_message_date_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_viewed_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_online_member_counts_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), previous_repaired_read_inbox_max_message_id_); + Scheduler::instance()->destroy_on_scheduler( + G()->get_gc_scheduler_id(), ttl_nodes_, ttl_heap_, being_sent_messages_, update_message_ids_, + update_scheduled_message_ids_, message_id_to_dialog_id_, last_clear_history_message_id_to_dialog_id_, dialogs_, + postponed_chat_read_inbox_updates_, found_public_dialogs_, found_on_server_dialogs_, found_common_dialogs_, + message_embedding_codes_[0], message_embedding_codes_[1], replied_by_media_timestamp_messages_, + notification_group_id_to_dialog_id_, active_get_channel_differencies_, get_channel_difference_to_log_event_id_, + channel_get_difference_retry_timeouts_, is_channel_difference_finished_, resolved_usernames_, + inaccessible_resolved_usernames_, dialog_bot_command_message_ids_, full_message_id_to_file_source_id_, + last_outgoing_forwarded_message_date_, dialog_viewed_messages_, dialog_online_member_counts_, + previous_repaired_read_inbox_max_message_id_); } void MessagesManager::on_channel_get_difference_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) { @@ -20806,7 +20789,8 @@ Status MessagesManager::view_messages(DialogId dialog_id, MessageId top_thread_m for (auto file_id : get_message_file_ids(m)) { auto file_view = td_->file_manager_->get_file_view(file_id); CHECK(!file_view.empty()); - td_->download_manager_->update_file_viewed(file_view.get_main_file_id(), file_source_id); + send_closure(td_->download_manager_actor_, &DownloadManager::update_file_viewed, file_view.get_main_file_id(), + file_source_id); } } @@ -22975,7 +22959,7 @@ void MessagesManager::remove_message_file_sources(DialogId dialog_id, const Mess for (auto file_id : file_ids) { auto file_view = td_->file_manager_->get_file_view(file_id); send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(), - file_source_id, false); + file_source_id, false, Promise()); td_->file_manager_->remove_file_source(file_id, file_source_id); } } @@ -23002,7 +22986,7 @@ void MessagesManager::change_message_files(DialogId dialog_id, const Message *m, if (file_source_id.is_valid()) { auto file_view = td_->file_manager_->get_file_view(file_id); send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(), - file_source_id, false); + file_source_id, false, Promise()); } } } @@ -28032,8 +28016,8 @@ class MessagesManager::ForwardMessagesLogEvent { DialogId from_dialog_id; vector message_ids; vector messages_in; - bool drop_author = false; - bool drop_media_captions = false; + bool drop_author; + bool drop_media_captions; vector> messages_out; template @@ -28055,6 +28039,9 @@ class MessagesManager::ForwardMessagesLogEvent { PARSE_FLAG(drop_author); PARSE_FLAG(drop_media_captions); END_PARSE_FLAGS(); + } else { + drop_author = false; + drop_media_captions = false; } td::parse(to_dialog_id, parser); td::parse(from_dialog_id, parser); @@ -28190,6 +28177,9 @@ unique_ptr MessagesManager::create_message_ void MessagesManager::fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message, int64 media_album_id, bool drop_author) const { + if (m->content->get_type() == MessageContentType::Audio) { + drop_author = true; + } bool is_game = m->content->get_type() == MessageContentType::Game; if (!drop_author || is_game) { m->via_bot_user_id = forwarded_message->via_bot_user_id; @@ -28346,9 +28336,20 @@ Result MessagesManager::get_forwarded_messag continue; } + bool is_broken_server_copy = [&] { + switch (forwarded_message->content->get_type()) { + case MessageContentType::Poll: + return get_message_content_poll_is_closed(td_, forwarded_message->content.get()) || + td_->auth_manager_->is_bot(); + case MessageContentType::Dice: + return true; + default: + return false; + } + }(); + bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy; - bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward && - forwarded_message->content->get_type() != MessageContentType::Dice); + bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward && !is_broken_server_copy); if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) { LOG(INFO) << "Forward of " << message_id << " is restricted"; continue; @@ -31044,8 +31045,29 @@ void MessagesManager::check_send_message_result(int64 random_id, DialogId dialog CHECK(source != nullptr); auto sent_messages = UpdatesManager::get_new_messages(updates_ptr); auto sent_messages_random_ids = UpdatesManager::get_sent_messages_random_ids(updates_ptr); + + auto is_invalid_poll_message = [](const telegram_api::Message *message) { + CHECK(message != nullptr); + auto constructor_id = message->get_id(); + if (constructor_id == telegram_api::messageEmpty::ID) { + return true; + } + if (constructor_id != telegram_api::message::ID) { + return false; + } + + auto media = static_cast(message)->media_.get(); + if (media == nullptr || media->get_id() != telegram_api::messageMediaPoll::ID) { + return false; + } + + auto poll = static_cast(media)->poll_.get(); + return !PollId(poll->id_).is_valid(); + }; + if (sent_messages.size() != 1u || sent_messages_random_ids.size() != 1u || - *sent_messages_random_ids.begin() != random_id || get_message_dialog_id(*sent_messages[0]) != dialog_id) { + *sent_messages_random_ids.begin() != random_id || get_message_dialog_id(*sent_messages[0]) != dialog_id || + is_invalid_poll_message(sent_messages[0]->get())) { LOG(ERROR) << "Receive wrong result for sending message with random_id " << random_id << " from " << source << " to " << dialog_id << ": " << oneline(to_string(*updates_ptr)); Dialog *d = get_dialog(dialog_id); @@ -40250,9 +40272,8 @@ void MessagesManager::add_message_file_to_downloads(FullMessageId full_message_i auto search_text = get_message_search_text(m); auto file_source_id = get_message_file_source_id(full_message_id, true); CHECK(file_source_id.is_valid()); - TRY_STATUS_PROMISE(promise, td_->download_manager_->add_file(file_id, file_source_id, std::move(search_text), - static_cast(priority))); - promise.set_value(td_->file_manager_->get_file_object(file_id)); + send_closure(td_->download_manager_actor_, &DownloadManager::add_file, file_id, file_source_id, + std::move(search_text), static_cast(priority), std::move(promise)); } void MessagesManager::get_message_file_search_text(FullMessageId full_message_id, string unique_file_id, diff --git a/td/telegram/PollManager.cpp b/td/telegram/PollManager.cpp index f28b541b1..1a8b3a2e1 100644 --- a/td/telegram/PollManager.cpp +++ b/td/telegram/PollManager.cpp @@ -267,11 +267,8 @@ void PollManager::tear_down() { } PollManager::~PollManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), server_poll_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), other_poll_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), poll_voters_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_polls_); + Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_, server_poll_messages_, + other_poll_messages_, poll_voters_, loaded_from_database_polls_); } void PollManager::on_update_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int) { @@ -1218,11 +1215,26 @@ void PollManager::do_stop_poll(PollId poll_id, FullMessageId full_message_id, un bool is_inserted = being_closed_polls_.insert(poll_id).second; CHECK(is_inserted); - auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise)); + auto new_promise = PromiseCreator::lambda( + [actor_id = actor_id(this), poll_id, log_event_id, promise = std::move(promise)](Result result) mutable { + send_closure(actor_id, &PollManager::on_stop_poll_finished, poll_id, log_event_id, std::move(result), + std::move(promise)); + }); td_->create_handler(std::move(new_promise))->send(full_message_id, std::move(reply_markup), poll_id); } +void PollManager::on_stop_poll_finished(PollId poll_id, uint64 log_event_id, Result &&result, + Promise &&promise) { + being_closed_polls_.erase(poll_id); + + if (log_event_id != 0 && !G()->close_flag()) { + binlog_erase(G()->td_db()->get_binlog(), log_event_id); + } + + promise.set_result(std::move(result)); +} + void PollManager::stop_local_poll(PollId poll_id) { CHECK(is_local_poll_id(poll_id)); auto poll = get_poll_editable(poll_id); diff --git a/td/telegram/PollManager.h b/td/telegram/PollManager.h index b36ef0ea9..2f3fb55f0 100644 --- a/td/telegram/PollManager.h +++ b/td/telegram/PollManager.h @@ -215,6 +215,8 @@ class PollManager final : public Actor { void do_stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr &&reply_markup, uint64 log_event_id, Promise &&promise); + void on_stop_poll_finished(PollId poll_id, uint64 log_event_id, Result &&result, Promise &&promise); + void forget_local_poll(PollId poll_id); MultiTimeout update_poll_timeout_{"UpdatePollTimeout"}; diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 740bf413b..229c99682 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -221,13 +221,14 @@ static KeyboardButton get_keyboard_button(tl_object_ptr(keyboard_button_ptr); - button.type = KeyboardButton::Type::WebView; - button.text = std::move(keyboard_button->text_); auto r_url = LinkManager::check_link(keyboard_button->url_); if (r_url.is_error()) { LOG(ERROR) << "Keyboard Web App " << r_url.error().message(); - return {}; + break; } + + button.type = KeyboardButton::Type::WebView; + button.text = std::move(keyboard_button->text_); button.url = r_url.move_as_ok(); break; } @@ -245,13 +246,13 @@ static InlineKeyboardButton get_inline_keyboard_button( switch (keyboard_button_ptr->get_id()) { case telegram_api::keyboardButtonUrl::ID: { auto keyboard_button = move_tl_object_as(keyboard_button_ptr); - button.type = InlineKeyboardButton::Type::Url; - button.text = std::move(keyboard_button->text_); auto r_url = LinkManager::check_link(keyboard_button->url_); if (r_url.is_error()) { LOG(ERROR) << "Inline keyboard " << r_url.error().message(); - return {}; + break; } + button.type = InlineKeyboardButton::Type::Url; + button.text = std::move(keyboard_button->text_); button.data = r_url.move_as_ok(); break; } @@ -286,38 +287,39 @@ static InlineKeyboardButton get_inline_keyboard_button( } case telegram_api::keyboardButtonUrlAuth::ID: { auto keyboard_button = move_tl_object_as(keyboard_button_ptr); + auto r_url = LinkManager::check_link(keyboard_button->url_); + if (r_url.is_error()) { + LOG(ERROR) << "Inline keyboard Login " << r_url.error().message(); + break; + } button.type = InlineKeyboardButton::Type::UrlAuth; button.id = keyboard_button->button_id_; button.text = std::move(keyboard_button->text_); button.forward_text = std::move(keyboard_button->fwd_text_); - auto r_url = LinkManager::check_link(keyboard_button->url_); - if (r_url.is_error()) { - LOG(ERROR) << "Inline keyboard Login " << r_url.error().message(); - return {}; - } button.data = r_url.move_as_ok(); break; } case telegram_api::keyboardButtonUserProfile::ID: { auto keyboard_button = move_tl_object_as(keyboard_button_ptr); + auto user_id = UserId(keyboard_button->user_id_); + if (!user_id.is_valid()) { + LOG(ERROR) << "Receive " << user_id << " in inline keyboard"; + break; + } button.type = InlineKeyboardButton::Type::User; button.text = std::move(keyboard_button->text_); - button.user_id = UserId(keyboard_button->user_id_); - if (!button.user_id.is_valid()) { - LOG(ERROR) << "Receive " << button.user_id << " in inline keyboard"; - return {}; - } + button.user_id = user_id; break; } case telegram_api::keyboardButtonWebView::ID: { auto keyboard_button = move_tl_object_as(keyboard_button_ptr); - button.type = InlineKeyboardButton::Type::WebView; - button.text = std::move(keyboard_button->text_); auto r_url = LinkManager::check_link(keyboard_button->url_); if (r_url.is_error()) { LOG(ERROR) << "Inline keyboard Web App " << r_url.error().message(); - return {}; + break; } + button.type = InlineKeyboardButton::Type::WebView; + button.text = std::move(keyboard_button->text_); button.data = r_url.move_as_ok(); break; } diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index a42542441..234ac78d1 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -1305,18 +1305,10 @@ StickersManager::StickersManager(Td *td, ActorShared<> parent) : td_(td), parent } StickersManager::~StickersManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), stickers_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), sticker_sets_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), short_name_to_sticker_set_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), attached_sticker_sets_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_stickers_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_sticker_sets_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_codes_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_code_versions_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_code_last_difference_times_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), reloaded_emoji_keywords_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dice_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_messages_); + Scheduler::instance()->destroy_on_scheduler( + G()->get_gc_scheduler_id(), stickers_, sticker_sets_, short_name_to_sticker_set_id_, attached_sticker_sets_, + found_stickers_, found_sticker_sets_, emoji_language_codes_, emoji_language_code_versions_, + emoji_language_code_last_difference_times_, reloaded_emoji_keywords_, dice_messages_, emoji_messages_); } void StickersManager::start_up() { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 47e05887b..34073f4d0 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4003,6 +4003,10 @@ void Td::init_file_manager() { explicit FileManagerContext(Td *td) : td_(td) { } + bool need_notify_on_new_files() final { + return !td_->auth_manager_->is_bot(); + } + void on_new_file(int64 size, int64 real_size, int32 cnt) final { send_closure(G()->storage_manager(), &StorageManager::on_new_file, size, real_size, cnt); } @@ -4894,6 +4898,7 @@ void Td::on_request(uint64 id, td_api::getStorageStatistics &request) { } void Td::on_request(uint64 id, td_api::getStorageStatisticsFast &request) { + CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { if (result.is_error()) { @@ -6691,23 +6696,26 @@ void Td::on_request(uint64 id, const td_api::addFileToDownloads &request) { void Td::on_request(uint64 id, const td_api::toggleDownloadIsPaused &request) { CREATE_OK_REQUEST_PROMISE(); - promise.set_result(download_manager_->toggle_is_paused(FileId(request.file_id_, 0), request.is_paused_)); + send_closure(download_manager_actor_, &DownloadManager::toggle_is_paused, FileId(request.file_id_, 0), + request.is_paused_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::toggleAllDownloadsArePaused &request) { CREATE_OK_REQUEST_PROMISE(); - promise.set_result(download_manager_->toggle_all_is_paused(request.are_paused_)); + send_closure(download_manager_actor_, &DownloadManager::toggle_all_is_paused, request.are_paused_, + std::move(promise)); } void Td::on_request(uint64 id, const td_api::removeFileFromDownloads &request) { CREATE_OK_REQUEST_PROMISE(); - promise.set_result(download_manager_->remove_file(FileId(request.file_id_, 0), {}, request.delete_from_cache_)); + send_closure(download_manager_actor_, &DownloadManager::remove_file, FileId(request.file_id_, 0), FileSourceId(), + request.delete_from_cache_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::removeAllFilesFromDownloads &request) { CREATE_OK_REQUEST_PROMISE(); - promise.set_result( - download_manager_->remove_all_files(request.only_active_, request.only_completed_, request.delete_from_cache_)); + send_closure(download_manager_actor_, &DownloadManager::remove_all_files, request.only_active_, + request.only_completed_, request.delete_from_cache_, std::move(promise)); } void Td::on_request(uint64 id, td_api::searchFileDownloads &request) { diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index b0f1f28e0..a15f1ecae 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1617,7 +1617,7 @@ void UpdatesManager::after_get_difference() { } } - td_->download_manager_->after_get_difference(); + send_closure(td_->download_manager_actor_, &DownloadManager::after_get_difference); td_->inline_queries_manager_->after_get_difference(); td_->messages_manager_->after_get_difference(); send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference); diff --git a/td/telegram/VoiceNotesManager.cpp b/td/telegram/VoiceNotesManager.cpp index 593e0b3e0..fddd8dd00 100644 --- a/td/telegram/VoiceNotesManager.cpp +++ b/td/telegram/VoiceNotesManager.cpp @@ -101,9 +101,8 @@ VoiceNotesManager::VoiceNotesManager(Td *td, ActorShared<> parent) : td_(td), pa } VoiceNotesManager::~VoiceNotesManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_note_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_voice_notes_); + Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_, voice_note_messages_, + message_voice_notes_); } void VoiceNotesManager::tear_down() { diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index fb30753c1..312d6cd4d 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -418,11 +418,8 @@ void WebPagesManager::tear_down() { } WebPagesManager::~WebPagesManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_page_messages_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), got_web_page_previews_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), url_to_web_page_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), url_to_file_source_id_); + Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_, web_page_messages_, + got_web_page_previews_, url_to_web_page_id_, url_to_file_source_id_); } WebPageId WebPagesManager::on_get_web_page(tl_object_ptr &&web_page_ptr, diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 309b57535..acbc0f152 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -841,14 +841,9 @@ void FileManager::init_actor() { } FileManager::~FileManager() { - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_hash_to_file_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), local_location_to_file_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), generate_location_to_file_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), pmc_id_to_file_node_id_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_id_info_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), empty_file_ids_); - Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_nodes_); + Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_, file_hash_to_file_id_, + local_location_to_file_id_, generate_location_to_file_id_, + pmc_id_to_file_node_id_, file_id_info_, empty_file_ids_, file_nodes_); } string FileManager::fix_file_extension(Slice file_name, Slice file_type, Slice file_extension) { @@ -2163,7 +2158,9 @@ void FileManager::delete_file(FileId file_id, Promise promise, const char if (file_view.has_local_location()) { if (begins_with(file_view.local_location().path_, get_files_dir(file_view.get_type()))) { clear_from_pmc(node); - context_->on_new_file(-file_view.size(), -file_view.get_allocated_local_size(), -1); + if (context_->need_notify_on_new_files()) { + context_->on_new_file(-file_view.size(), -file_view.get_allocated_local_size(), -1); + } path = std::move(node->local_.full().path_); } } else { @@ -3517,7 +3514,7 @@ void FileManager::on_download_ok(QueryId query_id, FullLocalFileLocation local, if (r_new_file_id.is_error()) { status = Status::Error(PSLICE() << "Can't register local file after download: " << r_new_file_id.error().message()); } else { - if (is_new) { + if (is_new && context_->need_notify_on_new_files()) { context_->on_new_file(size, get_file_view(r_new_file_id.ok()).get_allocated_local_size(), 1); } auto r_file_id = merge(r_new_file_id.ok(), file_id); @@ -3690,8 +3687,10 @@ void FileManager::on_generate_ok(QueryId query_id, FullLocalFileLocation local) CHECK(file_node); FileView file_view(file_node); - if (!file_view.has_generate_location() || !begins_with(file_view.generate_location().conversion_, "#file_id#")) { - context_->on_new_file(file_view.size(), file_view.get_allocated_local_size(), 1); + if (context_->need_notify_on_new_files()) { + if (!file_view.has_generate_location() || !begins_with(file_view.generate_location().conversion_, "#file_id#")) { + context_->on_new_file(file_view.size(), file_view.get_allocated_local_size(), 1); + } } run_upload(file_node, {}); diff --git a/td/telegram/files/FileManager.h b/td/telegram/files/FileManager.h index 2d651a544..3549b66f5 100644 --- a/td/telegram/files/FileManager.h +++ b/td/telegram/files/FileManager.h @@ -384,6 +384,8 @@ class FileManager final : public FileLoadManager::Callback { class Context { public: + virtual bool need_notify_on_new_files() = 0; + virtual void on_new_file(int64 size, int64 real_size, int32 cnt) = 0; virtual void on_file_updated(FileId size) = 0; diff --git a/tdactor/td/actor/impl/Scheduler-decl.h b/tdactor/td/actor/impl/Scheduler-decl.h index 57f49dbb4..a8ec2aaa9 100644 --- a/tdactor/td/actor/impl/Scheduler-decl.h +++ b/tdactor/td/actor/impl/Scheduler-decl.h @@ -105,6 +105,9 @@ class Scheduler { template void destroy_on_scheduler(int32 sched_id, T &value); + template + void destroy_on_scheduler(int32 sched_id, ArgsT &...values); + template void send_lambda(ActorRef actor_ref, EventT &&lambda); diff --git a/tdactor/td/actor/impl/Scheduler.h b/tdactor/td/actor/impl/Scheduler.h index 182066145..74910ff53 100644 --- a/tdactor/td/actor/impl/Scheduler.h +++ b/tdactor/td/actor/impl/Scheduler.h @@ -171,7 +171,7 @@ inline void Scheduler::send_to_scheduler(int32 sched_id, const ActorId &a } template -inline void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) { +void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) { if (!value.empty()) { destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([value = std::move(value)](Unit) { // destroy value @@ -179,6 +179,13 @@ inline void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) { } } +template +void Scheduler::destroy_on_scheduler(int32 sched_id, ArgsT &...values) { + destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([values = std::make_tuple(std::move(values)...)](Unit) { + // destroy values + })); +} + inline void Scheduler::before_tail_send(const ActorId<> &actor_id) { // TODO } diff --git a/tdactor/test/actors_main.cpp b/tdactor/test/actors_main.cpp index 2e795d40a..4bb9ac54b 100644 --- a/tdactor/test/actors_main.cpp +++ b/tdactor/test/actors_main.cpp @@ -253,7 +253,7 @@ class MainQueryActor final : public td::Actor { } void wakeup() final { - int cnt = 100000; + int cnt = 10000; while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) { if (td::Random::fast_bool()) { send_closure(rand_elem(actors_), &QueryActor::query, create_query()); @@ -294,7 +294,7 @@ class SimpleActor final : public td::Actor { } void wakeup() final { - if (q_ == 100000) { + if (q_ == 10000) { td::Scheduler::instance()->finish(); stop(); return; diff --git a/tdactor/test/actors_workers.cpp b/tdactor/test/actors_workers.cpp index 47b560113..748edd4e8 100644 --- a/tdactor/test/actors_workers.cpp +++ b/tdactor/test/actors_workers.cpp @@ -138,13 +138,13 @@ TEST(Actors, workers_big_query_nine_threads) { } TEST(Actors, workers_small_query_one_thread) { - test_workers(0, 10, 1000000, 1); + test_workers(0, 10, 100000, 1); } TEST(Actors, workers_small_query_two_threads) { - test_workers(2, 10, 1000000, 1); + test_workers(2, 10, 100000, 1); } TEST(Actors, workers_small_query_nine_threads) { - test_workers(9, 10, 1000000, 1); + test_workers(9, 10, 10000, 1); } diff --git a/tdutils/td/utils/FlatHashMapChunks.h b/tdutils/td/utils/FlatHashMapChunks.h index 81a2c4819..70fc36bac 100644 --- a/tdutils/td/utils/FlatHashMapChunks.h +++ b/tdutils/td/utils/FlatHashMapChunks.h @@ -469,7 +469,8 @@ class FlatHashTableChunks { struct ChunkIt { size_t chunk_i; size_t chunk_mask; - size_t shift{}; + size_t shift; + size_t pos() const { return chunk_i; } @@ -482,7 +483,7 @@ class FlatHashTableChunks { }; ChunkIt get_chunk_it(size_t chunk_i) { - return {chunk_i, chunks_.size() - 1}; + return ChunkIt{chunk_i, chunks_.size() - 1, 0}; } HashInfo calc_hash(const KeyT &key) { diff --git a/tdutils/td/utils/FlatHashTable.h b/tdutils/td/utils/FlatHashTable.h index 2048ea05d..079b3ede6 100644 --- a/tdutils/td/utils/FlatHashTable.h +++ b/tdutils/td/utils/FlatHashTable.h @@ -198,13 +198,8 @@ class FlatHashTable { }; FlatHashTable() = default; - FlatHashTable(const FlatHashTable &other) { - assign(other); - } - void operator=(const FlatHashTable &other) { - clear(); - assign(other); - } + FlatHashTable(const FlatHashTable &other) = delete; + FlatHashTable &operator=(const FlatHashTable &other) = delete; FlatHashTable(std::initializer_list nodes) { if (nodes.size() == 0) { @@ -249,9 +244,7 @@ class FlatHashTable { other.drop(); } ~FlatHashTable() { - if (nodes_ != nullptr) { - clear_nodes(nodes_); - } + clear_nodes(nodes_); } void swap(FlatHashTable &other) noexcept { @@ -433,30 +426,6 @@ class FlatHashTable { begin_bucket_ = 0; } - void assign(const FlatHashTable &other) { - if (other.size() == 0) { - return; - } - resize(other.bucket_count()); - auto other_nodes_end = other.nodes_ + other.bucket_count_; - for (const NodeT *other_node = other.nodes_; other_node != other_nodes_end; ++other_node) { - if (other_node->empty()) { - continue; - } - - auto bucket = calc_bucket(other_node->key()); - while (true) { - auto &node = nodes_[bucket]; - if (node.empty()) { - node.copy_from(*other_node); - break; - } - next_bucket(bucket); - } - } - used_node_count_ = other.used_node_count_; - } - NodeT *begin_impl() { if (empty()) { return nullptr; diff --git a/tdutils/td/utils/MapNode.h b/tdutils/td/utils/MapNode.h index 25cc84448..cad2ae9b3 100644 --- a/tdutils/td/utils/MapNode.h +++ b/tdutils/td/utils/MapNode.h @@ -54,7 +54,7 @@ struct MapNode { DCHECK(empty()); DCHECK(!other.empty()); first = std::move(other.first); - other.first = KeyT{}; + other.first = KeyT(); new (&second) ValueT(std::move(other.second)); other.second.~ValueT(); } diff --git a/tdutils/td/utils/SetNode.h b/tdutils/td/utils/SetNode.h index 7e99cb1fb..6d7b6e5ff 100644 --- a/tdutils/td/utils/SetNode.h +++ b/tdutils/td/utils/SetNode.h @@ -20,7 +20,7 @@ struct SetNode { using public_type = const KeyT; using second_type = KeyT; // TODO: remove second_type? - KeyT first{}; + KeyT first; const KeyT &key() const { return first; @@ -30,7 +30,8 @@ struct SetNode { return first; } - SetNode() = default; + SetNode(): first() { + } explicit SetNode(KeyT key) : first(std::move(key)) { } SetNode(const SetNode &other) = delete; @@ -42,7 +43,7 @@ struct SetNode { DCHECK(empty()); DCHECK(!other.empty()); first = std::move(other.first); - other.first = KeyT{}; + other.first = KeyT(); } ~SetNode() = default; @@ -71,7 +72,7 @@ struct SetNode 28 * sizeof(void struct Impl { using second_type = KeyT; - KeyT first{}; + KeyT first; template explicit Impl(InputKeyT &&key) : first(std::forward(key)) { @@ -99,7 +100,7 @@ struct SetNode 28 * sizeof(void return impl_->first; } - SetNode() { + SetNode(): impl_() { } explicit SetNode(KeyT key) : impl_(td::make_unique(std::move(key))) { } diff --git a/tdutils/test/HashSet.cpp b/tdutils/test/HashSet.cpp index 507960c4b..07bc1ce81 100644 --- a/tdutils/test/HashSet.cpp +++ b/tdutils/test/HashSet.cpp @@ -124,7 +124,6 @@ TEST(FlatHashMap, basic) { ASSERT_EQ(2, kv.second); } map.erase(map.find(1)); - auto map_copy = map; } td::FlatHashMap, 10>> x; @@ -159,9 +158,6 @@ TEST(FlatHashMap, basic) { } ASSERT_EQ(data, extract_kv(kv)); - KV copied_kv(kv); - ASSERT_EQ(data, extract_kv(copied_kv)); - KV moved_kv(std::move(kv)); ASSERT_EQ(data, extract_kv(moved_kv)); ASSERT_EQ(Data{}, extract_kv(kv)); @@ -169,10 +165,6 @@ TEST(FlatHashMap, basic) { kv = std::move(moved_kv); ASSERT_EQ(data, extract_kv(kv)); - KV assign_copied_kv; - assign_copied_kv = kv; - ASSERT_EQ(data, extract_kv(assign_copied_kv)); - KV assign_moved_kv; assign_moved_kv = std::move(kv); ASSERT_EQ(data, extract_kv(assign_moved_kv)); diff --git a/test/db.cpp b/test/db.cpp index 7dd80fbe0..b51a8cf20 100644 --- a/test/db.cpp +++ b/test/db.cpp @@ -377,7 +377,7 @@ TEST(DB, key_value) { values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10))); } - int queries_n = 3000; + int queries_n = 1000; td::vector queries(queries_n); for (auto &q : queries) { int op = td::Random::fast(0, 2); @@ -427,7 +427,7 @@ TEST(DB, key_value) { ASSERT_EQ(a.value, c.value); ASSERT_EQ(a.value, d.value); ASSERT_EQ(a.value, e.value); - if (cnt++ % 500 == 0) { + if (cnt++ % 200 == 0) { new_kv.impl().init(new_kv_name.str()).ensure(); } }